Merge "HDMI: Avoid NPE on Hotplug In" into main
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index 904109b..705a4df 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -26,7 +26,9 @@
     ":android.os.flags-aconfig-java{.generated_srcjars}",
     ":android.os.vibrator.flags-aconfig-java{.generated_srcjars}",
     ":android.security.flags-aconfig-java{.generated_srcjars}",
+    ":android.server.app.flags-aconfig-java{.generated_srcjars}",
     ":android.service.chooser.flags-aconfig-java{.generated_srcjars}",
+    ":android.service.dreams.flags-aconfig-java{.generated_srcjars}",
     ":android.service.notification.flags-aconfig-java{.generated_srcjars}",
     ":android.view.flags-aconfig-java{.generated_srcjars}",
     ":android.view.accessibility.flags-aconfig-java{.generated_srcjars}",
@@ -231,7 +233,6 @@
     name: "android.security.flags-aconfig-java-host",
     aconfig_declarations: "android.security.flags-aconfig",
     host_supported: true,
-    mode: "test",
     defaults: ["framework-minus-apex-aconfig-java-defaults"],
 }
 
@@ -658,7 +659,13 @@
     defaults: ["framework-minus-apex-aconfig-java-defaults"],
 }
 
-// CoreNetworking
+// Networking
+aconfig_declarations {
+    name: "com.android.net.flags-aconfig",
+    package: "com.android.net.flags",
+    srcs: ["core/java/android/net/flags.aconfig"],
+}
+
 java_aconfig_library {
     name: "com.android.net.flags-aconfig-java",
     aconfig_declarations: "com.android.net.flags-aconfig",
@@ -742,6 +749,19 @@
     defaults: ["framework-minus-apex-aconfig-java-defaults"],
 }
 
+// Dreams
+aconfig_declarations {
+    name: "android.service.dreams.flags-aconfig",
+    package: "android.service.dreams",
+    srcs: ["core/java/android/service/dreams/flags.aconfig"],
+}
+
+java_aconfig_library {
+    name: "android.service.dreams.flags-aconfig-java",
+    aconfig_declarations: "android.service.dreams.flags-aconfig",
+    defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
+
 // Notifications
 aconfig_declarations {
     name: "android.service.notification.flags-aconfig",
@@ -834,6 +854,19 @@
     defaults: ["framework-minus-apex-aconfig-java-defaults"],
 }
 
+// App
+aconfig_declarations {
+    name: "android.server.app.flags-aconfig",
+    package: "android.server.app",
+    srcs: ["services/core/java/com/android/server/app/flags.aconfig"],
+}
+
+java_aconfig_library {
+    name: "android.server.app.flags-aconfig-java",
+    aconfig_declarations: "android.server.app.flags-aconfig",
+    defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
+
 // WebView
 aconfig_declarations {
     name: "android.webkit.flags-aconfig",
diff --git a/Android.bp b/Android.bp
index fa7c97d..96d26cf 100644
--- a/Android.bp
+++ b/Android.bp
@@ -106,7 +106,7 @@
         ":android.hardware.radio.voice-V3-java-source",
         ":android.hardware.security.keymint-V3-java-source",
         ":android.hardware.security.secureclock-V1-java-source",
-        ":android.hardware.thermal-V1-java-source",
+        ":android.hardware.thermal-V2-java-source",
         ":android.hardware.tv.tuner-V2-java-source",
         ":android.security.apc-java-source",
         ":android.security.authorization-java-source",
@@ -210,6 +210,7 @@
         "apex_aidl_interface-java",
         "packagemanager_aidl-java",
         "framework-protos",
+        "libtombstone_proto_java",
         "updatable-driver-protos",
         "ota_metadata_proto_java",
         "android.hidl.base-V1.0-java",
diff --git a/OWNERS b/OWNERS
index 023bdef..733157f 100644
--- a/OWNERS
+++ b/OWNERS
@@ -37,3 +37,5 @@
 
 per-file *ravenwood* = file:ravenwood/OWNERS
 per-file *Ravenwood* = file:ravenwood/OWNERS
+
+per-file PERFORMANCE_OWNERS = file:/PERFORMANCE_OWNERS
diff --git a/PERFORMANCE_OWNERS b/PERFORMANCE_OWNERS
index 9452ea3..48a0201 100644
--- a/PERFORMANCE_OWNERS
+++ b/PERFORMANCE_OWNERS
@@ -3,3 +3,6 @@
 dualli@google.com
 carmenjackson@google.com
 philipcuadra@google.com
+shayba@google.com
+jdduke@google.com
+shombert@google.com
diff --git a/ProtoLibraries.bp b/ProtoLibraries.bp
index e7adf20..d03bbd2 100644
--- a/ProtoLibraries.bp
+++ b/ProtoLibraries.bp
@@ -34,7 +34,6 @@
         ":ipconnectivity-proto-src",
         ":libstats_atom_enum_protos",
         ":libstats_atom_message_protos",
-        ":libtombstone_proto-src",
         "core/proto/**/*.proto",
         "libs/incident/**/*.proto",
     ],
diff --git a/STABILITY_OWNERS b/STABILITY_OWNERS
new file mode 100644
index 0000000..a7ecb4d
--- /dev/null
+++ b/STABILITY_OWNERS
@@ -0,0 +1,2 @@
+gaillard@google.com
+
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 3409838..117faa2 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -126,6 +126,12 @@
           "exclude-annotation": "org.junit.Ignore"
         }
       ]
+    },
+    {
+      "name": "vts_treble_vintf_framework_test"
+    },
+    {
+      "name": "vts_treble_vintf_vendor_test"
     }
   ],
   "postsubmit-ravenwood": [
diff --git a/apct-tests/perftests/core/src/android/permission/AppOpsPerfTest.kt b/apct-tests/perftests/core/src/android/permission/AppOpsPerfTest.kt
new file mode 100644
index 0000000..2af878e
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/permission/AppOpsPerfTest.kt
@@ -0,0 +1,75 @@
+/*
+ * 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.permission
+
+import android.app.AppOpsManager
+import android.content.Context
+import androidx.benchmark.BenchmarkState
+import androidx.benchmark.junit4.BenchmarkRule
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.filters.LargeTest
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+
+@LargeTest
+/**
+ * Performance unit tests for app ops APIs.
+ *
+ * The APIs under test are used for checking permissions and tracking permission accesses and are
+ * therefore invoked frequently by the system for all permission-protected data accesses, hence
+ * these APIs should be monitored closely for performance.
+ */
+class AppOpsPerfTest {
+    @get:Rule val mBenchmarkRule: BenchmarkRule = BenchmarkRule()
+    private lateinit var appOpsManager: AppOpsManager
+    private lateinit var opPackageName: String
+    private var opPackageUid: Int = 0
+
+    @Before
+    fun setUp() {
+        val context: Context = ApplicationProvider.getApplicationContext()
+        appOpsManager = context.getSystemService<AppOpsManager>(AppOpsManager::class.java)!!
+        opPackageName = context.getOpPackageName()
+        opPackageUid = context.getPackageManager().getPackageUid(opPackageName, 0)
+    }
+
+    @Test
+    fun testNoteOp() {
+        val state: BenchmarkState = mBenchmarkRule.getState()
+        while (state.keepRunning()) {
+            appOpsManager.noteOp(
+                    AppOpsManager.OPSTR_FINE_LOCATION,
+                    opPackageUid,
+                    opPackageName,
+                    null,
+                    null
+            )
+        }
+    }
+
+    @Test
+    fun testUnsafeCheckOp() {
+        val state: BenchmarkState = mBenchmarkRule.getState()
+        while (state.keepRunning()) {
+            appOpsManager.unsafeCheckOp(
+                    AppOpsManager.OPSTR_FINE_LOCATION,
+                    opPackageUid,
+                    opPackageName
+            )
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/permission/OWNERS b/apct-tests/perftests/core/src/android/permission/OWNERS
new file mode 100644
index 0000000..b4b2b9e
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/permission/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 137825
+
+include platform/frameworks/base:/core/java/android/permission/OWNERS
\ No newline at end of file
diff --git a/apct-tests/perftests/packagemanager/src/android/os/PackageParsingPerfTest.kt b/apct-tests/perftests/packagemanager/src/android/os/PackageParsingPerfTest.kt
index 6d1e6d0..4352c8a 100644
--- a/apct-tests/perftests/packagemanager/src/android/os/PackageParsingPerfTest.kt
+++ b/apct-tests/perftests/packagemanager/src/android/os/PackageParsingPerfTest.kt
@@ -24,10 +24,11 @@
 import android.content.res.TypedArray
 import android.perftests.utils.BenchmarkState
 import android.perftests.utils.PerfStatusReporter
+import android.util.ArraySet
 import androidx.test.filters.LargeTest
+import com.android.internal.pm.parsing.pkg.PackageImpl
+import com.android.internal.pm.pkg.parsing.ParsingPackageUtils
 import com.android.internal.util.ConcurrentUtils
-import com.android.server.pm.parsing.pkg.PackageImpl
-import com.android.server.pm.pkg.parsing.ParsingPackageUtils
 import java.io.File
 import java.io.FileOutputStream
 import java.util.concurrent.ArrayBlockingQueue
@@ -214,7 +215,10 @@
                     path,
                     manifestArray,
                     isCoreApp,
+                    this,
                 )
+                override fun getHiddenApiWhitelistedApps() = ArraySet<String>()
+                override fun getInstallConstraintsAllowlist() = ArraySet<String>()
             })
 
         override fun parseImpl(file: File) =
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
index 4bc7313..324d8ca 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
@@ -288,12 +288,16 @@
     public static final int PRIORITY_HIGH = 400;
 
     /**
-     * This task should be run ahead of all other tasks. Only Expedited Jobs
-     * {@link Builder#setExpedited(boolean)} can have this priority and as such,
-     * are subject to the same execution time details noted in
-     * {@link Builder#setExpedited(boolean)}.
-     * A sample task of max priority: receiving a text message and processing it to
-     * show a notification
+     * This task is critical to user experience or functionality
+     * and should be run ahead of all other tasks. Only
+     * {@link Builder#setExpedited(boolean) expedited jobs} and
+     * {@link Builder#setUserInitiated(boolean) user-initiated jobs} can have this priority.
+     * <p>
+     * Example tasks of max priority:
+     * <ul>
+     *     <li>Receiving a text message and processing it to show a notification</li>
+     *     <li>Downloading or uploading some content the user requested to transfer immediately</li>
+     * </ul>
      */
     public static final int PRIORITY_MAX = 500;
 
@@ -1969,6 +1973,9 @@
          * </ol>
          *
          * <p>
+         * Expedited jobs are given {@link #PRIORITY_MAX} by default.
+         *
+         * <p>
          * Since these jobs have stronger guarantees than regular jobs, they will be subject to
          * stricter quotas. As long as an app has available expedited quota, jobs scheduled with
          * this set to true will run with these guarantees. If an app has run out of available
@@ -2059,6 +2066,7 @@
          * <p>
          * These jobs will not be subject to quotas and will be started immediately once scheduled
          * if all constraints are met and the device system health allows for additional tasks.
+         * They are also given {@link #PRIORITY_MAX} by default, and the priority cannot be changed.
          *
          * @see JobInfo#isUserInitiated()
          */
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
index 4aadc90..e3ba50d 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
@@ -26,6 +26,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.os.SystemClock;
 import android.os.UserHandle;
@@ -98,7 +99,10 @@
             switch (action) {
                 case Intent.ACTION_PACKAGE_RESTARTED: {
                     synchronized (mLock) {
-                        mPackageStoppedState.add(pkgUid, pkgName, Boolean.TRUE);
+                        // ACTION_PACKAGE_RESTARTED doesn't always mean the app is placed and kept
+                        // in the stopped state, so don't put TRUE in the cache. Remove any existing
+                        // entry and rely on an explicit call to PackageManager's isStopped() API.
+                        mPackageStoppedState.delete(pkgUid, pkgName);
                         updateJobRestrictionsForUidLocked(pkgUid, false);
                     }
                 }
@@ -126,6 +130,7 @@
     }
 
     @Override
+    @GuardedBy("mLock")
     public void startTrackingLocked() {
         mAppStateTracker.addListener(mForceAppStandbyListener);
         final IntentFilter filter = new IntentFilter();
@@ -137,15 +142,18 @@
     }
 
     @Override
+    @GuardedBy("mLock")
     public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
         updateSingleJobRestrictionLocked(jobStatus, sElapsedRealtimeClock.millis(), UNKNOWN);
     }
 
     @Override
+    @GuardedBy("mLock")
     public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob) {
     }
 
     @Override
+    @GuardedBy("mLock")
     public void evaluateStateLocked(JobStatus jobStatus) {
         if (jobStatus.isRequestedExpeditedJob()) {
             // Only requested-EJs could have their run-in-bg constraint change outside of something
@@ -155,11 +163,13 @@
     }
 
     @Override
+    @GuardedBy("mLock")
     public void onAppRemovedLocked(String packageName, int uid) {
         mPackageStoppedState.delete(uid, packageName);
     }
 
     @Override
+    @GuardedBy("mLock")
     public void onUserRemovedLocked(int userId) {
         for (int u = mPackageStoppedState.numMaps() - 1; u >= 0; --u) {
             final int uid = mPackageStoppedState.keyAt(u);
@@ -170,6 +180,7 @@
     }
 
     @Override
+    @GuardedBy("mLock")
     public void dumpControllerStateLocked(final IndentingPrintWriter pw,
             final Predicate<JobStatus> predicate) {
         pw.println("Aconfig flags:");
@@ -223,6 +234,7 @@
     }
 
     @Override
+    @GuardedBy("mLock")
     public void dumpControllerStateLocked(ProtoOutputStream proto, long fieldId,
             Predicate<JobStatus> predicate) {
         final long token = proto.start(fieldId);
@@ -260,14 +272,17 @@
         proto.end(token);
     }
 
+    @GuardedBy("mLock")
     private void updateAllJobRestrictionsLocked() {
         updateJobRestrictionsLocked(/*filterUid=*/ -1, UNKNOWN);
     }
 
+    @GuardedBy("mLock")
     private void updateJobRestrictionsForUidLocked(int uid, boolean isActive) {
         updateJobRestrictionsLocked(uid, (isActive) ? KNOWN_ACTIVE : KNOWN_INACTIVE);
     }
 
+    @GuardedBy("mLock")
     private void updateJobRestrictionsLocked(int filterUid, int newActiveState) {
         mUpdateJobFunctor.prepare(newActiveState);
 
@@ -295,28 +310,36 @@
         }
     }
 
-    private boolean isPackageStopped(String packageName, int uid) {
+    @GuardedBy("mLock")
+    private boolean isPackageStoppedLocked(String packageName, int uid) {
         if (mPackageStoppedState.contains(uid, packageName)) {
             return mPackageStoppedState.get(uid, packageName);
         }
-        final boolean isStopped = mPackageManagerInternal.isPackageStopped(packageName, uid);
-        mPackageStoppedState.add(uid, packageName, isStopped);
-        return isStopped;
+
+        try {
+            final boolean isStopped = mPackageManagerInternal.isPackageStopped(packageName, uid);
+            mPackageStoppedState.add(uid, packageName, isStopped);
+            return isStopped;
+        } catch (PackageManager.NameNotFoundException e) {
+            Slog.e(TAG, "Couldn't determine stopped state for unknown package: " + packageName);
+            return false;
+        }
     }
 
+    @GuardedBy("mLock")
     boolean updateSingleJobRestrictionLocked(JobStatus jobStatus, final long nowElapsed,
             int activeState) {
         final int uid = jobStatus.getSourceUid();
         final String packageName = jobStatus.getSourcePackageName();
 
         final boolean isSourcePkgStopped =
-                isPackageStopped(jobStatus.getSourcePackageName(), jobStatus.getSourceUid());
+                isPackageStoppedLocked(jobStatus.getSourcePackageName(), jobStatus.getSourceUid());
         final boolean isCallingPkgStopped;
         if (!jobStatus.isProxyJob()) {
             isCallingPkgStopped = isSourcePkgStopped;
         } else {
             isCallingPkgStopped =
-                    isPackageStopped(jobStatus.getCallingPackageName(), jobStatus.getUid());
+                    isPackageStoppedLocked(jobStatus.getCallingPackageName(), jobStatus.getUid());
         }
         final boolean isStopped = android.content.pm.Flags.stayStopped()
                 && (isCallingPkgStopped || isSourcePkgStopped);
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
index e06006f..f405083 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
@@ -1769,7 +1769,8 @@
 
     @VisibleForTesting
     class CcConfig {
-        private boolean mFlexIsEnabled = FlexibilityController.FcConfig.DEFAULT_FLEXIBILITY_ENABLED;
+        private boolean mFlexIsEnabled =
+                FlexibilityController.FcConfig.DEFAULT_APPLIED_CONSTRAINTS != 0;
         private boolean mShouldReprocessNetworkCapabilities = false;
 
         /**
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java
index 13a474cc..0e67b9a 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java
@@ -24,7 +24,6 @@
 import static com.android.server.job.controllers.JobStatus.CONSTRAINT_BATTERY_NOT_LOW;
 import static com.android.server.job.controllers.JobStatus.CONSTRAINT_CHARGING;
 import static com.android.server.job.controllers.JobStatus.CONSTRAINT_CONNECTIVITY;
-import static com.android.server.job.controllers.JobStatus.CONSTRAINT_FLEXIBLE;
 import static com.android.server.job.controllers.JobStatus.CONSTRAINT_IDLE;
 
 import android.annotation.ElapsedRealtimeLong;
@@ -74,17 +73,10 @@
     private static final int JOB_SPECIFIC_FLEXIBLE_CONSTRAINTS = CONSTRAINT_CONNECTIVITY;
 
     /** List of all flexible constraints. */
-    private static final int FLEXIBLE_CONSTRAINTS =
+    @VisibleForTesting
+    static final int FLEXIBLE_CONSTRAINTS =
             JOB_SPECIFIC_FLEXIBLE_CONSTRAINTS | SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS;
 
-    private static final int NUM_JOB_SPECIFIC_FLEXIBLE_CONSTRAINTS =
-            Integer.bitCount(JOB_SPECIFIC_FLEXIBLE_CONSTRAINTS);
-
-    static final int NUM_SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS =
-            Integer.bitCount(SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS);
-
-    static final int NUM_FLEXIBLE_CONSTRAINTS = Integer.bitCount(FLEXIBLE_CONSTRAINTS);
-
     private static final long NO_LIFECYCLE_END = Long.MAX_VALUE;
 
     /**
@@ -100,9 +92,15 @@
     private long mUnseenConstraintGracePeriodMs =
             FcConfig.DEFAULT_UNSEEN_CONSTRAINT_GRACE_PERIOD_MS;
 
-    @VisibleForTesting
+    /** Set of constraints supported on this device for flex scheduling. */
+    private final int mSupportedFlexConstraints;
+
     @GuardedBy("mLock")
-    boolean mFlexibilityEnabled = FcConfig.DEFAULT_FLEXIBILITY_ENABLED;
+    private boolean mFlexibilityEnabled;
+
+    /** Set of constraints that will be used in the flex policy. */
+    @GuardedBy("mLock")
+    private int mAppliedConstraints = FcConfig.DEFAULT_APPLIED_CONSTRAINTS;
 
     private long mMinTimeBetweenFlexibilityAlarmsMs =
             FcConfig.DEFAULT_MIN_TIME_BETWEEN_FLEXIBILITY_ALARMS_MS;
@@ -118,9 +116,6 @@
      */
     private int[] mPercentToDropConstraints;
 
-    @VisibleForTesting
-    boolean mDeviceSupportsFlexConstraints;
-
     /**
      * Keeps track of what flexible constraints are satisfied at the moment.
      * Is updated by the other controllers.
@@ -178,7 +173,7 @@
                             if (!js.hasFlexibilityConstraint()) {
                                 continue;
                             }
-                            mFlexibilityTracker.resetJobNumDroppedConstraints(js, nowElapsed);
+                            mFlexibilityTracker.calculateNumDroppedConstraints(js, nowElapsed);
                             mFlexibilityAlarmQueue.scheduleDropNumConstraintsAlarm(js, nowElapsed);
                         }
                     }
@@ -186,15 +181,23 @@
             };
 
     private static final int MSG_UPDATE_JOBS = 0;
+    private static final int MSG_UPDATE_JOB = 1;
 
     public FlexibilityController(
             JobSchedulerService service, PrefetchController prefetchController) {
         super(service);
         mHandler = new FcHandler(AppSchedulingModuleThread.get().getLooper());
-        mDeviceSupportsFlexConstraints = !mContext.getPackageManager().hasSystemFeature(
-                PackageManager.FEATURE_AUTOMOTIVE);
-        mFlexibilityEnabled &= mDeviceSupportsFlexConstraints;
-        mFlexibilityTracker = new FlexibilityTracker(NUM_FLEXIBLE_CONSTRAINTS);
+        if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)
+                || mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_EMBEDDED)) {
+            // Embedded devices have no user-installable apps. Assume all jobs are critical
+            // and can't be flexed.
+            mSupportedFlexConstraints = 0;
+        } else {
+            // TODO(236261941): handle devices without a battery
+            mSupportedFlexConstraints = FLEXIBLE_CONSTRAINTS;
+        }
+        mFlexibilityEnabled = (mAppliedConstraints & mSupportedFlexConstraints) != 0;
+        mFlexibilityTracker = new FlexibilityTracker(Integer.bitCount(mSupportedFlexConstraints));
         mFcConfig = new FcConfig();
         mFlexibilityAlarmQueue = new FlexibilityAlarmQueue(
                 mContext, AppSchedulingModuleThread.get().getLooper());
@@ -218,10 +221,12 @@
     public void maybeStartTrackingJobLocked(JobStatus js, JobStatus lastJob) {
         if (js.hasFlexibilityConstraint()) {
             final long nowElapsed = sElapsedRealtimeClock.millis();
-            if (!mDeviceSupportsFlexConstraints) {
+            if (mSupportedFlexConstraints == 0) {
                 js.setFlexibilityConstraintSatisfied(nowElapsed, true);
                 return;
             }
+            js.setNumAppliedFlexibleConstraints(
+                    Integer.bitCount(getRelevantAppliedConstraintsLocked(js)));
             js.setFlexibilityConstraintSatisfied(nowElapsed, isFlexibilitySatisfiedLocked(js));
             mFlexibilityTracker.add(js);
             js.setTrackingController(JobStatus.TRACKING_FLEXIBILITY);
@@ -266,6 +271,14 @@
                 || mService.isCurrentlyRunningLocked(js);
     }
 
+    @VisibleForTesting
+    @GuardedBy("mLock")
+    int getRelevantAppliedConstraintsLocked(@NonNull JobStatus js) {
+        final int relevantConstraints = SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS
+                | (js.canApplyTransportAffinities() ? CONSTRAINT_CONNECTIVITY : 0);
+        return mAppliedConstraints & relevantConstraints;
+    }
+
     /**
      * Returns whether there are enough constraints satisfied to allow running the job from flex's
      * perspective. This takes into account unseen constraint combinations and expectations around
@@ -274,7 +287,7 @@
     @VisibleForTesting
     @GuardedBy("mLock")
     boolean hasEnoughSatisfiedConstraintsLocked(@NonNull JobStatus js) {
-        final int satisfiedConstraints = mSatisfiedFlexibleConstraints
+        final int satisfiedConstraints = mSatisfiedFlexibleConstraints & mAppliedConstraints
                 & (SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS
                         | (js.areTransportAffinitiesSatisfied() ? CONSTRAINT_CONNECTIVITY : 0));
         final int numSatisfied = Integer.bitCount(satisfiedConstraints);
@@ -296,8 +309,7 @@
         // count have not been seen recently enough, then assume they won't be seen anytime soon,
         // so don't force the job to wait longer. If any combinations with a higher count have been
         // seen recently, then the job can potentially wait for those combinations.
-        final int irrelevantConstraints = ~(SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS
-                | (js.canApplyTransportAffinities() ? CONSTRAINT_CONNECTIVITY : 0));
+        final int irrelevantConstraints = ~getRelevantAppliedConstraintsLocked(js);
         for (int i = mLastSeenConstraintTimesElapsed.size() - 1; i >= 0; --i) {
             final int constraints = mLastSeenConstraintTimesElapsed.keyAt(i);
             if ((constraints & irrelevantConstraints) != 0) {
@@ -515,9 +527,9 @@
                     for (int j = 0; j < mFlexibilityTracker.size(); j++) {
                         final ArraySet<JobStatus> jobs = mFlexibilityTracker
                                 .getJobsByNumRequiredConstraints(j);
-                        for (int i = 0; i < jobs.size(); i++) {
+                        for (int i = jobs.size() - 1; i >= 0; --i) {
                             JobStatus js = jobs.valueAt(i);
-                            mFlexibilityTracker.resetJobNumDroppedConstraints(js, nowElapsed);
+                            mFlexibilityTracker.updateFlexibleConstraints(js, nowElapsed);
                             mFlexibilityAlarmQueue.scheduleDropNumConstraintsAlarm(js, nowElapsed);
                             if (js.setFlexibilityConstraintSatisfied(
                                     nowElapsed, isFlexibilitySatisfiedLocked(js))) {
@@ -579,18 +591,46 @@
             mTrackedJobs.get(js.getNumRequiredFlexibleConstraints()).remove(js);
         }
 
-        public void resetJobNumDroppedConstraints(JobStatus js, long nowElapsed) {
+        /**
+         * Updates applied and dropped constraints for the job.
+         */
+        public void updateFlexibleConstraints(JobStatus js, long nowElapsed) {
+            final int prevNumRequired = js.getNumRequiredFlexibleConstraints();
+
+            final int numAppliedConstraints =
+                    Integer.bitCount(getRelevantAppliedConstraintsLocked(js));
+            js.setNumAppliedFlexibleConstraints(numAppliedConstraints);
+
             final int curPercent = getCurPercentOfLifecycleLocked(js, nowElapsed);
             int toDrop = 0;
-            final int jsMaxFlexibleConstraints = NUM_SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS
-                    + (js.canApplyTransportAffinities() ? 1 : 0);
+            for (int i = 0; i < numAppliedConstraints; i++) {
+                if (curPercent >= mPercentToDropConstraints[i]) {
+                    toDrop++;
+                }
+            }
+            js.setNumDroppedFlexibleConstraints(toDrop);
+
+            if (prevNumRequired == js.getNumRequiredFlexibleConstraints()) {
+                return;
+            }
+            mTrackedJobs.get(prevNumRequired).remove(js);
+            add(js);
+        }
+
+        /**
+         * Calculates the number of constraints that should be dropped for the job, based on how
+         * far along the job is into its lifecycle.
+         */
+        public void calculateNumDroppedConstraints(JobStatus js, long nowElapsed) {
+            final int curPercent = getCurPercentOfLifecycleLocked(js, nowElapsed);
+            int toDrop = 0;
+            final int jsMaxFlexibleConstraints = js.getNumAppliedFlexibleConstraints();
             for (int i = 0; i < jsMaxFlexibleConstraints; i++) {
                 if (curPercent >= mPercentToDropConstraints[i]) {
                     toDrop++;
                 }
             }
-            adjustJobsRequiredConstraints(
-                    js, js.getNumDroppedFlexibleConstraints() - toDrop, nowElapsed);
+            setNumDroppedFlexibleConstraints(js, toDrop);
         }
 
         /** Returns all tracked jobs. */
@@ -599,17 +639,14 @@
         }
 
         /**
-         * Adjusts number of required flexible constraints and sorts it into the tracker.
-         * Returns false if the job status's number of flexible constraints is now 0.
+         * Updates the number of dropped flexible constraints and sorts it into the tracker.
          */
-        public boolean adjustJobsRequiredConstraints(JobStatus js, int adjustBy, long nowElapsed) {
-            if (adjustBy != 0) {
+        public void setNumDroppedFlexibleConstraints(JobStatus js, int numDropped) {
+            if (numDropped != js.getNumDroppedFlexibleConstraints()) {
                 remove(js);
-                js.adjustNumRequiredFlexibleConstraints(adjustBy);
-                js.setFlexibilityConstraintSatisfied(nowElapsed, isFlexibilitySatisfiedLocked(js));
+                js.setNumDroppedFlexibleConstraints(numDropped);
                 add(js);
             }
-            return js.getNumRequiredFlexibleConstraints() > 0;
         }
 
         public int size() {
@@ -658,8 +695,10 @@
                 if (DEBUG) {
                     Slog.d(TAG, "scheduleDropNumConstraintsAlarm: "
                             + js.getSourcePackageName() + " " + js.getSourceUserId()
+                            + " numApplied: " + js.getNumAppliedFlexibleConstraints()
                             + " numRequired: " + js.getNumRequiredFlexibleConstraints()
-                            + " numSatisfied: " + Integer.bitCount(mSatisfiedFlexibleConstraints)
+                            + " numSatisfied: " + Integer.bitCount(
+                            mSatisfiedFlexibleConstraints & getRelevantAppliedConstraintsLocked(js))
                             + " curTime: " + nowElapsed
                             + " earliest: " + earliest
                             + " latest: " + latest
@@ -669,8 +708,9 @@
                     if (DEBUG) {
                         Slog.d(TAG, "deadline proximity met: " + js);
                     }
-                    mFlexibilityTracker.adjustJobsRequiredConstraints(js,
-                            -js.getNumRequiredFlexibleConstraints(), nowElapsed);
+                    mFlexibilityTracker.setNumDroppedFlexibleConstraints(js,
+                            js.getNumAppliedFlexibleConstraints());
+                    mHandler.obtainMessage(MSG_UPDATE_JOB, js).sendToTarget();
                     return;
                 }
                 if (nextTimeElapsed == NO_LIFECYCLE_END) {
@@ -696,12 +736,15 @@
                 final long nowElapsed = sElapsedRealtimeClock.millis();
                 for (int i = 0; i < expired.size(); i++) {
                     JobStatus js = expired.valueAt(i);
-                    boolean wasFlexibilitySatisfied = js.isConstraintSatisfied(CONSTRAINT_FLEXIBLE);
-
-                    if (mFlexibilityTracker.adjustJobsRequiredConstraints(js, -1, nowElapsed)) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "Alarm fired for " + js.toShortString());
+                    }
+                    mFlexibilityTracker.calculateNumDroppedConstraints(js, nowElapsed);
+                    if (js.getNumRequiredFlexibleConstraints() > 0) {
                         scheduleDropNumConstraintsAlarm(js, nowElapsed);
                     }
-                    if (wasFlexibilitySatisfied != js.isConstraintSatisfied(CONSTRAINT_FLEXIBLE)) {
+                    if (js.setFlexibilityConstraintSatisfied(nowElapsed,
+                            isFlexibilitySatisfiedLocked(js))) {
                         changedJobs.add(js);
                     }
                 }
@@ -725,7 +768,9 @@
                         final long nowElapsed = sElapsedRealtimeClock.millis();
                         final ArraySet<JobStatus> changedJobs = new ArraySet<>();
 
-                        for (int o = 0; o <= NUM_SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS; ++o) {
+                        final int numAppliedSystemWideConstraints = Integer.bitCount(
+                                mAppliedConstraints & SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS);
+                        for (int o = 0; o <= numAppliedSystemWideConstraints; ++o) {
                             final ArraySet<JobStatus> jobsByNumConstraints = mFlexibilityTracker
                                     .getJobsByNumRequiredConstraints(o);
 
@@ -744,6 +789,23 @@
                         }
                     }
                     break;
+
+                case MSG_UPDATE_JOB:
+                    synchronized (mLock) {
+                        final JobStatus js = (JobStatus) msg.obj;
+                        if (DEBUG) {
+                            Slog.d("blah", "Checking on " + js.toShortString());
+                        }
+                        final long nowElapsed = sElapsedRealtimeClock.millis();
+                        if (js.setFlexibilityConstraintSatisfied(
+                                nowElapsed, isFlexibilitySatisfiedLocked(js))) {
+                            // TODO(141645789): add method that will take a single job
+                            ArraySet<JobStatus> changedJob = new ArraySet<>();
+                            changedJob.add(js);
+                            mStateChangedListener.onControllerStateChanged(changedJob);
+                        }
+                    }
+                    break;
             }
         }
     }
@@ -754,7 +816,8 @@
         /** Prefix to use with all constant keys in order to "sub-namespace" the keys. */
         private static final String FC_CONFIG_PREFIX = "fc_";
 
-        static final String KEY_FLEXIBILITY_ENABLED = FC_CONFIG_PREFIX + "enable_flexibility";
+        @VisibleForTesting
+        static final String KEY_APPLIED_CONSTRAINTS = FC_CONFIG_PREFIX + "applied_constraints";
         static final String KEY_DEADLINE_PROXIMITY_LIMIT =
                 FC_CONFIG_PREFIX + "flexibility_deadline_proximity_limit_ms";
         static final String KEY_FALLBACK_FLEXIBILITY_DEADLINE =
@@ -770,7 +833,7 @@
         static final String KEY_UNSEEN_CONSTRAINT_GRACE_PERIOD_MS =
                 FC_CONFIG_PREFIX + "unseen_constraint_grace_period_ms";
 
-        static final boolean DEFAULT_FLEXIBILITY_ENABLED = false;
+        static final int DEFAULT_APPLIED_CONSTRAINTS = 0;
         @VisibleForTesting
         static final long DEFAULT_DEADLINE_PROXIMITY_LIMIT_MS = 15 * MINUTE_IN_MILLIS;
         @VisibleForTesting
@@ -783,11 +846,8 @@
         @VisibleForTesting
         static final long DEFAULT_UNSEEN_CONSTRAINT_GRACE_PERIOD_MS = 3 * DAY_IN_MILLIS;
 
-        /**
-         * If false the controller will not track new jobs
-         * and the flexibility constraint will always be satisfied.
-         */
-        public boolean FLEXIBILITY_ENABLED = DEFAULT_FLEXIBILITY_ENABLED;
+        /** Which constraints to apply/consider in flex policy. */
+        public int APPLIED_CONSTRAINTS = DEFAULT_APPLIED_CONSTRAINTS;
         /** How close to a jobs' deadline all flexible constraints will be dropped. */
         public long DEADLINE_PROXIMITY_LIMIT_MS = DEFAULT_DEADLINE_PROXIMITY_LIMIT_MS;
         /** For jobs that lack a deadline, the time that will be used to drop all constraints by. */
@@ -811,16 +871,19 @@
         public void processConstantLocked(@NonNull DeviceConfig.Properties properties,
                 @NonNull String key) {
             switch (key) {
-                case KEY_FLEXIBILITY_ENABLED:
-                    FLEXIBILITY_ENABLED = properties.getBoolean(key, DEFAULT_FLEXIBILITY_ENABLED)
-                            && mDeviceSupportsFlexConstraints;
-                    if (mFlexibilityEnabled != FLEXIBILITY_ENABLED) {
-                        mFlexibilityEnabled = FLEXIBILITY_ENABLED;
+                case KEY_APPLIED_CONSTRAINTS:
+                    APPLIED_CONSTRAINTS =
+                            properties.getInt(key, DEFAULT_APPLIED_CONSTRAINTS)
+                                    & mSupportedFlexConstraints;
+                    if (mAppliedConstraints != APPLIED_CONSTRAINTS) {
+                        mAppliedConstraints = APPLIED_CONSTRAINTS;
                         mShouldReevaluateConstraints = true;
-                        if (mFlexibilityEnabled) {
+                        if (mAppliedConstraints != 0) {
+                            mFlexibilityEnabled = true;
                             mPrefetchController
                                     .registerPrefetchChangedListener(mPrefetchChangedListener);
                         } else {
+                            mFlexibilityEnabled = false;
                             mPrefetchController
                                     .unRegisterPrefetchChangedListener(mPrefetchChangedListener);
                         }
@@ -893,7 +956,7 @@
 
         private int[] parsePercentToDropString(String s) {
             String[] dropPercentString = s.split(",");
-            int[] dropPercentInt = new int[NUM_FLEXIBLE_CONSTRAINTS];
+            int[] dropPercentInt = new int[Integer.bitCount(FLEXIBLE_CONSTRAINTS)];
             if (dropPercentInt.length != dropPercentString.length) {
                 return DEFAULT_PERCENT_TO_DROP_FLEXIBLE_CONSTRAINTS;
             }
@@ -922,7 +985,7 @@
             pw.println(":");
             pw.increaseIndent();
 
-            pw.print(KEY_FLEXIBILITY_ENABLED, FLEXIBILITY_ENABLED).println();
+            pw.print(KEY_APPLIED_CONSTRAINTS, APPLIED_CONSTRAINTS).println();
             pw.print(KEY_DEADLINE_PROXIMITY_LIMIT, DEADLINE_PROXIMITY_LIMIT_MS).println();
             pw.print(KEY_FALLBACK_FLEXIBILITY_DEADLINE, FALLBACK_FLEXIBILITY_DEADLINE_MS).println();
             pw.print(KEY_MIN_TIME_BETWEEN_FLEXIBILITY_ALARMS_MS,
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 d1f575e..0d5d11e 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
@@ -24,7 +24,6 @@
 import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX;
 import static com.android.server.job.JobSchedulerService.WORKING_INDEX;
 import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
-import static com.android.server.job.controllers.FlexibilityController.NUM_SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS;
 import static com.android.server.job.controllers.FlexibilityController.SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS;
 
 import android.annotation.ElapsedRealtimeLong;
@@ -155,7 +154,7 @@
     /**
      * Keeps track of how many flexible constraints must be satisfied for the job to execute.
      */
-    private final int mNumRequiredFlexibleConstraints;
+    private int mNumAppliedFlexibleConstraints;
 
     /**
      * Number of required flexible constraints that have been dropped.
@@ -697,11 +696,7 @@
                 && satisfiesMinWindowException
                 && (numFailures + numSystemStops) != 1
                 && lacksSomeFlexibleConstraints) {
-            mNumRequiredFlexibleConstraints =
-                    NUM_SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS + (mCanApplyTransportAffinities ? 1 : 0);
             requiredConstraints |= CONSTRAINT_FLEXIBLE;
-        } else {
-            mNumRequiredFlexibleConstraints = 0;
         }
 
         this.requiredConstraints = requiredConstraints;
@@ -1527,9 +1522,14 @@
         return (requiredConstraints & CONSTRAINT_FLEXIBLE) != 0;
     }
 
+    /** Returns the number of flexible job constraints being applied to the job. */
+    public int getNumAppliedFlexibleConstraints() {
+        return mNumAppliedFlexibleConstraints;
+    }
+
     /** Returns the number of flexible job constraints required to be satisfied to execute */
     public int getNumRequiredFlexibleConstraints() {
-        return mNumRequiredFlexibleConstraints - mNumDroppedFlexibleConstraints;
+        return mNumAppliedFlexibleConstraints - mNumDroppedFlexibleConstraints;
     }
 
     /**
@@ -2112,9 +2112,14 @@
     }
 
     /** Adjusts the number of required flexible constraints by the given number */
-    public void adjustNumRequiredFlexibleConstraints(int adjustment) {
-        mNumDroppedFlexibleConstraints = Math.max(0, Math.min(mNumRequiredFlexibleConstraints,
-                mNumDroppedFlexibleConstraints - adjustment));
+    public void setNumAppliedFlexibleConstraints(int count) {
+        mNumAppliedFlexibleConstraints = count;
+    }
+
+    /** Sets the number of dropped flexible constraints to the given number */
+    public void setNumDroppedFlexibleConstraints(int count) {
+        mNumDroppedFlexibleConstraints = Math.max(0,
+                Math.min(mNumAppliedFlexibleConstraints, count));
     }
 
     /**
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
index 1c29982..8ddbf69 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
@@ -36,6 +36,7 @@
 import android.app.ActivityManager;
 import android.app.AlarmManager;
 import android.app.UidObserver;
+import android.app.job.JobInfo;
 import android.app.usage.UsageEvents;
 import android.app.usage.UsageStatsManagerInternal;
 import android.app.usage.UsageStatsManagerInternal.UsageEventListener;
@@ -772,18 +773,23 @@
         if (!jobStatus.shouldTreatAsExpeditedJob()) {
             // If quota is currently "free", then the job can run for the full amount of time,
             // regardless of bucket (hence using charging instead of isQuotaFreeLocked()).
-            if (mService.isBatteryCharging()
-                    // The top and foreground cases here were added because apps in those states
-                    // aren't really restricted and the work could be something the user is
-                    // waiting for. Now that user-initiated jobs are a defined concept, we may
-                    // not need these exemptions as much. However, UIJs are currently limited
-                    // (as of UDC) to data transfer work. There may be other work that could
-                    // rely on this exception. Once we add more UIJ types, we can re-evaluate
-                    // the need for these exceptions.
-                    // TODO: re-evaluate the need for these exceptions
-                    || mTopAppCache.get(jobStatus.getSourceUid())
+            if (mService.isBatteryCharging()) {
+                return mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS;
+            }
+            // The top and foreground cases here were added because apps in those states
+            // aren't really restricted and the work could be something the user is
+            // waiting for. Now that user-initiated jobs are a defined concept, we may
+            // not need these exemptions as much. However, UIJs are currently limited
+            // (as of UDC) to data transfer work. There may be other work that could
+            // rely on this exception. Once we add more UIJ types, we can re-evaluate
+            // the need for these exceptions.
+            // TODO: re-evaluate the need for these exceptions
+            final boolean isInPrivilegedState = mTopAppCache.get(jobStatus.getSourceUid())
                     || isTopStartedJobLocked(jobStatus)
-                    || isUidInForeground(jobStatus.getSourceUid())) {
+                    || isUidInForeground(jobStatus.getSourceUid());
+            final boolean isJobImportant = jobStatus.getEffectivePriority() >= JobInfo.PRIORITY_HIGH
+                    || (jobStatus.getFlags() & JobInfo.FLAG_IMPORTANT_WHILE_FOREGROUND) != 0;
+            if (isInPrivilegedState && isJobImportant) {
                 return mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS;
             }
             return getTimeUntilQuotaConsumedLocked(
@@ -2549,7 +2555,25 @@
          */
         @Override
         public void onUsageEvent(int userId, @NonNull UsageEvents.Event event) {
-            mHandler.obtainMessage(MSG_PROCESS_USAGE_EVENT, userId, 0, event).sendToTarget();
+            // Skip posting a message to the handler for events we don't care about.
+            switch (event.getEventType()) {
+                case UsageEvents.Event.ACTIVITY_RESUMED:
+                case UsageEvents.Event.ACTIVITY_PAUSED:
+                case UsageEvents.Event.ACTIVITY_STOPPED:
+                case UsageEvents.Event.ACTIVITY_DESTROYED:
+                case UsageEvents.Event.USER_INTERACTION:
+                case UsageEvents.Event.CHOOSER_ACTION:
+                case UsageEvents.Event.NOTIFICATION_INTERRUPTION:
+                case UsageEvents.Event.NOTIFICATION_SEEN:
+                    mHandler.obtainMessage(MSG_PROCESS_USAGE_EVENT, userId, 0, event)
+                            .sendToTarget();
+                    break;
+                default:
+                    if (DEBUG) {
+                        Slog.d(TAG, "Dropping event " + event.getEventType());
+                    }
+                    break;
+            }
         }
     }
 
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
index b8397d2..357e1396 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
@@ -316,8 +316,25 @@
                  */
                 @Override
                 public void onUsageEvent(int userId, @NonNull UsageEvents.Event event) {
-                    mHandler.obtainMessage(MSG_PROCESS_USAGE_EVENT, userId, 0, event)
-                            .sendToTarget();
+                    // Skip posting a message to the handler for events we don't care about.
+                    switch (event.getEventType()) {
+                        case UsageEvents.Event.ACTIVITY_RESUMED:
+                        case UsageEvents.Event.ACTIVITY_PAUSED:
+                        case UsageEvents.Event.ACTIVITY_STOPPED:
+                        case UsageEvents.Event.ACTIVITY_DESTROYED:
+                        case UsageEvents.Event.USER_INTERACTION:
+                        case UsageEvents.Event.CHOOSER_ACTION:
+                        case UsageEvents.Event.NOTIFICATION_INTERRUPTION:
+                        case UsageEvents.Event.NOTIFICATION_SEEN:
+                            mHandler.obtainMessage(MSG_PROCESS_USAGE_EVENT, userId, 0, event)
+                                    .sendToTarget();
+                            break;
+                        default:
+                            if (DEBUG) {
+                                Slog.d(TAG, "Dropping event " + event.getEventType());
+                            }
+                            break;
+                    }
                 }
             };
 
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
index 12f455a..bd5c006 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
@@ -2258,7 +2258,8 @@
             }
             synchronized (mSystemExemptionAppOpMode) {
                 if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
-                    mSystemExemptionAppOpMode.delete(UserHandle.getUid(userId, getAppId(pkgName)));
+                    final int uid = intent.getIntExtra(Intent.EXTRA_UID, Process.INVALID_UID);
+                    mSystemExemptionAppOpMode.delete(uid);
                 }
             }
 
diff --git a/api/Android.bp b/api/Android.bp
index 2b1cfcb..9029d25 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -31,12 +31,10 @@
         "blueprint",
         "soong",
         "soong-android",
-        "soong-bp2build",
         "soong-genrule",
         "soong-java",
     ],
     srcs: ["api.go"],
-    testSrcs: ["api_test.go"],
     pluginFor: ["soong_build"],
 }
 
diff --git a/api/api.go b/api/api.go
index 71b1e10..2668999 100644
--- a/api/api.go
+++ b/api/api.go
@@ -22,7 +22,6 @@
 	"github.com/google/blueprint/proptools"
 
 	"android/soong/android"
-	"android/soong/bazel"
 	"android/soong/genrule"
 	"android/soong/java"
 )
@@ -65,7 +64,6 @@
 
 type CombinedApis struct {
 	android.ModuleBase
-	android.BazelModuleBase
 
 	properties CombinedApisProperties
 }
@@ -115,20 +113,6 @@
 	Previous_api        *string
 }
 
-type Bazel_module struct {
-	Label              *string
-	Bp2build_available *bool
-}
-type bazelProperties struct {
-	*Bazel_module
-}
-
-var bp2buildNotAvailable = bazelProperties{
-	&Bazel_module{
-		Bp2build_available: proptools.BoolPtr(false),
-	},
-}
-
 // Struct to pass parameters for the various merged [current|removed].txt file modules we create.
 type MergedTxtDefinition struct {
 	// "current.txt" or "removed.txt"
@@ -143,8 +127,6 @@
 	ModuleTag string
 	// public, system, module-lib or system-server
 	Scope string
-	// True if there is a bp2build definition for this module
-	Bp2buildDefined bool
 }
 
 func createMergedTxt(ctx android.LoadHookContext, txt MergedTxtDefinition) {
@@ -178,20 +160,7 @@
 		},
 	}
 	props.Visibility = []string{"//visibility:public"}
-	bazelProps := bazelProperties{
-		&Bazel_module{
-			Bp2build_available: proptools.BoolPtr(false),
-		},
-	}
-	if txt.Bp2buildDefined {
-		moduleDir := ctx.ModuleDir()
-		if moduleDir == android.Bp2BuildTopLevel {
-			moduleDir = ""
-		}
-		label := fmt.Sprintf("//%s:%s", moduleDir, moduleName)
-		bazelProps.Label = &label
-	}
-	ctx.CreateModule(genrule.GenRuleFactory, &props, &bazelProps)
+	ctx.CreateModule(genrule.GenRuleFactory, &props)
 }
 
 func createMergedAnnotationsFilegroups(ctx android.LoadHookContext, modules, system_server_modules []string) {
@@ -221,7 +190,7 @@
 		props := fgProps{}
 		props.Name = proptools.StringPtr(i.name)
 		props.Srcs = createSrcs(i.modules, i.tag)
-		ctx.CreateModule(android.FileGroupFactory, &props, &bp2buildNotAvailable)
+		ctx.CreateModule(android.FileGroupFactory, &props)
 	}
 }
 
@@ -315,7 +284,7 @@
 	props.Name = proptools.StringPtr("all-modules-public-stubs-source")
 	props.Srcs = createSrcs(modules, "{.public.stubs.source}")
 	props.Visibility = []string{"//frameworks/base"}
-	ctx.CreateModule(android.FileGroupFactory, &props, &bp2buildNotAvailable)
+	ctx.CreateModule(android.FileGroupFactory, &props)
 }
 
 func createMergedTxts(ctx android.LoadHookContext, bootclasspath, system_server_classpath []string) {
@@ -323,43 +292,38 @@
 
 	tagSuffix := []string{".api.txt}", ".removed-api.txt}"}
 	distFilename := []string{"android.txt", "android-removed.txt"}
-	bp2BuildDefined := []bool{true, false}
 	for i, f := range []string{"current.txt", "removed.txt"} {
 		textFiles = append(textFiles, MergedTxtDefinition{
-			TxtFilename:     f,
-			DistFilename:    distFilename[i],
-			BaseTxt:         ":non-updatable-" + f,
-			Modules:         bootclasspath,
-			ModuleTag:       "{.public" + tagSuffix[i],
-			Scope:           "public",
-			Bp2buildDefined: bp2BuildDefined[i],
+			TxtFilename:  f,
+			DistFilename: distFilename[i],
+			BaseTxt:      ":non-updatable-" + f,
+			Modules:      bootclasspath,
+			ModuleTag:    "{.public" + tagSuffix[i],
+			Scope:        "public",
 		})
 		textFiles = append(textFiles, MergedTxtDefinition{
-			TxtFilename:     f,
-			DistFilename:    distFilename[i],
-			BaseTxt:         ":non-updatable-system-" + f,
-			Modules:         bootclasspath,
-			ModuleTag:       "{.system" + tagSuffix[i],
-			Scope:           "system",
-			Bp2buildDefined: bp2BuildDefined[i],
+			TxtFilename:  f,
+			DistFilename: distFilename[i],
+			BaseTxt:      ":non-updatable-system-" + f,
+			Modules:      bootclasspath,
+			ModuleTag:    "{.system" + tagSuffix[i],
+			Scope:        "system",
 		})
 		textFiles = append(textFiles, MergedTxtDefinition{
-			TxtFilename:     f,
-			DistFilename:    distFilename[i],
-			BaseTxt:         ":non-updatable-module-lib-" + f,
-			Modules:         bootclasspath,
-			ModuleTag:       "{.module-lib" + tagSuffix[i],
-			Scope:           "module-lib",
-			Bp2buildDefined: bp2BuildDefined[i],
+			TxtFilename:  f,
+			DistFilename: distFilename[i],
+			BaseTxt:      ":non-updatable-module-lib-" + f,
+			Modules:      bootclasspath,
+			ModuleTag:    "{.module-lib" + tagSuffix[i],
+			Scope:        "module-lib",
 		})
 		textFiles = append(textFiles, MergedTxtDefinition{
-			TxtFilename:     f,
-			DistFilename:    distFilename[i],
-			BaseTxt:         ":non-updatable-system-server-" + f,
-			Modules:         system_server_classpath,
-			ModuleTag:       "{.system-server" + tagSuffix[i],
-			Scope:           "system-server",
-			Bp2buildDefined: bp2BuildDefined[i],
+			TxtFilename:  f,
+			DistFilename: distFilename[i],
+			BaseTxt:      ":non-updatable-system-server-" + f,
+			Modules:      system_server_classpath,
+			ModuleTag:    "{.system-server" + tagSuffix[i],
+			Scope:        "system-server",
 		})
 	}
 	for _, txt := range textFiles {
@@ -446,55 +410,9 @@
 	module.AddProperties(&module.properties)
 	android.InitAndroidModule(module)
 	android.AddLoadHook(module, func(ctx android.LoadHookContext) { module.createInternalModules(ctx) })
-	android.InitBazelModule(module)
 	return module
 }
 
-type bazelCombinedApisAttributes struct {
-	Scope bazel.StringAttribute
-	Base  bazel.LabelAttribute
-	Deps  bazel.LabelListAttribute
-}
-
-// combined_apis bp2build converter
-func (a *CombinedApis) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
-	basePrefix := "non-updatable"
-	scopeToSuffix := map[string]string{
-		"public":        "-current.txt",
-		"system":        "-system-current.txt",
-		"module-lib":    "-module-lib-current.txt",
-		"system-server": "-system-server-current.txt",
-	}
-
-	for scopeName, suffix := range scopeToSuffix {
-		name := a.Name() + suffix
-
-		var scope bazel.StringAttribute
-		scope.SetValue(scopeName)
-
-		var base bazel.LabelAttribute
-		base.SetValue(android.BazelLabelForModuleDepSingle(ctx, basePrefix+suffix))
-
-		var deps bazel.LabelListAttribute
-		classpath := a.properties.Bootclasspath
-		if scopeName == "system-server" {
-			classpath = a.properties.System_server_classpath
-		}
-		deps = bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, classpath))
-
-		attrs := bazelCombinedApisAttributes{
-			Scope: scope,
-			Base:  base,
-			Deps:  deps,
-		}
-		props := bazel.BazelTargetModuleProperties{
-			Rule_class:        "merged_txts",
-			Bzl_load_location: "//build/bazel/rules/java:merged_txts.bzl",
-		}
-		ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name}, &attrs)
-	}
-}
-
 // Various utility methods below.
 
 // Creates an array of ":<m><tag>" for each m in <modules>.
diff --git a/api/api_test.go b/api/api_test.go
deleted file mode 100644
index 70f2162..0000000
--- a/api/api_test.go
+++ /dev/null
@@ -1,115 +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 api
-
-import (
-	"testing"
-
-	"android/soong/android"
-	"android/soong/bp2build"
-	"android/soong/java"
-)
-
-func runCombinedApisTestCaseWithRegistrationCtxFunc(t *testing.T, tc bp2build.Bp2buildTestCase, registrationCtxFunc func(ctx android.RegistrationContext)) {
-	t.Helper()
-	(&tc).ModuleTypeUnderTest = "combined_apis"
-	(&tc).ModuleTypeUnderTestFactory = combinedApisModuleFactory
-	bp2build.RunBp2BuildTestCase(t, registrationCtxFunc, tc)
-}
-
-func runCombinedApisTestCase(t *testing.T, tc bp2build.Bp2buildTestCase) {
-	t.Helper()
-	runCombinedApisTestCaseWithRegistrationCtxFunc(t, tc, func(ctx android.RegistrationContext) {
-		ctx.RegisterModuleType("java_defaults", java.DefaultsFactory)
-		ctx.RegisterModuleType("java_sdk_library", java.SdkLibraryFactory)
-		ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
-	})
-}
-
-func TestCombinedApisGeneral(t *testing.T) {
-	runCombinedApisTestCase(t, bp2build.Bp2buildTestCase{
-		Description: "combined_apis, general case",
-		Blueprint: `combined_apis {
-    name: "foo",
-    bootclasspath: ["bcp"],
-    system_server_classpath: ["ssc"],
-}
-
-java_sdk_library {
-		name: "bcp",
-		srcs: ["a.java", "b.java"],
-		shared_library: false,
-}
-java_sdk_library {
-		name: "ssc",
-		srcs: ["a.java", "b.java"],
-		shared_library: false,
-}
-filegroup {
-    name: "non-updatable-current.txt",
-    srcs: ["current.txt"],
-}
-filegroup {
-    name: "non-updatable-system-current.txt",
-    srcs: ["system-current.txt"],
-}
-filegroup {
-    name: "non-updatable-module-lib-current.txt",
-    srcs: ["system-removed.txt"],
-}
-filegroup {
-    name: "non-updatable-system-server-current.txt",
-    srcs: ["system-lint-baseline.txt"],
-}
-`,
-		Filesystem: map[string]string{
-			"a/Android.bp": `
-			java_defaults {
-				name: "android.jar_defaults",
-			}
-			`,
-			"api/current.txt":        "",
-			"api/removed.txt":        "",
-			"api/system-current.txt": "",
-			"api/system-removed.txt": "",
-			"api/test-current.txt":   "",
-			"api/test-removed.txt":   "",
-		},
-		StubbedBuildDefinitions:    []string{"bcp", "ssc", "non-updatable-current.txt", "non-updatable-system-current.txt", "non-updatable-module-lib-current.txt", "non-updatable-system-server-current.txt"},
-		ExpectedHandcraftedModules: []string{"foo-current.txt", "foo-system-current.txt", "foo-module-lib-current.txt", "foo-system-server-current.txt"},
-		ExpectedBazelTargets: []string{
-			bp2build.MakeBazelTargetNoRestrictions("merged_txts", "foo-current.txt", bp2build.AttrNameToString{
-				"scope": `"public"`,
-				"base":  `":non-updatable-current.txt"`,
-				"deps":  `[":bcp"]`,
-			}),
-			bp2build.MakeBazelTargetNoRestrictions("merged_txts", "foo-system-current.txt", bp2build.AttrNameToString{
-				"scope": `"system"`,
-				"base":  `":non-updatable-system-current.txt"`,
-				"deps":  `[":bcp"]`,
-			}),
-			bp2build.MakeBazelTargetNoRestrictions("merged_txts", "foo-module-lib-current.txt", bp2build.AttrNameToString{
-				"scope": `"module-lib"`,
-				"base":  `":non-updatable-module-lib-current.txt"`,
-				"deps":  `[":bcp"]`,
-			}),
-			bp2build.MakeBazelTargetNoRestrictions("merged_txts", "foo-system-server-current.txt", bp2build.AttrNameToString{
-				"scope": `"system-server"`,
-				"base":  `":non-updatable-system-server-current.txt"`,
-				"deps":  `[":ssc"]`,
-			}),
-		},
-	})
-}
diff --git a/api/coverage/tools/ExtractFlaggedApis.kt b/api/coverage/tools/ExtractFlaggedApis.kt
index 9ffb704..caa1929 100644
--- a/api/coverage/tools/ExtractFlaggedApis.kt
+++ b/api/coverage/tools/ExtractFlaggedApis.kt
@@ -23,35 +23,43 @@
 /** Usage: extract-flagged-apis <api text file> <output .pb file> */
 fun main(args: Array<String>) {
     var cb = ApiFile.parseApi(listOf(File(args[0])))
-    val flagToApi = mutableMapOf<String, MutableList<String>>()
-    cb.getPackages()
-        .allClasses()
-        .filter { it.methods().size > 0 }
-        .forEach {
-            for (method in it.methods()) {
-                val flagValue =
-                    method.modifiers
-                        .findAnnotation("android.annotation.FlaggedApi")
-                        ?.findAttribute("value")
-                        ?.value
-                        ?.value()
-                if (flagValue != null && flagValue is String) {
-                    val methodQualifiedName = "${it.qualifiedName()}.${method.name()}"
-                    if (flagToApi.containsKey(flagValue)) {
-                        flagToApi.get(flagValue)?.add(methodQualifiedName)
-                    } else {
-                        flagToApi.put(flagValue, mutableListOf(methodQualifiedName))
+    var builder = FlagApiMap.newBuilder()
+    for (pkg in cb.getPackages().packages) {
+        var packageName = pkg.qualifiedName()
+        pkg.allClasses()
+            .filter { it.methods().size > 0 }
+            .forEach {
+                for (method in it.methods()) {
+                    val flagValue =
+                        method.modifiers
+                            .findAnnotation("android.annotation.FlaggedApi")
+                            ?.findAttribute("value")
+                            ?.value
+                            ?.value()
+                    if (flagValue != null && flagValue is String) {
+                        var api =
+                            JavaMethod.newBuilder()
+                                .setPackageName(packageName)
+                                .setClassName(it.fullName())
+                                .setMethodName(method.name())
+                        for (param in method.parameters()) {
+                            api.addParameters(param.type().toTypeString())
+                        }
+                        if (builder.containsFlagToApi(flagValue)) {
+                            var updatedApis =
+                                builder
+                                    .getFlagToApiOrThrow(flagValue)
+                                    .toBuilder()
+                                    .addJavaMethods(api)
+                                    .build()
+                            builder.putFlagToApi(flagValue, updatedApis)
+                        } else {
+                            var apis = FlaggedApis.newBuilder().addJavaMethods(api).build()
+                            builder.putFlagToApi(flagValue, apis)
+                        }
                     }
                 }
             }
-        }
-    var builder = FlagApiMap.newBuilder()
-    for (flag in flagToApi.keys) {
-        var flaggedApis = FlaggedApis.newBuilder()
-        for (method in flagToApi.get(flag).orEmpty()) {
-            flaggedApis.addFlaggedApi(FlaggedApi.newBuilder().setQualifiedName(method))
-        }
-        builder.putFlagToApi(flag, flaggedApis.build())
     }
     val flagApiMap = builder.build()
     FileWriter(args[1]).use { it.write(flagApiMap.toString()) }
diff --git a/api/coverage/tools/extract_flagged_apis.proto b/api/coverage/tools/extract_flagged_apis.proto
index a858108..4db2a8b 100644
--- a/api/coverage/tools/extract_flagged_apis.proto
+++ b/api/coverage/tools/extract_flagged_apis.proto
@@ -25,10 +25,13 @@
 }
 
 message FlaggedApis {
-  repeated FlaggedApi flagged_api = 1;
+  repeated JavaMethod java_methods = 1;
 }
 
-message FlaggedApi {
-  string qualified_name = 1;
+message JavaMethod {
+  string package_name = 1;
+  string class_name = 2;
+  string method_name = 3;
+  repeated string parameters = 4;
 }
 
diff --git a/api/go.mod b/api/go.mod
index f8bb1c0..445a6f4 100644
--- a/api/go.mod
+++ b/api/go.mod
@@ -6,7 +6,5 @@
 	android/soong v0.0.0
 	github.com/google/blueprint v0.0.0
 	google.golang.org/protobuf v0.0.0
-	prebuilts/bazel/common/proto/analysis_v2 v0.0.0
-	prebuilts/bazel/common/proto/build v0.0.0
 	go.starlark.net v0.0.0
 )
diff --git a/api/go.work b/api/go.work
index aa2d2b1..edd002e 100644
--- a/api/go.work
+++ b/api/go.work
@@ -13,7 +13,5 @@
 	google.golang.org/protobuf v0.0.0 => ../../../external/golang-protobuf
 	github.com/google/blueprint v0.0.0 => ../../../build/blueprint
 	github.com/google/go-cmp v0.0.0 => ../../../external/go-cmp
-	prebuilts/bazel/common/proto/analysis_v2 v0.0.0 => ../../../prebuilts/bazel/common/proto/analysis_v2
-	prebuilts/bazel/common/proto/build v0.0.0 => ../../../prebuilts/bazel/common/proto/build
 	go.starlark.net v0.0.0 => ../../../external/starlark-go
 )
diff --git a/config/dirty-image-objects b/config/dirty-image-objects
index 2584610e..f2e2b82 100644
--- a/config/dirty-image-objects
+++ b/config/dirty-image-objects
@@ -16,282 +16,1713 @@
 #
 #
 # Dirty-image-objects file for boot image.
-#
-# Objects in this file are known dirty at runtime. Current this includes:
-#   - classes with known dirty static fields.
-#
 # The image writer will bin these objects together in the image.
+# More info about dirty objects format and how to collect the data can be
+# found in: art/imgdiag/dirty_image_objects.md
+# This particular file was generated by dumping all pre-installed apps.
 #
-# This file can be generated using imgdiag with a command such as:
-#   adb shell imgdiag --image-diff-pid=<app pid> --zygote-diff-pid=<zygote pid> \
-#     --boot-image=/system/framework/boot.art --dump-dirty-objects
-# Then, grep for lines containing "Private dirty object" from the output.
-# This particular file was generated by dumping systemserver and systemui.
-#
-Landroid/animation/LayoutTransition;
-Landroid/app/ActivityManager;
-Landroid/app/ActivityTaskManager;
-Landroid/app/ActivityThread;
-Landroid/app/AlarmManager;
-Landroid/app/AppOpsManager;
-Landroid/app/ContextImpl;
-Landroid/app/Notification;
-Landroid/app/NotificationManager;
-Landroid/app/PendingIntent$FinishedDispatcher;
-Landroid/app/PropertyInvalidatedCache$NoPreloadHolder;
-Landroid/app/QueuedWork;
-Landroid/app/ResourcesManager;
-Landroid/app/SystemServiceRegistry;
-Landroid/app/WallpaperManager;
-Landroid/app/backup/BackupManager;
-Landroid/compat/Compatibility;
-Landroid/content/AsyncQueryHandler;
-Landroid/content/ContentProviderClient;
-Landroid/content/ContentResolver;
-Landroid/content/Context;
-Landroid/content/pm/PackageItemInfo;
-Landroid/content/pm/UserPackage;
-Landroid/content/res/ResourceTimer;
-Landroid/database/CursorWindow;
-Landroid/database/sqlite/SQLiteCompatibilityWalFlags;
-Landroid/database/sqlite/SQLiteDebug$NoPreloadHolder;
-Landroid/database/sqlite/SQLiteGlobal;
-Landroid/ddm/DdmHandleAppName;
-Landroid/graphics/Bitmap;
-Landroid/graphics/Canvas;
-Landroid/graphics/Compatibility;
-Landroid/graphics/HardwareRenderer;
-Landroid/graphics/TemporaryBuffer;
-Landroid/graphics/Typeface;
-Landroid/graphics/drawable/AdaptiveIconDrawable;
-Landroid/hardware/SensorPrivacyManager;
-Landroid/hardware/SystemSensorManager;
-Landroid/hardware/devicestate/DeviceStateManagerGlobal;
-Landroid/hardware/display/ColorDisplayManager$ColorDisplayManagerInternal;
-Landroid/hardware/display/DisplayManagerGlobal;
-Landroid/hardware/input/InputManagerGlobal;
-Landroid/hardware/location/GeofenceHardwareImpl;
-Landroid/icu/impl/number/range/StandardPluralRanges;
-Landroid/icu/text/Collator;
-Landroid/icu/util/TimeZone;
-Landroid/location/LocationManager;
-Landroid/media/AudioManager;
-Landroid/media/AudioPlaybackConfiguration;
-Landroid/media/AudioSystem;
-Landroid/media/MediaCodec;
-Landroid/media/MediaCodecList;
-Landroid/media/MediaFrameworkPlatformInitializer;
-Landroid/media/MediaRouter2Manager;
-Landroid/media/MediaRouter;
-Landroid/media/PlayerBase;
-Landroid/media/audiopolicy/AudioProductStrategy;
-Landroid/media/audiopolicy/AudioVolumeGroup;
-Landroid/nfc/NfcAdapter;
-Landroid/nfc/NfcFrameworkInitializer;
-Landroid/nfc/cardemulation/CardEmulation;
-Landroid/os/AsyncTask;
-Landroid/os/BaseBundle;
-Landroid/os/Binder;
-Landroid/os/BinderProxy;
-Landroid/os/Environment;
-Landroid/os/FileObserver;
-Landroid/os/Handler;
-Landroid/os/LocaleList;
-Landroid/os/Looper;
-Landroid/os/Message;
-Landroid/os/NullVibrator;
-Landroid/os/Parcel;
-Landroid/os/Process;
-Landroid/os/ServiceManager;
-Landroid/os/StrictMode;
-Landroid/os/UEventObserver;
-Landroid/os/UserManager;
-Landroid/os/WorkSource;
-Landroid/os/storage/StorageManager;
-Landroid/permission/PermissionManager;
-Landroid/provider/DeviceConfigInitializer;
-Landroid/provider/FontsContract;
-Landroid/provider/Settings;
-Landroid/renderscript/RenderScript;
-Landroid/renderscript/RenderScriptCacheDir;
-Landroid/security/keystore2/KeyStoreCryptoOperationUtils;
-Landroid/security/net/config/ApplicationConfig;
-Landroid/security/net/config/SystemCertificateSource$NoPreloadHolder;
-Landroid/security/net/config/UserCertificateSource$NoPreloadHolder;
-Landroid/telecom/Log;
-Landroid/telecom/TelecomManager;
-Landroid/telephony/AnomalyReporter;
-Landroid/telephony/TelephonyFrameworkInitializer;
-Landroid/telephony/TelephonyLocalConnection;
-Landroid/telephony/TelephonyManager;
-Landroid/telephony/TelephonyRegistryManager;
-Landroid/text/DynamicLayout;
-Landroid/text/TextUtils;
-Landroid/text/format/DateFormat;
-Landroid/text/format/DateUtils;
-Landroid/text/method/ArrowKeyMovementMethod;
-Landroid/text/method/LinkMovementMethod;
-Landroid/text/method/SingleLineTransformationMethod;
-Landroid/text/style/ClickableSpan;
-Landroid/timezone/TelephonyLookup;
-Landroid/timezone/TimeZoneFinder;
-Landroid/util/ArrayMap;
-Landroid/util/ArraySet;
-Landroid/util/EventLog;
-Landroid/util/NtpTrustedTime;
-Landroid/view/Choreographer;
-Landroid/view/CrossWindowBlurListeners;
-Landroid/view/DisplayCutout;
-Landroid/view/KeyEvent;
-Landroid/view/MotionEvent;
-Landroid/view/PointerIcon;
-Landroid/view/RoundedCorners;
-Landroid/view/SurfaceControl;
-Landroid/view/View;
-Landroid/view/ViewGroup$TouchTarget;
-Landroid/view/ViewRootImpl;
-Landroid/view/ViewTreeObserver;
-Landroid/view/WindowManagerGlobal;
-Landroid/view/accessibility/AccessibilityManager;
-Landroid/view/accessibility/AccessibilityNodeIdManager;
-Landroid/view/autofill/Helper;
-Landroid/view/inputmethod/IInputMethodManagerGlobalInvoker;
-Landroid/view/inputmethod/InputMethodManager;
-Landroid/webkit/CookieSyncManager;
-Landroid/webkit/WebView;
-Landroid/webkit/WebViewFactory;
-Landroid/webkit/WebViewZygote;
-Landroid/widget/AbsListView;
-Landroid/widget/ImageView;
-Landroid/widget/LinearLayout;
-Landroid/widget/Toast;
-Landroid/window/SurfaceSyncGroup;
-Lcom/android/i18n/timezone/TelephonyLookup;
-Lcom/android/i18n/timezone/TimeZoneFinder;
-Lcom/android/internal/config/appcloning/AppCloningDeviceConfigHelper;
-Lcom/android/internal/content/om/OverlayConfig;
-Lcom/android/internal/display/BrightnessSynchronizer;
-Lcom/android/internal/infra/AndroidFuture;
-Lcom/android/internal/inputmethod/ImeTracing;
-Lcom/android/internal/inputmethod/InputMethodPrivilegedOperationsRegistry;
-Lcom/android/internal/jank/InteractionJankMonitor$InstanceHolder;
-Lcom/android/internal/jank/InteractionJankMonitor;
-Lcom/android/internal/logging/MetricsLogger;
-Lcom/android/internal/os/BackgroundThread;
-Lcom/android/internal/os/BinderInternal;
-Lcom/android/internal/os/KernelCpuBpfTracking;
-Lcom/android/internal/os/RuntimeInit;
-Lcom/android/internal/os/SomeArgs;
-Lcom/android/internal/os/ZygoteInit;
-Lcom/android/internal/policy/AttributeCache;
-Lcom/android/internal/protolog/BaseProtoLogImpl;
-Lcom/android/internal/protolog/ProtoLogImpl;
-Lcom/android/internal/statusbar/NotificationVisibility;
-Lcom/android/internal/telephony/CellBroadcastServiceManager;
-Lcom/android/internal/telephony/IntentBroadcaster;
-Lcom/android/internal/telephony/MccTable;
-Lcom/android/internal/telephony/MultiSimSettingController;
-Lcom/android/internal/telephony/PackageChangeReceiver;
-Lcom/android/internal/telephony/PhoneConfigurationManager;
-Lcom/android/internal/telephony/PhoneFactory;
-Lcom/android/internal/telephony/ProxyController;
-Lcom/android/internal/telephony/RILRequest;
-Lcom/android/internal/telephony/RadioConfig;
-Lcom/android/internal/telephony/RadioInterfaceCapabilityController;
-Lcom/android/internal/telephony/SmsApplication;
-Lcom/android/internal/telephony/SmsBroadcastUndelivered;
-Lcom/android/internal/telephony/SomeArgs;
-Lcom/android/internal/telephony/TelephonyComponentFactory;
-Lcom/android/internal/telephony/TelephonyDevController;
-Lcom/android/internal/telephony/cat/CatService;
-Lcom/android/internal/telephony/cdma/CdmaInboundSmsHandler;
-Lcom/android/internal/telephony/cdma/CdmaSubscriptionSourceManager;
-Lcom/android/internal/telephony/euicc/EuiccCardController;
-Lcom/android/internal/telephony/euicc/EuiccController;
-Lcom/android/internal/telephony/ims/ImsResolver;
-Lcom/android/internal/telephony/metrics/TelephonyMetrics;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$CarrierIdMismatch;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$CellularDataServiceSwitch;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$CellularServiceState;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$DataCallSession;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$EmergencyNumbersInfo;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$GbaEvent;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsDedicatedBearerEvent;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsDedicatedBearerListenerEvent;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsRegistrationFeatureTagStats;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsRegistrationServiceDescStats;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsRegistrationStats;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsRegistrationTermination;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$IncomingSms;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$NetworkRequests;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$NetworkRequestsV2;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$OutgoingShortCodeSms;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$OutgoingSms;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$PresenceNotifyEvent;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$RcsAcsProvisioningStats;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$RcsClientProvisioningStats;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteController;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteIncomingDatagram;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteOutgoingDatagram;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteProvision;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteSession;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteSosMessageRecommender;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$SipDelegateStats;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$SipMessageResponse;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$SipTransportFeatureTagStats;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$SipTransportSession;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$UceEventStats;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$UnmeteredNetworks;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$VoiceCallRatUsage;
-Lcom/android/internal/telephony/nano/PersistAtomsProto$VoiceCallSession;
-Lcom/android/internal/telephony/nano/TelephonyProto$RilDataCall;
-Lcom/android/internal/telephony/nano/TelephonyProto$TelephonyCallSession$Event$RilCall;
-Lcom/android/internal/telephony/nano/TelephonyProto$TelephonyServiceState$NetworkRegistrationInfo;
-Lcom/android/internal/telephony/satellite/PointingAppController;
-Lcom/android/internal/telephony/satellite/SatelliteModemInterface;
-Lcom/android/internal/telephony/uicc/UiccController;
-Lcom/android/internal/telephony/uicc/UiccStateChangedLauncher;
-Lcom/android/internal/util/ContrastColorUtil;
-Lcom/android/internal/view/WindowManagerPolicyThread;
-Lcom/android/org/bouncycastle/crypto/CryptoServicesRegistrar;
-Lcom/android/phone/ecc/nano/ProtobufEccData$CountryInfo;
-Lcom/android/phone/ecc/nano/ProtobufEccData$EccInfo;
-Lcom/android/server/AppWidgetBackupBridge;
-Ldalvik/system/BaseDexClassLoader;
-Ldalvik/system/BlockGuard;
-Ldalvik/system/CloseGuard;
-Ldalvik/system/RuntimeHooks;
-Ldalvik/system/SocketTagger;
-Ldalvik/system/VMRuntime;
-Ldalvik/system/ZipPathValidator;
-Ldalvik/system/ZygoteHooks;
-Ljava/lang/System;
-Ljava/lang/Thread;
-Ljava/lang/Throwable;
-Ljava/lang/ref/FinalizerReference;
-Ljava/lang/ref/ReferenceQueue;
-Ljava/net/ResponseCache;
-Ljava/nio/Bits;
-Ljava/nio/charset/Charset;
-Ljava/security/Provider;
-Ljava/util/Collections;
-Ljava/util/GregorianCalendar;
-Ljava/util/Locale$NoImagePreloadHolder;
-Ljava/util/Locale;
-Ljava/util/Scanner;
-Ljava/util/TimeZone;
-Ljava/util/concurrent/ForkJoinPool;
-Ljava/util/concurrent/ThreadLocalRandom;
-Ljavax/net/ServerSocketFactory;
-Ljavax/net/SocketFactory;
-Ljavax/net/ssl/HttpsURLConnection$NoPreloadHolder;
-Ljavax/net/ssl/HttpsURLConnection;
-Ljavax/net/ssl/SSLContext;
-Ljavax/net/ssl/SSLServerSocketFactory;
-Ljavax/net/ssl/SSLSocketFactory;
-Llibcore/io/Libcore;
-Llibcore/net/NetworkSecurityPolicy;
-Lsun/misc/Cleaner;
-Lsun/nio/ch/FileChannelImpl$Unmapper;
-Lsun/nio/ch/FileChannelImpl;
-Lsun/security/jca/Providers;
+Landroid/text/style/URLSpan; 0
+Landroid/content/res/Resources$NotFoundException; 1
+Landroid/os/PowerManager$WakeLock; 2
+Landroid/os/BatterySaverPolicyConfig; 2
+Landroid/content/ContextWrapper; 2
+Landroid/app/WallpaperInfo; 2
+Landroid/content/pm/PackageManager; 2
+Landroid/app/IWallpaperManager; 2
+Ljava/lang/BootClassLoader; 2
+Ljava/time/Duration; 2
+Landroid/util/Printer; 2
+Landroid/app/WallpaperManager$OnColorsChangedListener; 2
+Landroid/app/WallpaperColors; 2
+Landroid/content/pm/ServiceInfo; 2
+Landroid/app/KeyguardManager$KeyguardDismissCallback; 2
+Ljava/lang/CharSequence; 3
+Landroid/widget/Switch; 4
+Lcom/android/internal/util/ContrastColorUtil; 4
+Landroid/view/SurfaceControl; 4
+Landroid/graphics/ColorMatrix;.dexCache:Ljava/lang/Object; 4
+Lcom/android/internal/widget/CachingIconView; 4
+Landroid/window/IRemoteTransition$Stub$Proxy; 4
+Landroid/app/trust/TrustManager$TrustListener; 4
+Landroid/view/NotificationHeaderView; 4
+Lcom/android/internal/widget/ImageResolver; 4
+Landroid/window/WindowContainerTransaction$Change; 4
+Lcom/android/internal/widget/MessagingLayout; 4
+Ljava/util/concurrent/ConcurrentLinkedQueue; 4
+Lcom/android/internal/protolog/BaseProtoLogImpl;.LOG_GROUPS:Ljava/util/TreeMap;.root:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.left:Ljava/util/TreeMap$TreeMapEntry; 4
+Landroid/view/RemotableViewMethod; 4
+Landroid/app/IApplicationThread$Stub$Proxy; 4
+Landroid/os/FileUtils; 4
+Landroid/view/View;.SCALE_X:Landroid/util/Property; 4
+Landroid/widget/GridLayout;.UNDEFINED_ALIGNMENT:Landroid/widget/GridLayout$Alignment; 4
+Landroid/media/MediaPlayer$EventHandler; 4
+Landroid/widget/DateTimeView; 4
+Llibcore/util/ZoneInfo; 4
+Lcom/android/internal/statusbar/IStatusBarService; 4
+Ljava/lang/invoke/MethodType;.internTable:Ljava/lang/invoke/MethodType$ConcurrentWeakInternSet;.stale:Ljava/lang/ref/ReferenceQueue; 4
+Lcom/android/internal/protolog/BaseProtoLogImpl;.LOG_GROUPS:Ljava/util/TreeMap;.root:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry; 4
+Lcom/android/internal/logging/UiEventLogger; 4
+Lcom/android/internal/protolog/BaseProtoLogImpl;.LOG_GROUPS:Ljava/util/TreeMap;.root:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.left:Ljava/util/TreeMap$TreeMapEntry; 4
+Lcom/android/internal/protolog/BaseProtoLogImpl;.LOG_GROUPS:Ljava/util/TreeMap;.root:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry; 4
+Landroid/renderscript/RenderScript; 4
+Landroid/view/ViewTreeObserver$OnWindowVisibilityChangeListener; 4
+Lcom/android/internal/widget/RemeasuringLinearLayout; 4
+Landroid/widget/DateTimeView$ReceiverInfo$1; 4
+Landroid/view/View;.TRANSLATION_Y:Landroid/util/Property; 4
+Lcom/android/internal/protolog/BaseProtoLogImpl;.LOG_GROUPS:Ljava/util/TreeMap;.root:Ljava/util/TreeMap$TreeMapEntry; 4
+Lcom/android/internal/widget/NotificationExpandButton; 4
+Lcom/android/internal/view/menu/ActionMenuItemView; 4
+Landroid/view/animation/AnimationSet; 4
+Landroid/hardware/biometrics/BiometricSourceType;.FINGERPRINT:Landroid/hardware/biometrics/BiometricSourceType; 4
+Landroid/window/WindowOrganizer;.IWindowOrganizerControllerSingleton:Landroid/util/Singleton; 4
+Ljava/lang/Runnable; 4
+Lorg/apache/harmony/dalvik/ddmc/DdmServer;.mHandlerMap:Ljava/util/HashMap; 4
+Lcom/android/internal/protolog/BaseProtoLogImpl;.LOG_GROUPS:Ljava/util/TreeMap;.root:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry; 4
+Lcom/android/internal/widget/ImageFloatingTextView; 4
+Landroid/window/IWindowContainerToken$Stub$Proxy; 4
+Lcom/android/internal/protolog/BaseProtoLogImpl;.LOG_GROUPS:Ljava/util/TreeMap;.root:Ljava/util/TreeMap$TreeMapEntry;.left:Ljava/util/TreeMap$TreeMapEntry; 4
+Landroid/content/res/ColorStateList; 4
+Landroid/view/View;.SCALE_Y:Landroid/util/Property; 4
+Lcom/android/internal/protolog/BaseProtoLogImpl;.LOG_GROUPS:Ljava/util/TreeMap; 4
+Lcom/android/internal/widget/ConversationLayout; 4
+Lcom/android/internal/protolog/BaseProtoLogImpl;.LOG_GROUPS:Ljava/util/TreeMap;.root:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry; 4
+Lcom/android/internal/colorextraction/ColorExtractor$OnColorsChangedListener; 4
+Landroid/hardware/face/FaceManager$FaceDetectionCallback; 4
+Landroid/widget/RemoteViews;.sLookupKey:Landroid/widget/RemoteViews$MethodKey; 4
+Landroid/widget/ViewSwitcher;.dexCache:Ljava/lang/Object; 4
+Lcom/android/internal/widget/NotificationActionListLayout; 4
+Ljava/util/concurrent/ConcurrentLinkedQueue$Node; 4
+Landroid/hardware/biometrics/BiometricSourceType;.FACE:Landroid/hardware/biometrics/BiometricSourceType; 4
+Landroid/hardware/biometrics/BiometricSourceType;.IRIS:Landroid/hardware/biometrics/BiometricSourceType; 4
+Landroid/view/NotificationTopLineView; 4
+Lcom/android/internal/protolog/BaseProtoLogImpl;.LOG_GROUPS:Ljava/util/TreeMap;.root:Ljava/util/TreeMap$TreeMapEntry;.left:Ljava/util/TreeMap$TreeMapEntry;.left:Ljava/util/TreeMap$TreeMapEntry;.left:Ljava/util/TreeMap$TreeMapEntry;.left:Ljava/util/TreeMap$TreeMapEntry;.left:Ljava/util/TreeMap$TreeMapEntry; 4
+Landroid/widget/RemoteViews;.sMethods:Landroid/util/ArrayMap; 4
+Lcom/android/internal/os/BinderInternal$BinderProxyLimitListener; 5
+Landroid/app/AppOpsManager$OnOpNotedInternalListener; 5
+Lcom/android/internal/R$styleable;.WindowAnimation:[I 5
+Lcom/android/internal/logging/UiEventLogger$UiEventEnum; 5
+Lcom/android/internal/policy/AttributeCache; 5
+Landroid/app/Notification$CallStyle; 5
+Landroid/app/AppOpsManager$OnOpNotedListener; 5
+Lcom/android/internal/protolog/BaseProtoLogImpl; 5
+Landroid/app/AppOpsManager$OnOpStartedListener; 5
+Lcom/android/internal/util/ScreenshotHelper$1; 5
+Landroid/app/Notification$DecoratedCustomViewStyle; 5
+Landroid/view/DisplayCutout; 5
+Landroid/view/InputEvent;.mNextSeq:Ljava/util/concurrent/atomic/AtomicInteger; 5
+Lcom/android/internal/statusbar/NotificationVisibility; 5
+Landroid/telephony/DataSpecificRegistrationInfo; 6
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle; 7
+Landroid/telephony/VoiceSpecificRegistrationInfo; 8
+Landroid/telephony/AnomalyReporter; 8
+Landroid/telephony/TelephonyRegistryManager;.sCarrierPrivilegeCallbacks:Ljava/util/WeakHashMap; 8
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.1:Ljava/util/WeakHashMap$Entry; 8
+Landroid/app/LoadedApk$ServiceDispatcher$InnerConnection; 8
+Landroid/content/ContentProvider$Transport; 8
+Landroid/telephony/NetworkRegistrationInfo; 8
+Landroid/net/MatchAllNetworkSpecifier; 8
+Landroid/telephony/TelephonyRegistryManager;.sCarrierPrivilegeCallbacks:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry; 8
+Landroid/app/PropertyInvalidatedCache;.sInvalidates:Ljava/util/HashMap; 9
+Landroid/app/PropertyInvalidatedCache$NoPreloadHolder; 9
+Landroid/app/PropertyInvalidatedCache;.sDisabledKeys:Ljava/util/HashSet;.map:Ljava/util/HashMap; 10
+Landroid/media/AudioSystem$AudioRecordingCallback; 11
+Lcom/android/internal/util/Parcelling$BuiltIn$ForInternedString; 11
+Landroid/net/metrics/IpManagerEvent; 11
+Lcom/android/internal/os/ProcessCpuTracker$FilterStats; 11
+Lcom/android/internal/infra/AbstractRemoteService$AsyncRequest; 11
+Landroid/content/pm/RegisteredServicesCache$3; 11
+Lcom/android/internal/os/LooperStats; 11
+Lcom/android/server/AppWidgetBackupBridge; 11
+Landroid/hardware/display/DisplayManagerInternal; 11
+Landroid/content/pm/PackageInfo; 11
+Landroid/hardware/soundtrigger/SoundTriggerModule$EventHandlerDelegate; 11
+Landroid/app/servertransaction/ResumeActivityItem; 11
+Lcom/android/internal/widget/AlertDialogLayout; 11
+Landroid/content/pm/FallbackCategoryProvider;.sFallbacks:Landroid/util/ArrayMap; 11
+Landroid/os/RemoteCallback$1; 11
+Landroid/content/pm/SharedLibraryInfo; 11
+Landroid/util/MemoryIntArray; 11
+Landroid/net/metrics/DhcpErrorEvent; 11
+Lcom/android/internal/util/function/DodecConsumer; 11
+Landroid/provider/Settings; 11
+Landroid/app/PropertyInvalidatedCache;.sCorkLock:Ljava/lang/Object; 11
+Lcom/android/internal/os/CachedDeviceState$Readonly; 11
+Landroid/app/job/JobServiceEngine$JobHandler; 11
+Landroid/app/SystemServiceRegistry; 11
+Lcom/android/internal/os/BinderInternal$CallStatsObserver; 11
+Lcom/android/internal/statusbar/IStatusBar$Stub$Proxy; 11
+Landroid/hardware/location/IActivityRecognitionHardwareClient; 11
+Landroid/telecom/Logging/EventManager$EventListener; 11
+Landroid/accounts/AccountManagerInternal; 11
+Lcom/android/internal/os/KernelCpuBpfTracking; 11
+Lcom/android/internal/statusbar/NotificationVisibility$NotificationLocation; 11
+Landroid/hardware/camera2/CameraManager$CameraManagerGlobal; 11
+Landroid/os/ServiceSpecificException; 11
+Landroid/net/Uri$PathPart;.NULL:Landroid/net/Uri$PathPart; 11
+Landroid/app/ActivityManagerInternal; 11
+Landroid/media/AudioSystem; 11
+Landroid/service/dreams/DreamManagerInternal; 11
+Landroid/debug/AdbManagerInternal; 11
+Landroid/graphics/Bitmap$CompressFormat; 11
+Landroid/hardware/location/NanoAppMessage; 11
+Landroid/os/storage/StorageManagerInternal; 11
+Landroid/app/AppOpsManagerInternal; 11
+Ljava/security/cert/CertificateException; 11
+Ldalvik/system/VMRuntime; 11
+Landroid/content/pm/SigningInfo; 11
+Landroid/view/KeyEvent; 11
+Lcom/android/internal/view/WindowManagerPolicyThread; 11
+Landroid/graphics/Region;.sPool:Landroid/util/Pools$SynchronizedPool;.mPool:[Ljava/lang/Object; 11
+Landroid/content/res/ResourceTimer; 11
+Landroid/view/autofill/AutofillManagerInternal; 11
+Lcom/android/internal/util/Parcelling$Cache;.sCache:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object; 11
+Landroid/graphics/Region;.sPool:Landroid/util/Pools$SynchronizedPool; 11
+Landroid/app/LoadedApk$ReceiverDispatcher$Args$$ExternalSyntheticLambda0; 11
+Lcom/android/server/LocalServices;.sLocalServiceObjects:Landroid/util/ArrayMap; 11
+Landroid/app/admin/DevicePolicyManagerInternal$OnCrossProfileWidgetProvidersChangeListener; 11
+Landroid/accounts/AccountManagerInternal$OnAppPermissionChangeListener; 11
+Landroid/content/pm/PermissionInfo; 11
+Landroid/view/WindowManagerPolicyConstants$PointerEventListener; 11
+Landroid/os/UEventObserver; 11
+Landroid/media/AudioManagerInternal$RingerModeDelegate; 11
+Landroid/view/Display$HdrCapabilities; 11
+Landroid/service/notification/Condition; 11
+Landroid/content/pm/UserPackage; 11
+Landroid/app/AppOpsManager$SamplingStrategy; 11
+Landroid/telephony/ServiceState; 11
+Landroid/app/servertransaction/PauseActivityItem; 11
+Lcom/android/internal/util/function/pooled/PooledLambdaImpl;.sMessageCallbacksPool:Lcom/android/internal/util/function/pooled/PooledLambdaImpl$Pool;.mLock:Ljava/lang/Object; 11
+Landroid/view/KeyCharacterMap$FallbackAction; 11
+Lcom/android/internal/util/Parcelling$BuiltIn$ForInternedStringArray; 11
+Landroid/hardware/display/DeviceProductInfo; 11
+Lcom/android/internal/util/Parcelling$Cache;.sCache:Landroid/util/ArrayMap;.mHashes:[I 11
+Landroid/content/pm/RegisteredServicesCache$2; 11
+Landroid/content/pm/PackageManager;.sCacheAutoCorker:Landroid/app/PropertyInvalidatedCache$AutoCorker; 11
+Landroid/app/PropertyInvalidatedCache;.sCorks:Ljava/util/HashMap; 11
+Landroid/service/notification/StatusBarNotification; 11
+Landroid/app/servertransaction/ConfigurationChangeItem; 11
+Landroid/app/ActivityManager$RecentTaskInfo; 11
+Landroid/app/Notification; 11
+Landroid/app/servertransaction/DestroyActivityItem; 11
+Landroid/webkit/WebViewLibraryLoader$RelroFileCreator; 11
+Landroid/net/metrics/NetworkEvent; 11
+Landroid/media/AudioPlaybackConfiguration; 11
+Landroid/accessibilityservice/AccessibilityServiceInfo; 11
+Landroid/hardware/display/DeviceProductInfo$ManufactureDate; 11
+Landroid/os/storage/StorageVolume; 11
+Landroid/os/BatteryManagerInternal; 11
+Landroid/appwidget/AppWidgetManagerInternal; 11
+Landroid/app/servertransaction/NewIntentItem; 11
+Landroid/content/pm/ShortcutServiceInternal; 11
+Landroid/app/assist/ActivityId; 11
+Landroid/window/DisplayAreaAppearedInfo; 11
+Landroid/os/Process;.ZYGOTE_PROCESS:Landroid/os/ZygoteProcess;.mLock:Ljava/lang/Object; 11
+Landroid/app/usage/UsageStats; 11
+Landroid/app/Notification$MediaStyle; 11
+Landroid/media/AudioSystem$DynamicPolicyCallback; 11
+Landroid/content/pm/ProviderInfo; 11
+Landroid/os/PowerManagerInternal; 11
+Landroid/service/voice/VoiceInteractionManagerInternal; 11
+Landroid/content/pm/FeatureInfo; 11
+Landroid/app/servertransaction/TopResumedActivityChangeItem; 11
+Landroid/app/Notification$DecoratedMediaCustomViewStyle; 11
+Landroid/appwidget/AppWidgetProviderInfo; 11
+Landroid/app/AppOpsManager$NoteOpEvent; 11
+Landroid/graphics/GraphicsStatsService; 11
+Landroid/view/DisplayAddress$Physical; 11
+Landroid/content/ComponentName$WithComponentName; 11
+Landroid/app/admin/DevicePolicyManagerInternal; 11
+Landroid/os/ResultReceiver$MyResultReceiver; 11
+Landroid/content/ContentProviderClient; 11
+Landroid/content/pm/RegisteredServicesCache$1; 11
+Landroid/app/PendingIntent$FinishedDispatcher; 11
+Landroid/location/LocationManager; 11
+Landroid/hardware/location/ContextHubInfo; 11
+Landroid/content/pm/ShortcutServiceInternal$ShortcutChangeListener; 11
+Lcom/android/server/usage/AppStandbyInternal; 11
+Landroid/content/pm/RegisteredServicesCacheListener; 11
+Landroid/app/servertransaction/LaunchActivityItem; 11
+Landroid/content/pm/BaseParceledListSlice$1; 11
+Landroid/annotation/StringRes; 11
+Lcom/android/internal/R$styleable;.Window:[I 11
+Landroid/service/notification/ZenModeConfig; 11
+Landroid/telecom/Logging/SessionManager$ISessionListener; 11
+Landroid/app/time/TimeZoneConfiguration; 11
+Landroid/net/metrics/ValidationProbeEvent; 11
+Landroid/content/pm/PackageInstaller$SessionInfo; 11
+Landroid/content/pm/UserPackage;.sCache:Landroid/util/SparseArrayMap;.mData:Landroid/util/SparseArray; 11
+Landroid/content/pm/PermissionGroupInfo; 11
+Landroid/hardware/sidekick/SidekickInternal; 11
+Lcom/android/internal/widget/ButtonBarLayout; 11
+Landroid/content/pm/LauncherActivityInfoInternal; 11
+Lcom/android/internal/util/Parcelling$Cache;.sCache:Landroid/util/ArrayMap; 11
+Lcom/android/internal/widget/LockSettingsInternal; 11
+Landroid/media/AudioManagerInternal; 11
+Landroid/app/AppOpsManager$AttributedOpEntry; 11
+Lcom/android/internal/util/Parcelling$BuiltIn$ForInternedStringList; 11
+Landroid/telecom/Log; 11
+Landroid/app/time/TimeZoneCapabilities; 11
+Landroid/attention/AttentionManagerInternal; 11
+Landroid/view/WindowManagerPolicyConstants; 11
+Landroid/content/pm/CrossProfileAppsInternal; 11
+Landroid/hardware/location/GeofenceHardwareService; 11
+Landroid/content/pm/dex/ArtManagerInternal; 11
+Landroid/net/metrics/IpReachabilityEvent; 11
+Landroid/content/pm/LauncherApps$ShortcutQuery$QueryFlags; 11
+Landroid/media/AudioAttributes; 11
+Landroid/app/PropertyInvalidatedCache$AutoCorker$1; 11
+Landroid/net/metrics/ApfProgramEvent; 11
+Landroid/content/pm/SigningDetails; 11
+Lcom/android/internal/protolog/ProtoLogImpl; 11
+Landroid/hardware/biometrics/ComponentInfoInternal; 11
+Lcom/android/internal/util/ToBooleanFunction; 11
+Landroid/app/ActivityThread$H; 11
+Landroid/hardware/location/GeofenceHardwareImpl; 11
+Landroid/net/wifi/nl80211/WifiNl80211Manager$ScanEventHandler; 11
+Landroid/util/NtpTrustedTime; 11
+Landroid/hardware/soundtrigger/SoundTrigger$StatusListener; 11
+Lcom/android/internal/app/procstats/AssociationState;.sTmpSourceKey:Lcom/android/internal/app/procstats/AssociationState$SourceKey; 11
+Ljava/util/zip/ZipFile$ZipFileInflaterInputStream; 11
+Landroid/app/job/JobInfo; 11
+Lcom/android/internal/content/om/OverlayConfig; 11
+Landroid/webkit/WebViewZygote; 11
+Lcom/android/internal/util/Parcelling$BuiltIn$ForInternedStringSet; 11
+Lcom/android/internal/infra/AbstractRemoteService$VultureCallback; 11
+Landroid/permission/PermissionManagerInternal; 11
+Lcom/android/server/WidgetBackupProvider; 11
+Landroid/window/WindowOnBackInvokedDispatcher$OnBackInvokedCallbackWrapper; 11
+Landroid/app/PropertyInvalidatedCache;.sCorkedInvalidates:Ljava/util/HashMap; 11
+Landroid/media/AudioPlaybackConfiguration$PlayerDeathMonitor; 11
+Landroid/net/wifi/nl80211/WifiNl80211Manager$ScanEventCallback; 11
+Landroid/service/notification/NotificationListenerService$RankingMap; 11
+Landroid/os/UserHandle;.sExtraUserHandleCache:Landroid/util/SparseArray; 11
+Ljava/time/DateTimeException; 11
+Ljava/lang/NumberFormatException; 11
+Ljava/security/Provider;.knownEngines:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.125:Ljava/util/HashMap$Node;.value:Ljava/lang/Object; 11
+Landroid/app/LoadedApk$ServiceDispatcher$RunConnection; 11
+Landroid/view/RoundedCorners; 11
+Landroid/os/Process;.ZYGOTE_PROCESS:Landroid/os/ZygoteProcess; 11
+Landroid/media/audiopolicy/AudioVolumeGroup; 11
+Landroid/media/AudioSystem$ErrorCallback; 11
+Landroid/app/servertransaction/ActivityResultItem; 11
+Lcom/android/internal/widget/DialogTitle; 11
+Lcom/android/internal/os/StoragedUidIoStatsReader$Callback; 11
+Landroid/view/ViewRootImpl$W; 11
+Landroid/app/ServiceStartArgs; 11
+Landroid/window/TaskAppearedInfo; 11
+Lcom/android/internal/listeners/ListenerExecutor$FailureCallback; 11
+Landroid/app/ApplicationExitInfo; 11
+Landroid/content/pm/PackageManager;.sCacheAutoCorker:Landroid/app/PropertyInvalidatedCache$AutoCorker;.mLock:Ljava/lang/Object; 11
+Lcom/android/internal/util/Parcelling$BuiltIn$ForInternedStringValueMap; 11
+Landroid/content/pm/ResolveInfo; 11
+Lcom/android/internal/display/BrightnessSynchronizer; 11
+Landroid/window/IOnBackInvokedCallback$Stub$Proxy; 12
+Landroid/graphics/drawable/PictureDrawable; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.126:Ljava/lang/Byte; 13
+Landroid/view/ViewDebug$ExportedProperty; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.41:Ljava/lang/Byte; 13
+Landroid/view/inputmethod/DeleteGesture; 13
+Landroid/view/ViewDebug$IntToString; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.56:Ljava/lang/Byte; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.65:Ljava/lang/Byte; 13
+Landroid/webkit/WebViewFactory;.sProviderLock:Ljava/lang/Object; 13
+Ljava/lang/IllegalAccessError; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.51:Ljava/lang/Byte; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.52:Ljava/lang/Byte; 13
+Landroid/view/inputmethod/DeleteRangeGesture; 13
+Landroid/window/WindowContext; 13
+Ljava/util/concurrent/ConcurrentSkipListMap$Node; 13
+Landroid/view/inputmethod/SelectRangeGesture; 13
+Landroid/util/MalformedJsonException; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.131:Ljava/lang/Byte; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.120:Ljava/lang/Byte; 13
+Ljava/lang/Enum;.sharedConstantsCache:Llibcore/util/BasicLruCache;.map:Ljava/util/LinkedHashMap;.tail:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry; 13
+Ljava/nio/file/StandardOpenOption;.TRUNCATE_EXISTING:Ljava/nio/file/StandardOpenOption; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.121:Ljava/lang/Byte; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.16:Ljava/lang/Byte; 13
+Ljava/util/concurrent/ConcurrentSkipListMap$Index; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.139:Ljava/lang/Byte; 13
+Landroid/view/ViewDebug$FlagToString; 13
+Landroid/view/inputmethod/SelectGesture; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.20:Ljava/lang/Byte; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.94:Ljava/lang/Byte; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.64:Ljava/lang/Byte; 13
+Landroid/webkit/WebViewFactoryProvider$Statics; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.95:Ljava/lang/Byte; 13
+Landroid/service/media/MediaBrowserService$ServiceBinder$1; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.7:Ljava/lang/Byte; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.23:Ljava/lang/Byte; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.46:Ljava/lang/Byte; 13
+Landroid/provider/Settings$SettingNotFoundException; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.74:Ljava/lang/Byte; 13
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.8:Ljava/lang/Byte; 13
+Landroid/widget/TextView;.TEMP_POSITION:[F 13
+Ljava/io/ByteArrayInputStream; 14
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.93:Ljava/lang/Byte; 14
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.134:Ljava/lang/Byte; 14
+Landroid/text/style/ImageSpan; 14
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.154:Ljava/lang/Byte; 15
+Landroid/view/TextureView$SurfaceTextureListener; 16
+Landroid/media/AudioManager$OnAudioFocusChangeListener; 17
+Ljava/util/Locale;.JAPAN:Ljava/util/Locale; 18
+Ljava/util/Locale;.GERMANY:Ljava/util/Locale; 19
+Ljava/util/Locale;.CANADA_FRENCH:Ljava/util/Locale; 20
+Ljava/util/Locale;.ITALY:Ljava/util/Locale; 20
+Ljava/util/Locale;.FRANCE:Ljava/util/Locale; 20
+Ljava/util/Locale;.UK:Ljava/util/Locale; 21
+Ljava/util/Locale;.CANADA:Ljava/util/Locale; 21
+Ljava/util/Locale$Cache;.LOCALECACHE:Ljava/util/Locale$Cache;.map:Ljava/util/concurrent/ConcurrentMap; 22
+Ljava/lang/IllegalStateException; 23
+Lcom/android/internal/util/function/pooled/PooledLambdaImpl;.sMessageCallbacksPool:Lcom/android/internal/util/function/pooled/PooledLambdaImpl$Pool; 24
+Lcom/android/internal/util/function/pooled/PooledLambdaImpl;.sMessageCallbacksPool:Lcom/android/internal/util/function/pooled/PooledLambdaImpl$Pool;.mPool:[Ljava/lang/Object; 24
+Landroid/media/MediaRouter$WifiDisplayStatusChangedReceiver; 25
+Landroid/media/MediaRouter$VolumeChangeReceiver; 25
+Landroid/app/AppOpsManager$OnOpActiveChangedListener; 26
+Landroid/media/PlayerBase; 27
+Landroid/content/pm/Checksum$Type; 28
+Ljava/lang/Class; 29
+Landroid/widget/MediaController$MediaPlayerControl; 30
+Ljava/lang/Long$LongCache;.archivedCache:[Ljava/lang/Long;.135:Ljava/lang/Long; 30
+Ljava/lang/Long$LongCache;.archivedCache:[Ljava/lang/Long;.152:Ljava/lang/Long; 30
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.215:Ljava/lang/Byte; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.206:Ljava/lang/Byte; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.137:Ljava/lang/Byte; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.203:Ljava/lang/Byte; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.213:Ljava/lang/Byte; 31
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.549:Ljava/lang/Long; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.201:Ljava/lang/Byte; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.249:Ljava/lang/Byte; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.163:Ljava/lang/Byte; 31
+Ljava/util/HashMap; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.210:Ljava/lang/Byte; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.161:Ljava/lang/Byte; 31
+Landroid/icu/text/MeasureFormat;.hmsTo012:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.0:Ljava/util/HashMap$Node;.value:Ljava/lang/Object; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.199:Ljava/lang/Byte; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.248:Ljava/lang/Byte; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.252:Ljava/lang/Byte; 31
+Lcom/android/ims/rcs/uce/UceDeviceState;.DEVICE_STATE_DESCRIPTION:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.3:Ljava/util/HashMap$Node;.key:Ljava/lang/Object; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.159:Ljava/lang/Byte; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.217:Ljava/lang/Byte; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.200:Ljava/lang/Byte; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.240:Ljava/lang/Byte; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.198:Ljava/lang/Byte; 31
+Lcom/android/ims/rcs/uce/UceDeviceState;.DEVICE_STATE_DESCRIPTION:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.4:Ljava/util/HashMap$Node;.key:Ljava/lang/Object; 31
+Landroid/content/pm/PackageManager$OnChecksumsReadyListener; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.193:Ljava/lang/Byte; 31
+Ljava/lang/Long$LongCache;.archivedCache:[Ljava/lang/Long;.228:Ljava/lang/Long; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.236:Ljava/lang/Byte; 31
+Landroid/telephony/ims/ImsService;.CAPABILITIES_LOG_MAP:Ljava/util/Map;.table:[Ljava/lang/Object;.2:Ljava/lang/Long; 31
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.211:Ljava/lang/Byte; 31
+Landroid/view/SurfaceView; 32
+Landroid/view/ViewStub$OnInflateListener; 33
+Landroid/graphics/drawable/DrawableInflater;.CONSTRUCTOR_MAP:Ljava/util/HashMap; 34
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.245:Ljava/lang/Byte; 35
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.232:Ljava/lang/Byte; 35
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.12:Ljava/lang/Byte; 35
+Ljava/lang/Long$LongCache;.archivedCache:[Ljava/lang/Long;.170:Ljava/lang/Long; 35
+Ljava/lang/Long$LongCache;.archivedCache:[Ljava/lang/Long;.183:Ljava/lang/Long; 35
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.246:Ljava/lang/Byte; 35
+Ljava/lang/Long$LongCache;.archivedCache:[Ljava/lang/Long;.168:Ljava/lang/Long; 35
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.72:Ljava/lang/Byte; 35
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.243:Ljava/lang/Byte; 35
+Ljava/util/WeakHashMap;.NULL_KEY:Ljava/lang/Object; 35
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.235:Ljava/lang/Byte; 35
+Ljava/lang/Long$LongCache;.archivedCache:[Ljava/lang/Long;.147:Ljava/lang/Long; 35
+Ljava/io/InterruptedIOException; 35
+Ljava/lang/Long$LongCache;.archivedCache:[Ljava/lang/Long;.184:Ljava/lang/Long; 35
+Ljava/lang/Long$LongCache;.archivedCache:[Ljava/lang/Long;.165:Ljava/lang/Long; 35
+Landroid/text/style/ForegroundColorSpan; 35
+Ljava/lang/Long$LongCache;.archivedCache:[Ljava/lang/Long;.176:Ljava/lang/Long; 35
+Ljava/lang/Long$LongCache;.archivedCache:[Ljava/lang/Long;.173:Ljava/lang/Long; 35
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.181:Ljava/lang/Byte; 35
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.157:Ljava/lang/Byte; 35
+Landroid/content/res/AssetManager$AssetInputStream; 35
+Landroid/graphics/drawable/TransitionDrawable; 36
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.1:Ljava/lang/Boolean; 37
+Landroid/view/ViewOverlay$OverlayViewGroup; 38
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.11:Ljava/lang/Boolean; 39
+Ljava/util/Observer; 40
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.129:Ljava/lang/Byte; 41
+[Ljava/lang/Byte; 41
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.144:Ljava/lang/Byte; 41
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.164:Ljava/lang/Byte; 42
+Landroid/view/OrientationEventListener; 43
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.195:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.233:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.229:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.128:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.242:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.196:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.208:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.212:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.228:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.205:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.197:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.204:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.207:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.223:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.244:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.174:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.194:Ljava/lang/Byte; 44
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.225:Ljava/lang/Byte; 45
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.239:Ljava/lang/Byte; 45
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.238:Ljava/lang/Byte; 45
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.227:Ljava/lang/Byte; 45
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.152:Ljava/lang/Byte; 46
+Landroid/app/RemoteAction; 46
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.168:Ljava/lang/Byte; 46
+Landroid/text/style/QuoteSpan; 46
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.54:Ljava/lang/Byte; 46
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.124:Ljava/lang/Byte; 46
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.142:Ljava/lang/Byte; 46
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.190:Ljava/lang/Byte; 46
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.114:Ljava/lang/Byte; 46
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.69:Ljava/lang/Byte; 46
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.30:Ljava/lang/Byte; 46
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.133:Ljava/lang/Byte; 46
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.49:Ljava/lang/Byte; 46
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.58:Ljava/lang/Byte; 46
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.143:Ljava/lang/Byte; 47
+Landroid/icu/text/RelativeDateTimeFormatter$AbsoluteUnit; 47
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.82:Ljava/lang/Byte; 47
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.140:Ljava/lang/Byte; 47
+Landroid/icu/text/RelativeDateTimeFormatter;.fallbackCache:[Landroid/icu/text/RelativeDateTimeFormatter$Style; 47
+Landroid/icu/text/RelativeDateTimeFormatter$Style; 47
+Landroid/icu/text/RelativeDateTimeFormatter;.cache:Landroid/icu/text/RelativeDateTimeFormatter$Cache;.cache:Landroid/icu/impl/CacheBase;.map:Ljava/util/concurrent/ConcurrentHashMap; 47
+Landroid/icu/text/RelativeDateTimeFormatter$RelativeUnit; 47
+Landroid/icu/text/RelativeDateTimeFormatter$Direction; 47
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.130:Ljava/lang/Byte; 47
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.43:Ljava/lang/Byte; 47
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.146:Ljava/lang/Byte; 47
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.138:Ljava/lang/Byte; 47
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.136:Ljava/lang/Byte; 48
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.0:Ljava/lang/Byte; 49
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.160:Ljava/lang/Byte; 49
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.169:Ljava/lang/Byte; 50
+Landroid/widget/Spinner; 50
+Landroid/widget/MultiAutoCompleteTextView; 50
+Ljava/util/ArrayList; 50
+Landroid/widget/CheckBox; 50
+Ljava/io/Serializable; 50
+Landroid/widget/RatingBar; 50
+Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.132:Ljava/lang/Byte; 50
+Landroid/widget/AutoCompleteTextView; 50
+Ljava/util/concurrent/ConcurrentLinkedDeque$Node; 50
+[Ljava/lang/Object; 50
+Landroid/widget/SeekBar; 51
+Ljava/lang/Void; 52
+Landroid/app/ActivityTaskManager;.sInstance:Landroid/util/Singleton; 53
+Landroid/view/ViewRootImpl$$ExternalSyntheticLambda11; 54
+Landroid/view/ViewTreeObserver$OnWindowFocusChangeListener; 55
+Landroid/view/InsetsAnimationThread; 56
+Lcom/android/internal/jank/InteractionJankMonitor$InstanceHolder; 57
+Lcom/android/internal/jank/InteractionJankMonitor; 57
+Landroid/hardware/camera2/CameraCharacteristics;.FLASH_INFO_AVAILABLE:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 58
+Landroid/hardware/display/NightDisplayListener$Callback; 59
+Landroid/media/MediaRouter2Manager; 59
+Landroid/os/HandlerExecutor; 59
+Landroid/os/strictmode/LeakedClosableViolation; 60
+Lcom/android/internal/logging/MetricsLogger; 60
+Lcom/android/internal/os/PowerProfile;.sPowerItemMap:Ljava/util/HashMap; 61
+Lcom/android/internal/os/PowerProfile;.sPowerArrayMap:Ljava/util/HashMap; 61
+Lcom/android/internal/os/PowerProfile;.sModemPowerProfile:Lcom/android/internal/power/ModemPowerProfile;.mPowerConstants:Landroid/util/SparseDoubleArray;.mValues:Landroid/util/SparseLongArray; 61
+Landroid/content/IntentFilter; 62
+Landroid/telecom/TelecomManager; 63
+Ljava/lang/IllegalArgumentException; 64
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.1:Ljava/util/WeakHashMap$Entry;.referent:Ljava/lang/Object; 65
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.1:Ljava/util/WeakHashMap$Entry;.referent:Ljava/lang/Object;.mCache:Ljava/util/LinkedHashMap; 65
+Landroid/telephony/VisualVoicemailSmsFilterSettings;.DEFAULT_ORIGINATING_NUMBERS:Ljava/util/List; 66
+Ljava/util/AbstractList; 68
+Ljava/util/AbstractCollection; 68
+Ljava/util/Collections$EmptyList; 69
+Ljava/lang/StackTraceElement; 69
+[Ljava/lang/StackTraceElement; 69
+Landroid/os/strictmode/Violation; 70
+Ljava/util/List; 71
+Ljava/lang/String; 72
+Ljava/io/ObjectInputStream; 73
+Ljava/io/ObjectStreamClass$Caches;.localDescs:Ljava/util/concurrent/ConcurrentMap; 73
+Ljava/io/ObjectStreamClass$Caches;.reflectors:Ljava/util/concurrent/ConcurrentMap; 73
+Ljava/io/ObjectOutputStream; 73
+Ljava/lang/Number; 74
+Ljava/math/BigInteger; 75
+[B 76
+Landroid/os/Handler; 77
+Landroid/view/accessibility/AccessibilityManager; 78
+Landroid/view/ViewConfiguration;.sConfigurations:Landroid/util/SparseArray;.mKeys:[I 79
+Landroid/view/ViewConfiguration;.sConfigurations:Landroid/util/SparseArray;.mValues:[Ljava/lang/Object; 79
+Landroid/view/ViewConfiguration;.sConfigurations:Landroid/util/SparseArray; 79
+Landroid/widget/FrameLayout; 80
+Lcom/android/internal/inputmethod/ImeTracing; 80
+Lcom/android/internal/policy/DecorView; 80
+Landroid/view/accessibility/AccessibilityNodeIdManager; 80
+Landroid/view/ViewTreeObserver; 80
+Landroid/view/ViewRootImpl; 80
+Landroid/os/SystemProperties;.sChangeCallbacks:Ljava/util/ArrayList; 80
+Landroid/transition/ChangeTransform; 80
+Landroid/window/SurfaceSyncGroup; 80
+Landroid/transition/ChangeClipBounds; 80
+Landroid/view/SurfaceControlRegistry; 80
+Landroid/transition/ChangeImageTransform; 80
+Landroid/widget/LinearLayout; 80
+Landroid/view/ViewStub; 81
+Landroid/text/TextLine;.sCached:[Landroid/text/TextLine; 82
+Landroid/text/TextUtils; 82
+Landroid/graphics/TemporaryBuffer; 82
+Landroid/content/res/ColorStateList;.sCache:Landroid/util/SparseArray; 83
+Landroid/text/Layout;.sTempRect:Landroid/graphics/Rect; 84
+Landroid/widget/ImageView; 85
+Landroid/graphics/drawable/ColorDrawable; 86
+Landroid/os/StrictMode$InstanceTracker;.sInstanceCounts:Ljava/util/HashMap; 87
+Landroid/app/ActivityClient;.INTERFACE_SINGLETON:Landroid/app/ActivityClient$ActivityClientControllerSingleton; 88
+Landroid/app/ActivityClient;.sInstance:Landroid/util/Singleton; 88
+Landroid/view/AbsSavedState$1; 89
+Landroid/app/FragmentManagerState; 90
+Landroid/window/OnBackAnimationCallback; 91
+Landroid/animation/AnimatorInflater;.sTmpTypedValue:Landroid/util/TypedValue; 92
+Landroid/graphics/drawable/RippleDrawable; 93
+Landroid/view/inputmethod/IInputMethodManagerGlobalInvoker; 94
+Landroid/app/ActivityTaskManager;.IActivityTaskManagerSingleton:Landroid/util/Singleton; 95
+Landroid/view/Choreographer; 96
+Lcom/android/internal/os/SomeArgs; 97
+Landroid/graphics/Bitmap; 98
+Landroid/view/autofill/AutofillId; 99
+Landroid/view/inputmethod/BaseInputConnection;.COMPOSING:Ljava/lang/Object; 100
+Landroid/text/Selection;.SELECTION_MEMORY:Ljava/lang/Object; 101
+Landroid/text/Selection;.SELECTION_END:Ljava/lang/Object; 101
+Landroid/text/Selection;.SELECTION_START:Ljava/lang/Object; 101
+Landroid/text/SpannableStringBuilder;.sCachedIntBuffer:[[I 102
+Landroid/text/Selection$MemoryTextWatcher; 103
+Landroid/text/SpanWatcher; 104
+Lcom/android/internal/util/ArrayUtils;.sCache:[Ljava/lang/Object; 105
+Ljava/lang/Integer;.SMALL_NEG_VALUES:[Ljava/lang/String; 106
+Ljava/lang/Enum;.sharedConstantsCache:Llibcore/util/BasicLruCache;.map:Ljava/util/LinkedHashMap;.tail:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry; 107
+Lsun/nio/ch/SharedFileLockTable;.lockMap:Ljava/util/concurrent/ConcurrentHashMap; 108
+Lsun/nio/ch/FileChannelImpl; 108
+Landroid/database/sqlite/SQLiteDatabase$CursorFactory; 109
+Landroid/database/sqlite/SQLiteDebug$NoPreloadHolder; 110
+Landroid/database/sqlite/SQLiteCompatibilityWalFlags; 110
+Landroid/database/sqlite/SQLiteGlobal; 110
+Landroid/database/CursorWindow; 111
+Landroid/content/ContentResolver; 112
+Ljava/nio/charset/Charset; 113
+Landroid/app/ContextImpl; 114
+Ljava/util/concurrent/Executors$DefaultThreadFactory;.poolNumber:Ljava/util/concurrent/atomic/AtomicInteger; 115
+Landroid/content/pm/PackageManager;.sPackageInfoCache:Landroid/app/PropertyInvalidatedCache;.mCache:Ljava/util/LinkedHashMap; 116
+Landroid/content/pm/PackageManager;.sApplicationInfoCache:Landroid/app/PropertyInvalidatedCache;.mCache:Ljava/util/LinkedHashMap; 117
+Ljava/util/logging/LogManager;.manager:Ljava/util/logging/LogManager;.systemContext:Ljava/util/logging/LogManager$LoggerContext;.namedLoggers:Ljava/util/Hashtable;.table:[Ljava/util/Hashtable$HashtableEntry; 118
+Landroid/ddm/DdmHandleAppName; 118
+Landroid/provider/DeviceConfigInitializer; 118
+Lsun/misc/Cleaner; 118
+Ldalvik/system/CloseGuard; 118
+Landroid/graphics/Typeface; 118
+Landroid/os/BinderProxy;.sProxyMap:Landroid/os/BinderProxy$ProxyMap;.mMainIndexKeys:[[Ljava/lang/Long; 118
+Landroid/permission/PermissionManager; 118
+Landroid/media/MediaFrameworkPlatformInitializer; 118
+Ljava/util/TimeZone; 118
+Landroid/os/Environment; 118
+Landroid/compat/Compatibility; 118
+Landroid/os/ServiceManager; 118
+Landroid/content/pm/PackageManager;.sApplicationInfoCache:Landroid/app/PropertyInvalidatedCache; 118
+Ljava/util/Locale$NoImagePreloadHolder; 118
+Ljava/lang/System; 118
+Lcom/android/internal/os/RuntimeInit; 118
+Ljava/util/logging/LogManager;.manager:Ljava/util/logging/LogManager;.systemContext:Ljava/util/logging/LogManager$LoggerContext;.namedLoggers:Ljava/util/Hashtable; 118
+Ldalvik/system/VMRuntime;.THE_ONE:Ldalvik/system/VMRuntime; 118
+Landroid/view/View; 118
+Landroid/hardware/display/DisplayManagerGlobal; 118
+Ljava/util/logging/LogManager;.manager:Ljava/util/logging/LogManager; 118
+Landroid/telephony/TelephonyFrameworkInitializer; 118
+Landroid/se/omapi/SeFrameworkInitializer; 118
+Landroid/app/LoadedApk;.sApplications:Landroid/util/ArrayMap;.mHashes:[I 118
+Landroid/security/net/config/SystemCertificateSource$NoPreloadHolder; 118
+Landroid/security/net/config/ApplicationConfig; 118
+Landroid/content/res/Resources;.sResourcesHistory:Ljava/util/Set;.c:Ljava/util/Collection;.m:Ljava/util/Map; 118
+Ljava/util/Locale; 118
+Landroid/content/res/Resources;.sResourcesHistory:Ljava/util/Set;.c:Ljava/util/Collection;.m:Ljava/util/Map;.table:[Ljava/util/WeakHashMap$Entry; 118
+Ljava/security/Provider; 118
+Ldalvik/system/ZygoteHooks; 118
+Landroid/os/Message; 118
+Landroid/app/LoadedApk;.sApplications:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object; 118
+Landroid/app/LoadedApk;.sApplications:Landroid/util/ArrayMap; 118
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap; 118
+Ljava/util/logging/LogManager;.manager:Ljava/util/logging/LogManager;.userContext:Ljava/util/logging/LogManager$LoggerContext;.namedLoggers:Ljava/util/Hashtable; 118
+Ljava/lang/ThreadGroup;.mainThreadGroup:Ljava/lang/ThreadGroup; 118
+Ldalvik/system/RuntimeHooks; 118
+Landroid/nfc/NfcFrameworkInitializer; 118
+Landroid/os/Looper; 118
+Landroid/os/LocaleList; 118
+Ldalvik/system/SocketTagger; 118
+Landroid/icu/util/TimeZone; 118
+Landroid/util/ArraySet; 118
+Ljava/util/logging/LogManager;.manager:Ljava/util/logging/LogManager;.systemContext:Ljava/util/logging/LogManager$LoggerContext;.root:Ljava/util/logging/LogManager$LogNode; 118
+Landroid/os/BinderProxy;.sProxyMap:Landroid/os/BinderProxy$ProxyMap;.mMainIndexValues:[Ljava/util/ArrayList; 118
+Ljava/util/Random;.seedUniquifier:Ljava/util/concurrent/atomic/AtomicLong; 118
+Landroid/app/ActivityThread; 118
+Landroid/os/Binder; 118
+Ljava/lang/ThreadLocal;.nextHashCode:Ljava/util/concurrent/atomic/AtomicInteger; 119
+Landroid/os/Parcel; 120
+Landroid/system/UnixSocketAddress; 120
+Ljava/lang/ThreadGroup;.systemThreadGroup:Ljava/lang/ThreadGroup; 120
+Ljava/lang/Daemons$FinalizerDaemon;.INSTANCE:Ljava/lang/Daemons$FinalizerDaemon; 120
+Landroid/os/Parcel;.sPairedCreators:Ljava/util/HashMap; 120
+Ljava/lang/Thread; 120
+Landroid/os/Parcel;.mCreators:Ljava/util/HashMap; 120
+Ljava/lang/Daemons$FinalizerDaemon;.INSTANCE:Ljava/lang/Daemons$FinalizerDaemon;.progressCounter:Ljava/util/concurrent/atomic/AtomicInteger; 120
+Landroid/system/StructPollfd; 120
+Ljava/lang/Daemons$HeapTaskDaemon;.INSTANCE:Ljava/lang/Daemons$HeapTaskDaemon; 120
+Landroid/system/StructTimeval; 120
+Ldalvik/system/VMRuntime;.THE_ONE:Ldalvik/system/VMRuntime;.allocationCount:Ljava/util/concurrent/atomic/AtomicInteger; 120
+Ljava/lang/Daemons$ReferenceQueueDaemon;.INSTANCE:Ljava/lang/Daemons$ReferenceQueueDaemon;.progressCounter:Ljava/util/concurrent/atomic/AtomicInteger; 120
+Landroid/os/GraphicsEnvironment;.sInstance:Landroid/os/GraphicsEnvironment; 120
+Ljava/lang/Daemons$FinalizerWatchdogDaemon;.INSTANCE:Ljava/lang/Daemons$FinalizerWatchdogDaemon; 120
+Ljava/lang/ref/FinalizerReference; 120
+Landroid/os/Process; 120
+Ljava/lang/Daemons$ReferenceQueueDaemon;.INSTANCE:Ljava/lang/Daemons$ReferenceQueueDaemon; 120
+Lcom/android/internal/os/BinderInternal; 120
+Landroid/app/ApplicationLoaders;.gApplicationLoaders:Landroid/app/ApplicationLoaders;.mLoaders:Landroid/util/ArrayMap; 121
+Landroid/app/DexLoadReporter;.INSTANCE:Landroid/app/DexLoadReporter;.mDataDirs:Ljava/util/Set;.map:Ljava/util/HashMap; 122
+Ldalvik/system/BaseDexClassLoader; 122
+Landroid/renderscript/RenderScriptCacheDir; 122
+Landroid/graphics/Compatibility; 123
+Llibcore/io/Libcore; 123
+Landroid/provider/FontsContract; 123
+Ljava/security/Security;.version:Ljava/util/concurrent/atomic/AtomicInteger; 123
+Llibcore/net/NetworkSecurityPolicy; 123
+Lsun/security/jca/Providers; 123
+Landroid/graphics/Canvas; 123
+Landroid/os/StrictMode; 124
+Landroid/content/pm/PackageManager;.sPackageInfoCache:Landroid/app/PropertyInvalidatedCache; 125
+Lcom/android/internal/os/StatsdHiddenApiUsageLogger;.sInstance:Lcom/android/internal/os/StatsdHiddenApiUsageLogger; 126
+Ljava/util/logging/LogManager;.manager:Ljava/util/logging/LogManager;.loggerRefQueue:Ljava/lang/ref/ReferenceQueue; 127
+Landroid/view/WindowManagerGlobal; 128
+Lcom/android/internal/util/function/pooled/PooledLambdaImpl;.sPool:Lcom/android/internal/util/function/pooled/PooledLambdaImpl$Pool; 129
+Lcom/android/internal/util/function/pooled/PooledLambdaImpl;.sPool:Lcom/android/internal/util/function/pooled/PooledLambdaImpl$Pool;.mPool:[Ljava/lang/Object; 129
+Landroid/view/inputmethod/InputMethodManager; 130
+Landroid/media/MediaRouter; 131
+Landroid/hardware/SensorPrivacyManager; 132
+Landroid/os/storage/StorageManager; 133
+Landroid/view/contentcapture/ContentCaptureManager; 134
+Landroid/hardware/input/InputManager; 134
+Landroid/app/people/PeopleManager; 134
+Landroid/media/session/MediaSessionManager; 134
+Landroid/security/attestationverification/AttestationVerificationManager; 134
+Landroid/net/vcn/VcnManager; 134
+Landroid/os/RecoverySystem; 134
+Landroid/net/NetworkPolicyManager; 134
+Landroid/net/wifi/sharedconnectivity/app/SharedConnectivityManager; 134
+Landroid/permission/PermissionControllerManager; 134
+Landroid/app/tare/EconomyManager; 134
+Landroid/view/translation/TranslationManager; 134
+Landroid/view/textclassifier/TextClassificationManager; 134
+Landroid/view/autofill/AutofillManager; 134
+Landroid/os/SystemConfigManager; 134
+Landroid/view/LayoutInflater; 134
+Landroid/credentials/CredentialManager; 134
+Landroid/service/persistentdata/PersistentDataBlockManager; 134
+Landroid/view/textservice/TextServicesManager; 134
+Landroid/app/admin/DevicePolicyManager; 134
+Ljava/lang/StackStreamFactory; 134
+Landroid/view/WindowManager; 134
+Landroid/app/contentsuggestions/ContentSuggestionsManager; 134
+Landroid/media/tv/tunerresourcemanager/TunerResourceManager; 134
+Landroid/telephony/SubscriptionManager; 134
+Landroid/os/HardwarePropertiesManager; 134
+Landroid/media/AudioManager; 135
+Landroid/telephony/TelephonyManager; 136
+Landroid/util/ArrayMap; 137
+Landroid/app/QueuedWork; 138
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.0:Ljava/util/WeakHashMap$Entry; 139
+Ljava/lang/Enum;.sharedConstantsCache:Llibcore/util/BasicLruCache;.map:Ljava/util/LinkedHashMap; 140
+Ljava/util/concurrent/ScheduledThreadPoolExecutor;.sequencer:Ljava/util/concurrent/atomic/AtomicLong; 141
+Landroid/util/Log; 142
+Ljava/util/Collections$SynchronizedCollection; 143
+Ljava/util/Set; 143
+Ljava/util/Collections$SynchronizedSet; 143
+Ljava/util/Collection; 143
+Ljava/lang/Integer;.SMALL_NONNEG_VALUES:[Ljava/lang/String; 144
+Landroid/content/ComponentName; 145
+Landroid/view/textclassifier/TextLanguage;.EMPTY:Landroid/view/textclassifier/TextLanguage;.mBundle:Landroid/os/Bundle; 146
+Landroid/os/PersistableBundle;.EMPTY:Landroid/os/PersistableBundle; 147
+Landroid/icu/impl/locale/BaseLocale;.CACHE:Landroid/icu/impl/locale/BaseLocale$Cache;._map:Ljava/util/concurrent/ConcurrentHashMap; 148
+Ljava/util/GregorianCalendar; 149
+Ljava/text/DontCareFieldPosition;.INSTANCE:Ljava/text/FieldPosition; 150
+Landroid/app/UiModeManager; 151
+Ljdk/internal/access/SharedSecrets; 152
+Landroid/icu/impl/ZoneMeta;.CANONICAL_ID_CACHE:Landroid/icu/impl/ICUCache; 153
+Landroid/icu/impl/ZoneMeta;.SYSTEM_ZONE_CACHE:Landroid/icu/impl/ZoneMeta$SystemTimeZoneCache;.map:Ljava/util/concurrent/ConcurrentHashMap; 154
+Ljava/time/ZoneOffset;.ID_CACHE:Ljava/util/concurrent/ConcurrentMap; 155
+Ljava/time/ZoneOffset;.ID_CACHE:Ljava/util/concurrent/ConcurrentMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node; 155
+Ljava/time/ZoneOffset;.SECONDS_CACHE:Ljava/util/concurrent/ConcurrentMap; 155
+Ljava/time/ZoneOffset;.SECONDS_CACHE:Ljava/util/concurrent/ConcurrentMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node;.0:Ljava/util/concurrent/ConcurrentHashMap$Node;.next:Ljava/util/concurrent/ConcurrentHashMap$Node; 155
+Ljava/time/ZoneOffset;.SECONDS_CACHE:Ljava/util/concurrent/ConcurrentMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node; 155
+Landroid/widget/TextView; 156
+Landroid/view/ViewGroup$ChildListForAutoFillOrContentCapture;.sPool:Landroid/util/Pools$SimplePool;.mPool:[Ljava/lang/Object; 157
+Landroid/view/ViewGroup$ChildListForAutoFillOrContentCapture;.sPool:Landroid/util/Pools$SimplePool; 157
+Landroid/view/ViewGroup; 158
+Landroid/graphics/Rect; 159
+Landroid/view/View$BaseSavedState; 160
+Landroid/widget/Button; 161
+Landroid/widget/ImageButton; 162
+Landroid/view/View$OnHoverListener; 163
+Landroid/widget/Toolbar; 164
+Landroid/hardware/display/ColorDisplayManager$ColorDisplayManagerInternal; 165
+Landroid/app/WallpaperManager; 166
+Landroid/graphics/ColorSpace$Model;.RGB:Landroid/graphics/ColorSpace$Model; 166
+Landroid/graphics/drawable/AdaptiveIconDrawable; 167
+Landroid/animation/ValueAnimator$DurationScaleChangeListener; 168
+Landroid/widget/Toast; 168
+Landroid/app/smartspace/SmartspaceSession$OnTargetsAvailableListener; 168
+Landroid/view/CrossWindowBlurListeners; 168
+Landroid/app/servertransaction/ActivityRelaunchItem; 169
+[Ljava/util/concurrent/ForkJoinTask; 169
+Landroid/view/WindowManager$LayoutParams; 169
+Ljava/util/concurrent/ForkJoinPool$WorkQueue; 169
+Landroid/app/prediction/AppTargetEvent; 169
+Lorg/xmlpull/v1/XmlPullParserException; 169
+Landroid/app/servertransaction/ObjectPool;.sPoolMap:Ljava/util/Map; 170
+Landroid/app/servertransaction/ClientTransaction; 170
+Landroid/app/servertransaction/StopActivityItem; 170
+Landroid/system/ErrnoException; 171
+Landroid/hardware/location/ContextHubTransaction$OnCompleteListener; 172
+Landroid/app/PendingIntent$OnFinished; 172
+Ljava/lang/NullPointerException; 173
+Landroid/os/strictmode/DiskReadViolation; 174
+Lorg/apache/http/params/HttpParams; 175
+Landroid/nfc/cardemulation/CardEmulation; 176
+Ljava/io/FileDescriptor; 177
+Landroid/content/pm/PackageManager$OnPermissionsChangedListener; 178
+Landroid/security/keystore2/KeyStoreCryptoOperationUtils; 179
+Landroid/app/ActivityTaskManager; 180
+Landroid/util/EventLog; 181
+Ljava/net/URLConnection; 181
+Ljava/net/SocketException; 181
+Ljava/lang/reflect/InvocationTargetException; 181
+Ljava/lang/Enum; 182
+Landroid/widget/AbsListView$SelectionBoundsAdjuster; 183
+Ljava/lang/ClassNotFoundException; 183
+Landroid/content/SyncStatusObserver; 184
+Landroid/content/AsyncTaskLoader$LoadTask; 185
+Landroid/app/LoaderManager$LoaderCallbacks; 185
+Landroid/webkit/CookieSyncManager; 186
+Landroid/webkit/WebViewProvider$ViewDelegate; 187
+Landroid/webkit/WebView; 187
+Landroid/webkit/WebViewProvider$ScrollDelegate; 187
+Landroid/webkit/WebViewProvider; 187
+Landroid/webkit/WebViewFactory;.sTimestamps:Landroid/webkit/WebViewFactory$StartupTimestamps; 188
+Landroid/webkit/WebViewFactoryProvider; 189
+Landroid/webkit/WebViewFactory; 190
+Landroid/os/PowerManager$OnThermalStatusChangedListener; 191
+Landroid/os/Bundle; 192
+Landroid/widget/ProgressBar; 193
+Landroid/graphics/Bitmap$Config;.ALPHA_8:Landroid/graphics/Bitmap$Config; 194
+Landroid/graphics/Bitmap$Config;.RGB_565:Landroid/graphics/Bitmap$Config; 194
+Landroid/graphics/Bitmap$Config;.RGBA_1010102:Landroid/graphics/Bitmap$Config; 194
+Landroid/renderscript/Allocation;.mBitmapOptions:Landroid/graphics/BitmapFactory$Options;.inPreferredConfig:Landroid/graphics/Bitmap$Config; 194
+Landroid/graphics/Bitmap$Config;.RGBA_F16:Landroid/graphics/Bitmap$Config; 194
+Landroid/graphics/Bitmap$Config;.ARGB_4444:Landroid/graphics/Bitmap$Config; 194
+Landroid/graphics/Bitmap$Config;.HARDWARE:Landroid/graphics/Bitmap$Config; 194
+Landroid/graphics/drawable/StateListDrawable; 195
+Landroid/view/PointerIcon;.gSystemIconsByDisplay:Landroid/util/SparseArray; 196
+Landroid/view/PointerIcon; 196
+Ljavax/net/ssl/SSLServerSocketFactory; 197
+Ljavax/net/ssl/SSLSocketFactory; 198
+Ljavax/net/ssl/HttpsURLConnection$NoPreloadHolder; 198
+Ljavax/net/ssl/SSLSessionContext; 199
+Lcom/android/org/bouncycastle/crypto/CryptoServicesRegistrar; 200
+Lsun/security/x509/PKIXExtensions;.KeyUsage_Id:Lsun/security/util/ObjectIdentifier; 201
+Lsun/security/x509/PKIXExtensions;.PolicyConstraints_Id:Lsun/security/util/ObjectIdentifier; 201
+Ljava/security/cert/PKIXRevocationChecker$Option;.ONLY_END_ENTITY:Ljava/security/cert/PKIXRevocationChecker$Option; 201
+Lsun/security/x509/PKIXExtensions;.ExtendedKeyUsage_Id:Lsun/security/util/ObjectIdentifier; 201
+Lsun/security/provider/X509Factory;.certCache:Lsun/security/util/Cache; 201
+Lsun/security/x509/PKIXExtensions;.CertificatePolicies_Id:Lsun/security/util/ObjectIdentifier; 201
+Lsun/security/x509/PKIXExtensions;.NameConstraints_Id:Lsun/security/util/ObjectIdentifier; 201
+Lsun/security/x509/PKIXExtensions;.AuthorityKey_Id:Lsun/security/util/ObjectIdentifier; 201
+Lsun/security/provider/X509Factory;.certCache:Lsun/security/util/Cache;.cacheMap:Ljava/util/Map; 201
+Ljava/security/cert/PKIXRevocationChecker$Option;.NO_FALLBACK:Ljava/security/cert/PKIXRevocationChecker$Option; 201
+Lsun/security/x509/PKIXExtensions;.SubjectAlternativeName_Id:Lsun/security/util/ObjectIdentifier; 201
+Lsun/security/x509/PKIXExtensions;.PolicyMappings_Id:Lsun/security/util/ObjectIdentifier; 202
+Lsun/security/x509/PKIXExtensions;.InhibitAnyPolicy_Id:Lsun/security/util/ObjectIdentifier; 202
+Lsun/security/x509/PKIXExtensions;.BasicConstraints_Id:Lsun/security/util/ObjectIdentifier; 202
+Ljava/security/Security;.spiMap:Ljava/util/Map; 203
+Lsun/security/x509/X500Name;.commonName_oid:Lsun/security/util/ObjectIdentifier; 204
+Lsun/security/x509/X500Name;.countryName_oid:Lsun/security/util/ObjectIdentifier; 204
+Lsun/security/x509/X500Name;.orgName_oid:Lsun/security/util/ObjectIdentifier; 204
+Ljava/nio/charset/Charset;.cache2:Ljava/util/HashMap; 205
+Ljava/net/URL;.handlers:Ljava/util/Hashtable;.table:[Ljava/util/Hashtable$HashtableEntry; 206
+Ljava/net/URL;.handlers:Ljava/util/Hashtable; 206
+Ljava/net/Inet6AddressImpl;.addressCache:Ljava/net/AddressCache;.cache:Llibcore/util/BasicLruCache;.map:Ljava/util/LinkedHashMap; 207
+Ljava/net/Proxy$Type;.DIRECT:Ljava/net/Proxy$Type; 208
+Ljava/net/ProxySelector;.theProxySelector:Ljava/net/ProxySelector; 208
+Lcom/android/okhttp/okio/SegmentPool; 209
+Lcom/android/okhttp/internal/http/AuthenticatorAdapter;.INSTANCE:Lcom/android/okhttp/Authenticator; 209
+Lcom/android/okhttp/HttpsHandler;.HTTP_1_1_ONLY:Ljava/util/List;.element:Ljava/lang/Object; 209
+Lcom/android/okhttp/ConfigAwareConnectionPool;.instance:Lcom/android/okhttp/ConfigAwareConnectionPool;.networkEventDispatcher:Llibcore/net/event/NetworkEventDispatcher;.listeners:Ljava/util/List; 210
+Lcom/android/okhttp/Dns;.SYSTEM:Lcom/android/okhttp/Dns; 210
+Lcom/android/okhttp/ConfigAwareConnectionPool;.instance:Lcom/android/okhttp/ConfigAwareConnectionPool; 210
+Lcom/android/okhttp/okio/AsyncTimeout; 211
+Ljava/lang/IllegalAccessException; 212
+Ljavax/net/ssl/SSLContext; 213
+Ljavax/net/ssl/HttpsURLConnection; 213
+Ljava/security/Security;.props:Ljava/util/Properties;.map:Ljava/util/concurrent/ConcurrentHashMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node;.12:Ljava/util/concurrent/ConcurrentHashMap$Node;.next:Ljava/util/concurrent/ConcurrentHashMap$Node; 214
+Ljava/security/Security;.props:Ljava/util/Properties;.map:Ljava/util/concurrent/ConcurrentHashMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node;.30:Ljava/util/concurrent/ConcurrentHashMap$Node; 214
+Landroid/database/sqlite/SQLiteTransactionListener; 215
+Landroid/accounts/OnAccountsUpdateListener; 216
+Landroid/accounts/AccountManager$20; 217
+Lsun/nio/ch/FileChannelImpl$Unmapper; 218
+Landroid/content/res/Resources;.sResourcesHistory:Ljava/util/Set;.c:Ljava/util/Collection;.m:Ljava/util/Map;.queue:Ljava/lang/ref/ReferenceQueue; 219
+Landroid/text/method/SingleLineTransformationMethod; 220
+Landroid/widget/RelativeLayout; 221
+Landroid/graphics/drawable/BitmapDrawable; 222
+Landroid/graphics/drawable/GradientDrawable; 223
+Landroid/animation/PropertyValuesHolder;.sGetterPropertyMap:Ljava/util/HashMap; 224
+Landroid/animation/PropertyValuesHolder$FloatPropertyValuesHolder;.sJNISetterPropertyMap:Ljava/util/HashMap; 225
+Landroid/graphics/drawable/Drawable;.DEFAULT_TINT_MODE:Landroid/graphics/PorterDuff$Mode; 226
+Landroid/text/StaticLayout$Builder;.sPool:Landroid/util/Pools$SynchronizedPool; 227
+Landroid/text/StaticLayout$Builder;.sPool:Landroid/util/Pools$SynchronizedPool;.mPool:[Ljava/lang/Object; 227
+Ljava/util/concurrent/ThreadLocalRandom; 228
+Landroid/widget/Space; 229
+Landroid/widget/ScrollView; 230
+Landroid/text/style/LineHeightSpan; 231
+Landroid/text/style/TabStopSpan; 232
+Landroid/text/style/ReplacementSpan; 233
+Landroid/text/style/MetricAffectingSpan; 233
+Landroid/text/style/LeadingMarginSpan; 233
+Landroid/text/style/LineBackgroundSpan; 234
+Landroid/text/style/CharacterStyle; 235
+Landroid/text/style/SuggestionSpan; 236
+Landroid/widget/TextView$ChangeWatcher; 237
+Landroid/text/DynamicLayout$Builder;.sPool:Landroid/util/Pools$SynchronizedPool;.mPool:[Ljava/lang/Object; 238
+Landroid/text/DynamicLayout; 238
+Landroid/text/DynamicLayout$ChangeWatcher; 238
+Landroid/text/style/WrapTogetherSpan; 238
+Landroid/text/DynamicLayout$Builder;.sPool:Landroid/util/Pools$SynchronizedPool; 238
+Landroid/text/method/LinkMovementMethod; 239
+Landroid/text/style/ClickableSpan; 240
+Ljava/util/logging/LogRecord;.globalSequenceNumber:Ljava/util/concurrent/atomic/AtomicLong; 241
+Ljava/lang/Runtime;.currentRuntime:Ljava/lang/Runtime; 242
+Landroid/content/pm/LauncherActivityInfo; 243
+Landroid/database/sqlite/SQLiteMisuseException; 243
+Landroid/speech/tts/TextToSpeech$Connection$SetupConnectionAsyncTask; 243
+Landroid/database/sqlite/SQLiteCantOpenDatabaseException; 243
+Landroid/database/sqlite/SQLiteDatabaseCorruptException; 243
+Landroid/database/sqlite/SQLiteDatabaseLockedException; 243
+Ljava/util/Map$Entry; 243
+Ljava/util/zip/ZipException; 243
+Landroid/database/sqlite/SQLiteAccessPermException; 243
+Landroid/speech/tts/TextToSpeech$OnInitListener; 243
+Landroid/app/Notification$MessagingStyle; 244
+Landroid/text/TextUtils$TruncateAt; 245
+Landroid/app/smartspace/SmartspaceTarget; 246
+Landroid/app/prediction/AppTarget; 246
+Landroid/app/smartspace/uitemplatedata/BaseTemplateData; 246
+Landroid/location/LocationManager;.sLocationListeners:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry; 247
+Landroid/location/LocationManager;.sLocationListeners:Ljava/util/WeakHashMap; 247
+Landroid/service/notification/ConditionProviderService; 248
+Landroid/os/WorkSource; 249
+Landroid/security/keystore2/AndroidKeyStoreProvider; 249
+Ljava/net/Socket; 249
+Lcom/android/internal/listeners/ListenerTransport; 249
+Landroid/os/ParcelUuid; 250
+Landroid/telephony/emergency/EmergencyNumber; 251
+Lcom/android/internal/telephony/uicc/UiccProfile$4; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$IncomingSms; 251
+Lcom/android/internal/telephony/SmsStorageMonitor$1; 251
+Lcom/android/internal/telephony/TelephonyDevController; 251
+Lcom/android/internal/telephony/uicc/UiccController; 251
+Lcom/android/internal/telephony/emergency/EmergencyNumberTracker$1; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$DataCallSession; 251
+Lcom/android/internal/telephony/TelephonyDevController;.mSims:Ljava/util/ArrayList; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$RcsAcsProvisioningStats; 251
+Ljava/lang/UnsupportedOperationException; 251
+Landroid/database/CursorToBulkCursorAdaptor; 251
+Lcom/android/internal/telephony/satellite/PointingAppController; 251
+Landroid/telephony/ModemActivityInfo; 251
+Lcom/android/internal/telephony/imsphone/ImsPhone; 251
+Lcom/android/internal/telephony/ServiceStateTracker; 251
+Lcom/android/internal/telephony/IccSmsInterfaceManager; 251
+Lcom/android/internal/telephony/util/NotificationChannelController$1; 251
+Lcom/android/internal/telephony/RilWakelockInfo; 251
+Lcom/android/internal/telephony/gsm/GsmInboundSmsHandler$GsmCbTestBroadcastReceiver; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$SipTransportFeatureTagStats; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$UceEventStats; 251
+Lcom/android/internal/telephony/euicc/EuiccConnector$BindingState; 251
+Lcom/android/internal/telephony/ims/ImsResolver$3; 251
+Landroid/net/NetworkPolicyManager$SubscriptionCallbackProxy; 251
+Lcom/android/internal/telephony/TelephonyDevController;.mModems:Ljava/util/ArrayList; 251
+Landroid/telephony/ims/aidl/IImsServiceController$Stub$Proxy; 251
+Lcom/android/internal/telephony/CarrierPrivilegesTracker$1; 251
+Lcom/android/internal/telephony/CommandException; 251
+Lcom/android/ims/FeatureConnector$1; 251
+Lcom/android/internal/telephony/IWapPushManager; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$SipDelegateStats; 251
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker; 251
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mTtyModeReceivedRegistrants:Lcom/android/internal/telephony/RegistrantList;.registrants:Ljava/util/ArrayList; 251
+Landroid/view/textclassifier/TextLanguage;.EMPTY:Landroid/view/textclassifier/TextLanguage;.mBundle:Landroid/os/Bundle;.mClassLoader:Ljava/lang/ClassLoader; 251
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mMmiCompleteRegistrants:Lcom/android/internal/telephony/RegistrantList;.registrants:Ljava/util/ArrayList; 251
+Lcom/android/i18n/timezone/TelephonyLookup; 251
+Landroid/telephony/BarringInfo$BarringServiceInfo; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$NetworkRequests; 251
+Lcom/android/internal/telephony/euicc/EuiccConnector$ConnectedState$14; 251
+Lcom/android/internal/telephony/SmsBroadcastUndelivered; 251
+Lcom/android/internal/telephony/LocaleTracker; 251
+Lcom/android/internal/telephony/PhoneSubInfoController; 251
+Lcom/android/internal/telephony/CarrierKeyDownloadManager$1; 251
+Lcom/android/internal/telephony/GsmCdmaCallTracker$1; 251
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.339:[Ljava/lang/String; 251
+Lcom/android/internal/telephony/ServiceStateTracker$1; 251
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.353:[Ljava/lang/String; 251
+Lcom/android/internal/telephony/euicc/EuiccCardController$SimSlotStatusChangedBroadcastReceiver; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$PresenceNotifyEvent; 251
+Lcom/android/internal/telephony/SimActivationTracker$1; 251
+Landroid/telephony/ModemInfo; 251
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.1393:[Ljava/lang/String; 251
+Landroid/telephony/CellSignalStrengthWcdma; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteProvision; 251
+Lcom/android/internal/telephony/PhoneConfigurationManager; 251
+Lcom/android/internal/telephony/SmsApplication$SmsPackageMonitor; 251
+Landroid/telephony/TelephonyRegistryManager$3; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$VoiceCallSession; 251
+Landroid/os/Handler$MessengerImpl; 251
+Lcom/android/internal/telephony/LocaleTracker$1; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$CellularDataServiceSwitch; 251
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mInCallVoicePrivacyOffRegistrants:Lcom/android/internal/telephony/RegistrantList;.registrants:Ljava/util/ArrayList; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteSosMessageRecommender; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsRegistrationServiceDescStats; 251
+Lcom/android/internal/telephony/uicc/UiccPkcs15$Pkcs15Selector; 251
+Lcom/android/internal/telephony/CarrierResolver$2; 251
+Lcom/android/internal/telephony/CarrierActionAgent$1; 251
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mPhones:Ljava/util/ArrayList; 251
+Lcom/android/internal/telephony/SmsController; 251
+Lcom/android/internal/telephony/uicc/euicc/EuiccCardException; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsRegistrationTermination; 251
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.1125:[Ljava/lang/String; 251
+Lcom/android/internal/telephony/NetworkTypeController$1; 251
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.803:[Ljava/lang/String; 251
+Lcom/android/internal/telephony/uicc/asn1/TagNotFoundException; 251
+Lcom/android/internal/telephony/CarrierServiceBindHelper$1; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$CellularServiceState; 251
+Lcom/android/internal/telephony/cdma/CdmaSubscriptionSourceManager; 251
+Lcom/android/internal/telephony/InboundSmsHandler$NewMessageNotificationActionReceiver; 251
+Lcom/android/internal/telephony/CarrierActionAgent; 251
+Lcom/android/i18n/timezone/TimeZoneFinder; 251
+Lcom/android/internal/telephony/RILRequest; 251
+Lcom/android/internal/telephony/RIL;.sRilTimeHistograms:Landroid/util/SparseArray; 251
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.33:[Ljava/lang/String; 251
+Lcom/android/internal/telephony/MccTable; 251
+Lcom/android/internal/telephony/uicc/UiccProfile$2; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$CarrierIdMismatch; 251
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.1235:[Ljava/lang/String; 251
+Lcom/android/internal/telephony/uicc/UiccCarrierPrivilegeRules; 251
+Landroid/telephony/CellSignalStrengthTdscdma; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsDedicatedBearerListenerEvent; 251
+Lcom/android/internal/telephony/SmsDispatchersController; 251
+Landroid/timezone/TelephonyLookup; 251
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteOutgoingDatagram; 251
+Lcom/android/internal/telephony/SMSDispatcher$1; 251
+Lcom/android/internal/telephony/AppSmsManager; 251
+Landroid/timezone/TimeZoneFinder; 251
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mBackgroundCalls:Ljava/util/ArrayList; 251
+Lcom/android/ims/rcs/uce/eab/EabProvider; 251
+Lcom/android/internal/telephony/uicc/PinStorage$1; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsDedicatedBearerEvent; 251
+Landroid/telephony/CellSignalStrengthLte; 251
+Landroid/telephony/ims/ProvisioningManager$Callback$CallbackBinder; 251
+Lcom/android/ims/ImsManager;.IMS_STATS_CALLBACKS:Landroid/util/SparseArray;.mKeys:[I 251
+Landroid/telephony/CellSignalStrengthNr; 251
+Lcom/android/internal/telephony/SomeArgs; 251
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mInCallVoicePrivacyOnRegistrants:Lcom/android/internal/telephony/RegistrantList;.registrants:Ljava/util/ArrayList; 251
+Lcom/android/internal/telephony/StateMachine$SmHandler; 251
+Lcom/android/internal/telephony/PackageChangeReceiver; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$OutgoingShortCodeSms; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$NetworkRequestsV2; 251
+Lcom/android/internal/telephony/nano/TelephonyProto$RilDataCall; 251
+Lcom/android/internal/telephony/euicc/EuiccConnector$AvailableState; 251
+Lcom/android/ims/internal/IImsServiceFeatureCallback$Stub$Proxy; 251
+Landroid/telephony/data/ApnSetting;.APN_TYPE_INT_MAP:Ljava/util/Map; 251
+Lcom/android/internal/telephony/RadioInterfaceCapabilityController; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsRegistrationStats; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$VoiceCallRatUsage; 251
+Lcom/android/internal/telephony/metrics/TelephonyMetrics; 251
+Lcom/android/internal/telephony/nano/TelephonyProto$TelephonyCallSession$Event$RilCall; 251
+Lcom/android/internal/telephony/NetworkRegistrationManager$NetworkRegStateCallback; 251
+Lcom/android/internal/telephony/cdma/CdmaInboundSmsHandler; 251
+Lcom/android/internal/telephony/euicc/EuiccConnector$ConnectedState; 251
+Lcom/android/internal/telephony/RadioConfig; 251
+Lcom/android/internal/telephony/euicc/EuiccConnector$DisconnectedState; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteSession; 251
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mDisplayInfoRegistrants:Lcom/android/internal/telephony/RegistrantList;.registrants:Ljava/util/ArrayList; 251
+Lcom/android/phone/ecc/nano/ProtobufEccData$EccInfo; 251
+Lcom/android/internal/telephony/GsmCdmaPhone; 251
+Lcom/android/internal/telephony/TelephonyTester$1; 251
+Lcom/android/internal/telephony/cdma/CdmaInboundSmsHandler$CdmaScpTestBroadcastReceiver; 251
+Lcom/android/internal/telephony/NetworkTypeController$DefaultState; 251
+Landroid/net/TelephonyNetworkSpecifier; 251
+Lcom/android/internal/telephony/NitzStateMachine; 251
+Landroid/app/timezonedetector/TimeZoneDetector; 251
+Lcom/android/internal/telephony/IntentBroadcaster$1; 251
+Lcom/android/internal/telephony/uicc/UiccStateChangedLauncher; 251
+Lcom/android/internal/telephony/ims/ImsResolver$1; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$OutgoingSms; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$UnmeteredNetworks; 251
+Landroid/view/textclassifier/TextLanguage;.EMPTY:Landroid/view/textclassifier/TextLanguage;.mBundle:Landroid/os/Bundle;.mClassLoader:Ljava/lang/ClassLoader;.packages:Ljava/util/Map;.m:Ljava/util/Map; 251
+Lcom/android/internal/telephony/euicc/EuiccController; 251
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mForegroundCalls:Ljava/util/ArrayList; 251
+Lcom/android/internal/telephony/satellite/SatelliteModemInterface; 251
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.531:[Ljava/lang/String; 251
+Lcom/android/ims/ImsManager;.IMS_STATS_CALLBACKS:Landroid/util/SparseArray; 251
+Lcom/android/internal/telephony/euicc/EuiccConnector$1; 251
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.467:[Ljava/lang/String; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$SipMessageResponse; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$SipTransportSession; 251
+Lcom/android/internal/telephony/euicc/EuiccConnector$UnavailableState; 251
+Lcom/android/internal/telephony/DeviceStateMonitor$3; 251
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mSignalInfoRegistrants:Lcom/android/internal/telephony/RegistrantList;.registrants:Ljava/util/ArrayList; 251
+Lcom/android/ims/ImsManager;.IMS_STATS_CALLBACKS:Landroid/util/SparseArray;.mValues:[Ljava/lang/Object; 251
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager; 251
+Lcom/android/internal/telephony/DisplayInfoController; 251
+Lcom/android/internal/telephony/ims/ImsResolver$2; 251
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.1377:[Ljava/lang/String; 251
+Lcom/android/internal/telephony/nano/TelephonyProto$TelephonyServiceState$NetworkRegistrationInfo; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteController; 251
+Landroid/telephony/ims/RegistrationManager$RegistrationCallback$RegistrationBinder; 251
+Lcom/android/internal/telephony/imsphone/ImsExternalCallTracker; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$EmergencyNumbersInfo; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$GbaEvent; 251
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.23:[Ljava/lang/String; 251
+Landroid/telephony/CellSignalStrengthCdma; 251
+Landroid/telephony/TelephonyLocalConnection; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteIncomingDatagram; 251
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker$2; 251
+Lcom/android/internal/telephony/ims/ImsResolver; 251
+Lcom/android/internal/telephony/SmsStorageMonitor; 251
+Lcom/android/internal/telephony/uicc/UiccProfile; 251
+Landroid/telephony/ims/ImsMmTelManager$CapabilityCallback$CapabilityBinder; 251
+Lcom/android/internal/telephony/euicc/EuiccCardController; 251
+Lcom/android/internal/telephony/SmsBroadcastUndelivered$1; 251
+Lcom/android/internal/telephony/GsmCdmaCallTracker; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$RcsClientProvisioningStats; 251
+Lcom/android/internal/telephony/cat/CatService; 251
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.761:[Ljava/lang/String; 251
+Lcom/android/internal/telephony/SmsApplication; 251
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mDisconnectRegistrants:Lcom/android/internal/telephony/RegistrantList;.registrants:Ljava/util/ArrayList; 251
+Lcom/android/internal/telephony/PhoneFactory; 251
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mHandlerMap:Ljava/util/HashMap; 251
+Landroid/os/AsyncResult; 251
+Lcom/android/internal/telephony/ProxyController; 251
+Lcom/android/internal/telephony/cdma/CdmaInboundSmsHandler$CdmaCbTestBroadcastReceiver; 251
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.453:[Ljava/lang/String; 251
+Lcom/android/internal/telephony/MultiSimSettingController; 251
+Ljava/io/BufferedReader; 251
+Landroid/telephony/CellSignalStrengthGsm; 251
+Lcom/android/internal/telephony/SimActivationTracker; 251
+Lcom/android/internal/telephony/CellBroadcastServiceManager; 251
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mRingingCalls:Ljava/util/ArrayList; 251
+Lcom/android/internal/telephony/IntentBroadcaster; 251
+Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsRegistrationFeatureTagStats; 251
+Lcom/android/internal/telephony/euicc/EuiccConnector$EuiccPackageMonitor; 251
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mSuppServiceFailedRegistrants:Lcom/android/internal/telephony/RegistrantList;.registrants:Ljava/util/ArrayList; 251
+Landroid/view/textclassifier/TextLanguage;.EMPTY:Landroid/view/textclassifier/TextLanguage;.mBundle:Landroid/os/Bundle;.mClassLoader:Ljava/lang/ClassLoader;.packages:Ljava/util/Map;.m:Ljava/util/Map;.table:[Ljava/util/HashMap$Node; 251
+Lcom/android/internal/telephony/CarrierServiceBindHelper$CarrierServicePackageMonitor; 251
+Lcom/android/internal/telephony/TelephonyComponentFactory; 251
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.637:[Ljava/lang/String; 251
+Lcom/android/phone/ecc/nano/ProtobufEccData$CountryInfo; 251
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.651:[Ljava/lang/String; 251
+Lcom/android/internal/telephony/SmsUsageMonitor; 251
+Lcom/android/internal/telephony/CommandException$Error;.INVALID_SIM_STATE:Lcom/android/internal/telephony/CommandException$Error; 251
+Landroid/hardware/display/DisplayManagerGlobal$DisplayManagerCallback; 252
+Landroid/app/ActivityThread$ApplicationThread; 252
+Landroid/app/ActivityManager$MyUidObserver; 253
+Landroid/media/browse/MediaBrowser$ServiceCallbacks; 253
+Landroid/media/session/MediaController$CallbackStub; 253
+Landroid/media/session/MediaSessionManager$OnMediaKeyEventSessionChangedListener; 253
+Landroid/app/PendingIntent$CancelListener; 253
+Landroid/media/AudioManager$2; 253
+Landroid/database/ContentObserver$Transport; 253
+Landroid/media/session/MediaSessionManager$SessionsChangedWrapper$1; 253
+Landroid/content/ContentProvider$PipeDataWriter; 254
+Landroid/security/net/config/UserCertificateSource$NoPreloadHolder; 255
+Landroid/view/Window$Callback; 256
+Landroid/transition/TransitionManager;.sDefaultTransition:Landroid/transition/Transition;.mTransitions:Ljava/util/ArrayList;.elementData:[Ljava/lang/Object;.1:Landroid/transition/ChangeBounds;.mCurrentAnimators:Ljava/util/ArrayList; 256
+Landroid/transition/TransitionManager;.sDefaultTransition:Landroid/transition/Transition;.mTransitions:Ljava/util/ArrayList;.elementData:[Ljava/lang/Object;.2:Landroid/transition/Fade;.mCurrentAnimators:Ljava/util/ArrayList; 256
+Landroid/transition/TransitionManager;.sPendingTransitions:Ljava/util/ArrayList; 256
+Landroid/transition/TransitionManager;.sDefaultTransition:Landroid/transition/Transition;.mTransitions:Ljava/util/ArrayList;.elementData:[Ljava/lang/Object;.0:Landroid/transition/Fade;.mCurrentAnimators:Ljava/util/ArrayList; 256
+Landroid/view/AttachedSurfaceControl$OnBufferTransformHintChangedListener; 257
+Landroid/webkit/ValueCallback; 258
+Landroid/webkit/WebResourceRequest; 258
+Landroid/webkit/WebChromeClient$CustomViewCallback; 258
+Landroid/hardware/camera2/CameraCharacteristics;.INFO_SUPPORTED_HARDWARE_LEVEL:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 258
+Landroid/accounts/Account; 258
+Landroid/hardware/camera2/CameraCharacteristics;.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 258
+Landroid/hardware/camera2/CameraCharacteristics;.DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/CameraCharacteristics;.DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/CameraCharacteristics;.HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/CameraCharacteristics;.SCALER_AVAILABLE_STALL_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/CameraCharacteristics;.JPEGR_AVAILABLE_JPEG_R_MIN_FRAME_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/params/StreamConfigurationDuration; 259
+Landroid/hardware/camera2/CameraCharacteristics;.SCALER_AVAILABLE_STREAM_CONFIGURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/CameraCharacteristics;.DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/CameraCharacteristics;.JPEGR_AVAILABLE_JPEG_R_STALL_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/CameraCharacteristics;.DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/CameraCharacteristics;.SCALER_AVAILABLE_MIN_FRAME_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/CameraCharacteristics;.CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/CameraCharacteristics;.HEIC_AVAILABLE_HEIC_STALL_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/CameraCharacteristics;.JPEGR_AVAILABLE_JPEG_R_STREAM_CONFIGURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/CameraCharacteristics;.HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/params/HighSpeedVideoConfiguration; 259
+Landroid/hardware/camera2/CameraCharacteristics;.DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/CameraCharacteristics;.SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/CameraCharacteristics;.DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+I 259
+Landroid/hardware/camera2/CameraCharacteristics;.REQUEST_AVAILABLE_CAPABILITIES:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
+Landroid/hardware/camera2/params/StreamConfiguration; 259
+Z 260
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_INFO_PIXEL_ARRAY_SIZE:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.LENS_FOCAL_LENGTH:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.LENS_INFO_AVAILABLE_APERTURES:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.DISTORTION_CORRECTION_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.EXTENSION_STRENGTH:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+J 260
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_INFO_PHYSICAL_SIZE:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.TONEMAP_PRESET_CURVE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+B 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AF_TRIGGER:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AE_EXPOSURE_COMPENSATION:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+[D 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AWB_REGIONS:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.REQUEST_AVAILABLE_SESSION_KEYS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.SENSOR_EXPOSURE_TIME:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_CALIBRATION_TRANSFORM2:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.COLOR_CORRECTION_TRANSFORM:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/content/res/Resources$Theme; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AE_LOCK:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+F 260
+Landroid/hardware/camera2/CaptureRequest;.LENS_FILTER_DENSITY:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.LENS_OPTICAL_STABILIZATION_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.NOISE_REDUCTION_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.SENSOR_FRAME_DURATION:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AE_REGIONS:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_EXTENDED_SCENE_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.STATISTICS_OIS_DATA_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.SENSOR_TEST_PATTERN_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.HOT_PIXEL_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AE_ANTIBANDING_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.STATISTICS_LENS_SHADING_MAP_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.SCALER_CROP_REGION:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.LENS_FOCUS_DISTANCE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.TONEMAP_GAMMA:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_REFERENCE_ILLUMINANT2:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_REFERENCE_ILLUMINANT1:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+[F 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_ZOOM_RATIO:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.COLOR_CORRECTION_ABERRATION_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.TONEMAP_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.REQUEST_AVAILABLE_REQUEST_KEYS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.SCALER_ROTATE_AND_CROP:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.COLOR_CORRECTION_GAINS:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_COLOR_TRANSFORM1:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AF_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.SENSOR_SENSITIVITY:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.LENS_INFO_AVAILABLE_FOCAL_LENGTHS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_OPTICAL_BLACK_REGIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.JPEG_QUALITY:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.FLASH_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_POST_RAW_SENSITIVITY_BOOST:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AE_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_INFO_WHITE_LEVEL:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_SETTINGS_OVERRIDE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+[Landroid/hardware/camera2/params/MeteringRectangle; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AWB_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.LOGICAL_MULTI_CAMERA_PHYSICAL_IDS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_INFO_EXPOSURE_TIME_RANGE:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Ljava/lang/Float; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_ENABLE_ZSL:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.INFO_DEVICE_STATE_ORIENTATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_CALIBRATION_TRANSFORM1:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.EDGE_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_CAPTURE_INTENT:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_ORIENTATION:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.JPEG_ORIENTATION:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_COLOR_TRANSFORM2:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+[J 260
+Landroid/hardware/camera2/CameraCharacteristics;.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Ljava/util/concurrent/Phaser; 260
+Landroid/hardware/camera2/CaptureRequest;.BLACK_LEVEL_LOCK:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.COLOR_CORRECTION_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_SCENE_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.JPEG_THUMBNAIL_SIZE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.SHADING_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.STATISTICS_FACE_DETECT_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.STATISTICS_HOT_PIXEL_MAP_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AUTOFRAMING:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AE_TARGET_FPS_RANGE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AWB_LOCK:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.SENSOR_TEST_PATTERN_DATA:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AE_PRECAPTURE_TRIGGER:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.FLASH_STRENGTH_LEVEL:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_VIDEO_STABILIZATION_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.REPROCESS_EFFECTIVE_EXPOSURE_FACTOR:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Ljava/lang/Boolean; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_EFFECT_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.LENS_APERTURE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.JPEG_THUMBNAIL_QUALITY:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AF_REGIONS:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+Ljava/lang/Long; 260
+Landroid/hardware/camera2/CaptureRequest;.SENSOR_PIXEL_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
+[Ljava/lang/String; 261
+[Z 262
+Ljava/lang/Class$Caches;.genericInterfaces:Llibcore/util/BasicLruCache;.map:Ljava/util/LinkedHashMap; 263
+Ljava/util/Map; 264
+Ljava/nio/Bits; 265
+Ljava/nio/DirectByteBuffer; 266
+Ljava/io/File; 267
+Ljava/nio/ByteBuffer; 268
+Ljava/io/InputStream; 269
+Landroid/os/ParcelFileDescriptor; 270
+Landroid/os/BinderProxy;.sProxyMap:Landroid/os/BinderProxy$ProxyMap; 271
+Landroid/app/PendingIntent; 272
+Landroid/content/Intent; 273
+Landroid/net/Uri$HierarchicalUri; 274
+Landroid/net/Uri$StringUri; 275
+Landroid/net/Uri$PathPart;.EMPTY:Landroid/net/Uri$PathPart; 276
+Lcom/android/internal/telephony/MccTable;.FALLBACKS:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.6:Ljava/util/HashMap$Node;.key:Ljava/lang/Object; 277
+Landroid/icu/text/DecimalFormatSymbols;.cachedLocaleData:Landroid/icu/impl/CacheBase;.map:Ljava/util/concurrent/ConcurrentHashMap; 278
+Llibcore/icu/DecimalFormatData;.CACHE:Ljava/util/concurrent/ConcurrentHashMap; 279
+Landroid/icu/impl/CurrencyData;.provider:Landroid/icu/impl/CurrencyData$CurrencyDisplayInfoProvider; 280
+Lcom/android/internal/infra/AndroidFuture; 281
+Lcom/android/internal/util/LatencyTracker$Action; 282
+Landroid/app/AppOpsManager$Mode; 283
+Landroid/view/accessibility/AccessibilityManager$AccessibilityServicesStateChangeListener; 284
+Landroid/annotation/IdRes; 285
+Landroid/content/pm/PackageItemInfo; 286
+Ljava/util/Random; 287
+Landroid/widget/RadioButton; 288
+Lcom/android/internal/policy/PhoneWindow$PanelFeatureState$SavedState; 289
+Landroid/graphics/Insets; 290
+Landroid/view/View;.sNextGeneratedId:Ljava/util/concurrent/atomic/AtomicInteger; 291
+Landroid/graphics/drawable/LayerDrawable; 292
+Landroid/animation/LayoutTransition; 293
+Llibcore/reflect/AnnotationFactory;.cache:Ljava/util/Map; 294
+Llibcore/reflect/AnnotationFactory;.cache:Ljava/util/Map;.table:[Ljava/util/WeakHashMap$Entry; 294
+Ljava/lang/reflect/Proxy;.proxyClassCache:Ljava/lang/reflect/WeakCache;.reverseMap:Ljava/util/concurrent/ConcurrentMap; 295
+Ljava/lang/reflect/Proxy$ProxyClassFactory;.nextUniqueNumber:Ljava/util/concurrent/atomic/AtomicLong; 295
+Ljava/lang/reflect/Proxy;.proxyClassCache:Ljava/lang/reflect/WeakCache;.map:Ljava/util/concurrent/ConcurrentMap; 296
+Ljava/lang/Object; 297
+Ljava/lang/invoke/MethodType;.internTable:Ljava/lang/invoke/MethodType$ConcurrentWeakInternSet;.map:Ljava/util/concurrent/ConcurrentMap; 298
+Ljava/nio/channels/SocketChannel;.dexCache:Ljava/lang/Object; 298
+Ljava/lang/invoke/MethodType;.objectOnlyTypes:[Ljava/lang/invoke/MethodType; 299
+Ljava/util/concurrent/ForkJoinTask; 300
+Ljava/util/concurrent/CompletableFuture; 301
+Landroid/app/Notification$BigTextStyle; 302
+Landroid/content/pm/ApplicationInfo; 303
+Ljava/security/Signature;.signatureInfo:Ljava/util/Map;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node;.13:Ljava/util/concurrent/ConcurrentHashMap$Node;.next:Ljava/util/concurrent/ConcurrentHashMap$Node;.next:Ljava/util/concurrent/ConcurrentHashMap$Node; 304
+Lsun/security/x509/X500Name;.stateName_oid:Lsun/security/util/ObjectIdentifier; 305
+Lsun/security/x509/X500Name;.localityName_oid:Lsun/security/util/ObjectIdentifier; 306
+Lsun/security/x509/X500Name;.orgUnitName_oid:Lsun/security/util/ObjectIdentifier; 306
+Ljava/util/UUID; 307
+Landroid/app/slice/Slice; 308
+Ljava/util/Locale;.FRENCH:Ljava/util/Locale; 308
+Landroid/os/NullVibrator; 308
+Ldalvik/system/CloseGuard;.MESSAGE:Ljava/lang/String; 308
+Lsun/util/locale/BaseLocale$Cache;.CACHE:Lsun/util/locale/BaseLocale$Cache;.map:Ljava/util/concurrent/ConcurrentMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node;.22:Ljava/util/concurrent/ConcurrentHashMap$Node;.val:Ljava/lang/Object;.referent:Ljava/lang/Object; 308
+Ljava/util/Locale$Cache;.LOCALECACHE:Ljava/util/Locale$Cache;.map:Ljava/util/concurrent/ConcurrentMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node;.24:Ljava/util/concurrent/ConcurrentHashMap$Node;.val:Ljava/lang/Object;.referent:Ljava/lang/Object; 308
+Landroid/app/Activity$$ExternalSyntheticLambda0; 308
+Landroid/icu/impl/locale/BaseLocale;.CACHE:Landroid/icu/impl/locale/BaseLocale$Cache;._map:Ljava/util/concurrent/ConcurrentHashMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node;.0:Ljava/util/concurrent/ConcurrentHashMap$Node; 308
+Ljava/util/Locale;.ITALIAN:Ljava/util/Locale; 308
+Landroid/media/MediaRouter2Manager$Callback; 308
+Lsun/util/locale/BaseLocale$Cache;.CACHE:Lsun/util/locale/BaseLocale$Cache;.map:Ljava/util/concurrent/ConcurrentMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node;.29:Ljava/util/concurrent/ConcurrentHashMap$Node;.val:Ljava/lang/Object;.referent:Ljava/lang/Object; 308
+Ljava/util/Locale;.GERMAN:Ljava/util/Locale; 309
+Landroid/icu/impl/StandardPlural; 310
+Landroid/icu/impl/number/range/StandardPluralRanges; 311
+Landroid/icu/impl/PluralRulesLoader;.loader:Landroid/icu/impl/PluralRulesLoader; 311
+Landroid/icu/impl/PluralRulesLoader;.loader:Landroid/icu/impl/PluralRulesLoader;.pluralRulesCache:Ljava/util/Map; 311
+Landroid/icu/text/PluralRules$Operand; 311
+Landroid/icu/util/Calendar;.PATTERN_CACHE:Landroid/icu/impl/ICUCache; 312
+Landroid/icu/impl/DateNumberFormat;.CACHE:Landroid/icu/impl/SimpleCache; 313
+Landroid/text/format/DateFormat; 314
+Landroid/view/View$OnDragListener; 315
+Landroid/hardware/input/InputManager$InputDeviceListener; 316
+Landroid/hardware/input/InputManagerGlobal; 317
+Landroid/hardware/SystemSensorManager; 318
+Lcom/android/internal/os/BackgroundThread; 319
+Ljava/lang/Throwable; 320
+Landroid/app/NotificationManager; 321
+Landroid/app/NotificationChannel; 322
+Landroid/content/SharedPreferences$OnSharedPreferenceChangeListener; 323
+Landroid/content/pm/VersionedPackage; 324
+Landroid/app/AppOpsManager; 325
+Ldalvik/system/ZipPathValidator; 326
+Landroid/content/pm/PackageManager;.sPackageInfoCache:Landroid/app/PropertyInvalidatedCache;.mSkips:[J 327
+Landroid/content/pm/PackageManager;.sApplicationInfoCache:Landroid/app/PropertyInvalidatedCache;.mSkips:[J 328
+Lsun/util/locale/BaseLocale$Cache;.CACHE:Lsun/util/locale/BaseLocale$Cache;.map:Ljava/util/concurrent/ConcurrentMap; 329
+Landroid/content/Context; 330
+Ljava/util/concurrent/Executor; 331
+Ljava/util/concurrent/ScheduledExecutorService; 332
+Ljava/util/concurrent/ExecutorService; 332
+Landroid/view/Window$OnFrameMetricsAvailableListener; 333
+Ljava/lang/annotation/Annotation; 334
+Ljava/lang/Enum;.sharedConstantsCache:Llibcore/util/BasicLruCache;.map:Ljava/util/LinkedHashMap;.tail:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry; 335
+Ljava/util/concurrent/CancellationException; 336
+Ljava/lang/NoSuchMethodException; 337
+Landroid/os/strictmode/CustomViolation; 338
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.3:Ljava/util/WeakHashMap$Entry; 339
+Lcom/android/internal/policy/PhoneWindow; 340
+Landroid/view/autofill/AutofillValue; 340
+Landroid/widget/TextView$SavedState; 341
+Landroid/text/method/MetaKeyKeyListener;.SYM:Ljava/lang/Object; 342
+Landroid/text/method/MetaKeyKeyListener;.ALT:Ljava/lang/Object; 342
+Landroid/text/method/MetaKeyKeyListener;.SELECTING:Ljava/lang/Object; 342
+Landroid/text/method/MetaKeyKeyListener;.CAP:Ljava/lang/Object; 342
+Landroid/widget/PopupWindow$PopupBackgroundView; 343
+Landroid/widget/TextView;.TEMP_RECTF:Landroid/graphics/RectF; 343
+Landroid/text/method/ScrollingMovementMethod; 343
+Landroid/icu/impl/locale/UnicodeLocaleExtension;.EMPTY_SORTED_SET:Ljava/util/SortedSet;.m:Ljava/util/NavigableMap; 343
+Landroid/widget/PopupWindow$PopupDecorView; 343
+Landroid/widget/Editor$TextRenderNode; 343
+Landroid/widget/Editor$PositionListener; 344
+Landroid/text/style/SpellCheckSpan; 345
+Landroid/text/method/ArrowKeyMovementMethod; 346
+Landroid/text/method/TextKeyListener;.sInstance:[Landroid/text/method/TextKeyListener; 346
+Landroid/text/TextUtils$TruncateAt;.MARQUEE:Landroid/text/TextUtils$TruncateAt; 347
+Landroid/view/autofill/Helper; 348
+Lcom/android/internal/util/LatencyTracker; 349
+Lcom/android/internal/util/LatencyTracker$SLatencyTrackerHolder; 349
+Landroid/graphics/drawable/Icon; 350
+Landroid/text/style/AlignmentSpan; 351
+Landroid/text/MeasuredParagraph;.sPool:Landroid/util/Pools$SynchronizedPool;.mPool:[Ljava/lang/Object; 352
+Landroid/text/MeasuredParagraph;.sPool:Landroid/util/Pools$SynchronizedPool; 352
+Landroid/icu/impl/ICUResourceBundleReader;.CACHE:Landroid/icu/impl/ICUResourceBundleReader$ReaderCache;.map:Ljava/util/concurrent/ConcurrentHashMap; 353
+Landroid/location/ILocationManager$Stub;.dexCache:Ljava/lang/Object; 354
+Landroid/annotation/CurrentTimeMillisLong; 355
+Ljava/lang/reflect/Method; 356
+Lcom/android/internal/os/ZygoteInit; 356
+Landroid/database/DatabaseUtils; 356
+Landroid/os/HandlerThread; 356
+Ljava/security/Signature;.signatureInfo:Ljava/util/Map;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node; 357
+Ljava/security/Signature;.signatureInfo:Ljava/util/Map; 358
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.queue:Ljava/lang/ref/ReferenceQueue; 359
+Landroid/telephony/TelephonyRegistryManager; 360
+Landroid/graphics/HardwareRenderer; 361
+Landroid/os/BinderProxy; 362
+Landroid/app/compat/CompatChanges;.QUERY_CACHE:Landroid/app/compat/ChangeIdStateCache;.mCache:Ljava/util/LinkedHashMap; 363
+Landroid/app/compat/CompatChanges;.QUERY_CACHE:Landroid/app/compat/ChangeIdStateCache; 363
+Landroid/app/AlarmManager; 364
+Landroid/net/metrics/DhcpClientEvent; 365
+[I 366
+Landroid/media/MediaCodecList; 367
+Landroid/graphics/drawable/InsetDrawable; 368
+Landroid/widget/ProgressBar$SavedState; 369
+Landroid/widget/ScrollView$SavedState; 370
+Landroid/graphics/drawable/AnimatedVectorDrawable; 371
+Landroid/widget/ListView; 372
+Landroid/widget/AbsListView; 373
+Landroid/widget/AbsListView$SavedState; 373
+Landroid/widget/CompoundButton$SavedState; 374
+Landroid/widget/HorizontalScrollView$SavedState; 375
+Landroid/widget/HorizontalScrollView; 376
+Landroid/icu/text/MeasureFormat;.hmsTo012:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.1:Ljava/util/HashMap$Node;.value:Ljava/lang/Object; 377
+Landroid/icu/text/MeasureFormat;.hmsTo012:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.6:Ljava/util/HashMap$Node;.value:Ljava/lang/Object; 377
+Landroid/view/View$OnSystemUiVisibilityChangeListener; 378
+Ljava/util/AbstractMap; 379
+Landroid/telephony/euicc/EuiccCardManager$ResultCallback; 380
+Ljava/lang/Character$UnicodeBlock;.CJK_SYMBOLS_AND_PUNCTUATION:Ljava/lang/Character$UnicodeBlock; 381
+Ljava/lang/Character$UnicodeBlock;.KANBUN:Ljava/lang/Character$UnicodeBlock; 381
+Ljava/lang/Character$UnicodeBlock;.HANGUL_COMPATIBILITY_JAMO:Ljava/lang/Character$UnicodeBlock; 381
+Ljava/lang/Character$UnicodeBlock;.KATAKANA:Ljava/lang/Character$UnicodeBlock; 381
+Ljava/lang/Character$UnicodeBlock;.HANGUL_SYLLABLES:Ljava/lang/Character$UnicodeBlock; 381
+Ljava/lang/Character$UnicodeBlock;.ENCLOSED_CJK_LETTERS_AND_MONTHS:Ljava/lang/Character$UnicodeBlock; 381
+Ljava/lang/Character$UnicodeBlock;.HANGUL_JAMO:Ljava/lang/Character$UnicodeBlock; 381
+Ljava/lang/Character$UnicodeBlock;.BOPOMOFO_EXTENDED:Ljava/lang/Character$UnicodeBlock; 381
+Ljava/lang/Character$UnicodeBlock;.CJK_COMPATIBILITY_FORMS:Ljava/lang/Character$UnicodeBlock; 381
+Ljava/lang/Character$UnicodeBlock;.BOPOMOFO:Ljava/lang/Character$UnicodeBlock; 381
+Ljava/lang/Character$UnicodeBlock;.HIRAGANA:Ljava/lang/Character$UnicodeBlock; 381
+Ljava/lang/Character$UnicodeBlock;.HALFWIDTH_AND_FULLWIDTH_FORMS:Ljava/lang/Character$UnicodeBlock; 381
+Ljava/lang/Character$UnicodeBlock;.KANGXI_RADICALS:Ljava/lang/Character$UnicodeBlock; 381
+Ljava/lang/Character$UnicodeBlock;.CJK_RADICALS_SUPPLEMENT:Ljava/lang/Character$UnicodeBlock; 381
+Ljava/lang/Character$UnicodeBlock;.KATAKANA_PHONETIC_EXTENSIONS:Ljava/lang/Character$UnicodeBlock; 381
+Ljava/lang/Character$UnicodeBlock;.CJK_COMPATIBILITY:Ljava/lang/Character$UnicodeBlock; 381
+Ljava/lang/Character$UnicodeBlock;.CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT:Ljava/lang/Character$UnicodeBlock; 382
+Ljava/lang/Character$UnicodeBlock;.CJK_COMPATIBILITY_IDEOGRAPHS:Ljava/lang/Character$UnicodeBlock; 382
+Ljava/lang/Character$UnicodeBlock;.CJK_UNIFIED_IDEOGRAPHS:Ljava/lang/Character$UnicodeBlock; 382
+Ljava/lang/Character$UnicodeBlock;.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A:Ljava/lang/Character$UnicodeBlock; 382
+Ljava/lang/Character$UnicodeBlock;.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B:Ljava/lang/Character$UnicodeBlock; 382
+Lcom/android/internal/inputmethod/InputMethodPrivilegedOperationsRegistry; 383
+Landroid/view/Window$DecorCallback; 383
+Landroid/view/inputmethod/EditorInfo; 383
+Landroid/view/MenuItem$OnActionExpandListener; 384
+Ljava/util/Locale;.JAPANESE:Ljava/util/Locale; 385
+Ljava/util/Locale;.KOREAN:Ljava/util/Locale; 385
+Lcom/android/internal/config/appcloning/AppCloningDeviceConfigHelper; 386
+Landroid/telecom/PhoneAccountHandle; 387
+Landroid/content/AsyncQueryHandler; 388
+Landroid/speech/RecognitionListener; 389
+Ljava/lang/InstantiationException; 390
+Ljava/util/concurrent/ExecutionException; 391
+Landroid/icu/text/DateIntervalInfo;.DIICACHE:Landroid/icu/impl/ICUCache; 392
+Landroid/text/format/DateIntervalFormat;.CACHED_FORMATTERS:Landroid/util/LruCache;.map:Ljava/util/LinkedHashMap; 392
+Landroid/icu/text/DateIntervalFormat;.LOCAL_PATTERN_CACHE:Landroid/icu/impl/ICUCache; 392
+Landroid/icu/impl/OlsonTimeZone; 392
+Landroid/text/format/DateIntervalFormat;.CACHED_FORMATTERS:Landroid/util/LruCache; 392
+Landroid/graphics/drawable/Drawable; 393
+Ljava/lang/Enum;.sharedConstantsCache:Llibcore/util/BasicLruCache;.map:Ljava/util/LinkedHashMap;.tail:Ljava/util/LinkedHashMap$LinkedHashMapEntry; 394
+Landroid/app/Activity; 395
+Landroid/icu/text/PluralRules$KeywordStatus;.INVALID:Landroid/icu/text/PluralRules$KeywordStatus;.name:Ljava/lang/String; 396
+Landroid/net/Uri; 396
+Lsun/util/calendar/CalendarSystem;.calendars:Ljava/util/concurrent/ConcurrentMap; 396
+Landroid/animation/PropertyValuesHolder$IntPropertyValuesHolder;.sJNISetterPropertyMap:Ljava/util/HashMap; 397
+Landroid/graphics/drawable/ShapeDrawable; 398
+Lcom/android/internal/widget/ActionBarContextView; 399
+Landroid/widget/Toolbar$SavedState; 399
+Lcom/android/internal/widget/ActionBarContainer; 399
+Lcom/android/internal/widget/ActionBarOverlayLayout; 399
+Lcom/android/internal/widget/ActionBarContainer$ActionBarBackgroundDrawable; 399
+Landroid/widget/ActionMenuPresenter$OverflowMenuButton; 400
+Landroid/widget/ActionMenuView; 401
+Landroid/content/res/Configuration; 402
+Ljava/util/IdentityHashMap;.NULL_KEY:Ljava/lang/Object; 403
+Ljava/util/concurrent/ForkJoinPool; 404
+Landroid/os/ResultReceiver; 405
+Ljava/util/concurrent/TimeoutException; 406
+Ljava/io/IOException; 407
+Landroid/accounts/AccountAuthenticatorResponse; 408
+Landroid/nfc/NfcAdapter; 409
+Landroid/nfc/NfcAdapter;.sNfcAdapters:Ljava/util/HashMap; 409
+Landroid/app/backup/BackupManager; 410
+Landroid/app/NotificationChannelGroup; 411
+Landroid/content/pm/ParceledListSlice; 411
+Landroid/os/FileObserver; 412
+Landroid/os/UserHandle; 413
+Landroid/content/pm/PackageManager$NameNotFoundException; 414
+[Ljava/lang/Integer; 415
+Landroid/animation/PropertyValuesHolder;.sSetterPropertyMap:Ljava/util/HashMap; 415
+Landroid/content/LocusId; 416
+Landroid/view/contentcapture/ContentCaptureContext; 416
+Landroid/telephony/ims/RegistrationManager;.IMS_REG_TO_ACCESS_TYPE_MAP:Ljava/util/Map;.table:[Ljava/lang/Object;.18:Ljava/lang/Integer; 417
+Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;.pool:Ljava/util/concurrent/ConcurrentMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node;.4:Ljava/util/concurrent/ConcurrentHashMap$Node; 418
+Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;.pool:Ljava/util/concurrent/ConcurrentMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node; 418
+Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;.pool:Ljava/util/concurrent/ConcurrentMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node;.2:Ljava/util/concurrent/ConcurrentHashMap$Node;.next:Ljava/util/concurrent/ConcurrentHashMap$Node; 418
+Lcom/android/internal/telephony/cdnr/CarrierDisplayNameResolver;.EF_SOURCE_PRIORITY:Ljava/util/List;.a:[Ljava/lang/Object;.9:Ljava/lang/Integer; 418
+Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;.pool:Ljava/util/concurrent/ConcurrentMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node;.56:Ljava/util/concurrent/ConcurrentHashMap$Node; 418
+Lcom/android/internal/telephony/cdnr/CarrierDisplayNameResolver;.EF_SOURCE_PRIORITY:Ljava/util/List;.a:[Ljava/lang/Object;.5:Ljava/lang/Integer; 418
+Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;.pool:Ljava/util/concurrent/ConcurrentMap; 418
+Landroid/widget/EditText; 419
+Landroid/widget/CheckedTextView; 420
+Landroid/os/strictmode/UnsafeIntentLaunchViolation; 421
+Landroid/app/Service; 422
+Ldalvik/system/BlockGuard; 423
+Landroid/hardware/devicestate/DeviceStateManagerGlobal; 424
+Landroid/hardware/camera2/CameraCharacteristics;.SCALER_MULTI_RESOLUTION_STREAM_SUPPORTED:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 425
+Landroid/hardware/camera2/marshal/MarshalRegistry;.sMarshalerMap:Ljava/util/HashMap; 425
+Landroid/hardware/camera2/CameraCharacteristics;.LENS_FACING:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 425
+Landroid/content/ClipboardManager$OnPrimaryClipChangedListener; 426
+Landroid/icu/text/BreakIterator;.iterCache:[Landroid/icu/impl/CacheValue; 427
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.13:Ljava/util/WeakHashMap$Entry; 428
+Landroid/icu/text/Collator; 429
+Landroid/icu/impl/number/parse/NanMatcher;.DEFAULT:Landroid/icu/impl/number/parse/NanMatcher;.uniSet:Landroid/icu/text/UnicodeSet;.strings:Ljava/util/SortedSet;.c:Ljava/util/Collection;.m:Ljava/util/NavigableMap; 430
+Ljava/io/FileNotFoundException; 431
+Landroid/os/BaseBundle; 432
+Landroid/service/watchdog/ExplicitHealthCheckService$PackageConfig; 433
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.116:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.12:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.90:Ljava/lang/String; 434
+Landroid/icu/text/MessageFormat;.rootLocale:Ljava/util/Locale;.baseLocale:Lsun/util/locale/BaseLocale;.language:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.385:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.107:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.112:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.480:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.550:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.143:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._obsoleteLanguages:[Ljava/lang/String;.1:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.473:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.138:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.204:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.71:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._replacementCountries:[Ljava/lang/String;.12:Ljava/lang/String; 434
+Landroid/icu/impl/duration/impl/DataRecord$ETimeLimit;.names:[Ljava/lang/String;.1:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._replacementCountries:[Ljava/lang/String;.9:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.99:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages3:[Ljava/lang/String;.152:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.256:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.170:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.220:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.461:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._replacementLanguages:[Ljava/lang/String;.5:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.190:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.157:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._obsoleteCountries:[Ljava/lang/String;.4:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.196:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.117:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.5:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.499:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.199:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.18:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.324:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.101:Ljava/lang/String; 434
+Landroid/icu/impl/locale/UnicodeLocaleExtension;.CA_JAPANESE:Landroid/icu/impl/locale/UnicodeLocaleExtension;._keywords:Ljava/util/SortedMap;.root:Ljava/util/TreeMap$TreeMapEntry;.key:Ljava/lang/Object; 434
+Landroid/icu/impl/LocaleIDs;._replacementCountries:[Ljava/lang/String;.3:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.140:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.105:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.37:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._replacementCountries:[Ljava/lang/String;.5:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.22:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.103:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.412:Ljava/lang/String; 434
+Landroid/icu/impl/duration/impl/DataRecord$EMilliSupport;.names:[Ljava/lang/String;.1:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.124:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.232:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.219:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.179:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.523:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.75:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.486:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.166:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.112:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.119:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.160:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.298:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.257:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.182:Ljava/lang/String; 434
+Landroid/icu/impl/units/UnitPreferences;.measurementSystem:Ljava/util/Map;.m:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.5:Ljava/util/HashMap$Node;.next:Ljava/util/HashMap$Node;.value:Ljava/lang/Object; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.47:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.180:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.111:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.358:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.96:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._obsoleteLanguages:[Ljava/lang/String;.0:Ljava/lang/String; 434
+Landroid/icu/text/DateFormat;.HOUR_GENERIC_TZ:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.67:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.254:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.222:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.55:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.349:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.16:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.352:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.443:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.478:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.19:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.401:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.137:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.65:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.474:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.168:Ljava/lang/String; 434
+Landroid/icu/impl/units/UnitPreferences;.measurementSystem:Ljava/util/Map;.m:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.15:Ljava/util/HashMap$Node;.value:Ljava/lang/Object; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.111:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages3:[Ljava/lang/String;.545:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.30:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.469:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.21:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.69:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.56:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.519:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._replacementLanguages:[Ljava/lang/String;.4:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.107:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.290:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.59:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.220:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.186:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.516:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.181:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.199:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.396:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.117:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.227:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.331:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.447:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.151:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.144:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.132:Ljava/lang/String; 434
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.230:Ljava/lang/String; 434
+Landroid/icu/text/DateFormat;.MINUTE_SECOND:Ljava/lang/String; 434
+Ljava/lang/Enum;.sharedConstantsCache:Llibcore/util/BasicLruCache;.map:Ljava/util/LinkedHashMap;.tail:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry; 435
+Ljava/lang/Enum;.sharedConstantsCache:Llibcore/util/BasicLruCache;.map:Ljava/util/LinkedHashMap;.head:Ljava/util/LinkedHashMap$LinkedHashMapEntry; 436
+Ljava/lang/Enum;.sharedConstantsCache:Llibcore/util/BasicLruCache;.map:Ljava/util/LinkedHashMap;.tail:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry; 437
+Landroid/graphics/drawable/ColorStateListDrawable; 438
+Ljava/lang/SecurityException; 439
+Ljava/lang/RuntimeException; 440
+Landroid/media/audiopolicy/AudioProductStrategy; 441
+Landroid/os/PersistableBundle; 442
+Landroid/content/pm/ShortcutInfo; 442
+Landroid/icu/text/TimeZoneFormat;._tzfCache:Landroid/icu/text/TimeZoneFormat$TimeZoneFormatCache;.map:Ljava/util/concurrent/ConcurrentHashMap; 443
+Landroid/graphics/LeakyTypefaceStorage;.sStorage:Ljava/util/ArrayList; 443
+Landroid/graphics/LeakyTypefaceStorage;.sTypefaceMap:Landroid/util/ArrayMap; 443
+Landroid/text/TextWatcher; 444
+Landroid/view/accessibility/AccessibilityManager$TouchExplorationStateChangeListener; 445
+Ljavax/net/SocketFactory; 446
+Ljava/util/Collections; 447
+Ljava/lang/Exception; 448
+Landroid/os/UserManager; 449
+Landroid/os/RemoteException; 450
+Landroid/content/AttributionSource; 451
+Lcom/android/okhttp/internalandroidapi/HttpURLConnectionFactory$DnsAdapter; 452
+Lcom/android/okhttp/Protocol;.HTTP_2:Lcom/android/okhttp/Protocol; 452
+Ljava/net/Inet4Address; 452
+Lcom/android/okhttp/Protocol;.SPDY_3:Lcom/android/okhttp/Protocol; 452
+Lcom/android/okhttp/OkHttpClient; 452
+Landroid/os/storage/VolumeInfo; 453
+Landroid/os/storage/DiskInfo; 453
+Landroid/view/textclassifier/TextLanguage;.EMPTY:Landroid/view/textclassifier/TextLanguage;.mBundle:Landroid/os/Bundle;.mMap:Landroid/util/ArrayMap; 454
+Ljava/nio/file/StandardOpenOption;.WRITE:Ljava/nio/file/StandardOpenOption; 455
+Ljava/nio/file/StandardOpenOption;.APPEND:Ljava/nio/file/StandardOpenOption; 456
+Ljava/util/logging/FileHandler; 457
+Ljava/nio/file/StandardOpenOption;.CREATE_NEW:Ljava/nio/file/StandardOpenOption; 457
+Ljava/util/logging/FileHandler;.locks:Ljava/util/Set;.map:Ljava/util/HashMap; 457
+Lsun/nio/ch/SharedFileLockTable;.queue:Ljava/lang/ref/ReferenceQueue; 458
+Ljavax/net/ServerSocketFactory; 458
+Landroid/os/AsyncTask; 459
+Landroid/os/strictmode/UnbufferedIoViolation; 460
+Landroid/app/usage/AppStandbyInfo; 461
+Landroid/text/format/DateUtils; 462
+Landroid/security/IKeyChainService; 463
+Landroid/util/Log$TerribleFailure; 464
+Lcom/android/internal/os/RuntimeInit$KillApplicationHandler; 464
+Ljava/util/Timer;.nextSerialNumber:Ljava/util/concurrent/atomic/AtomicInteger; 465
+Landroid/telephony/ims/stub/ImsConfigImplBase$ImsConfigStub; 466
+Landroid/telephony/ims/stub/ImsRegistrationImplBase$1; 466
+Landroid/telephony/ims/ImsUtListener; 466
+Landroid/telephony/ims/feature/MmTelFeature$1; 466
+Lcom/android/ims/ImsManager;.IMS_MANAGER_INSTANCES:Landroid/util/SparseArray;.mValues:[Ljava/lang/Object; 467
+Lcom/android/ims/ImsManager;.IMS_MANAGER_INSTANCES:Landroid/util/SparseArray; 467
+Lcom/android/ims/ImsManager;.IMS_MANAGER_INSTANCES:Landroid/util/SparseArray;.mKeys:[I 467
+Landroid/telephony/ims/aidl/IImsConfig$Stub$Proxy; 468
+Landroid/telephony/ims/aidl/IImsRegistration$Stub$Proxy; 468
+Landroid/telephony/NetworkService; 469
+Landroid/telephony/TelephonyCallback$ServiceStateListener; 470
+Landroid/telephony/TelephonyCallback$PhysicalChannelConfigListener; 471
+Landroid/telephony/TelephonyCallback$RadioPowerStateListener; 471
+Lsun/security/x509/X500Name;.internedOIDs:Ljava/util/Map; 472
+Lsun/security/x509/X500Name;.internedOIDs:Ljava/util/Map;.table:[Ljava/util/HashMap$Node; 472
+Landroid/media/MediaCodec; 473
+Ljava/nio/file/StandardOpenOption;.CREATE:Ljava/nio/file/StandardOpenOption; 474
+Ljava/nio/file/NoSuchFileException; 475
+Ljava/text/DateFormatSymbols;.cachedInstances:Ljava/util/concurrent/ConcurrentMap; 476
+Ljava/util/Currency;.instances:Ljava/util/concurrent/ConcurrentMap; 476
+Ljava/util/Calendar;.cachedLocaleData:Ljava/util/concurrent/ConcurrentMap; 476
+Ljava/text/SimpleDateFormat;.cachedNumberFormatData:Ljava/util/concurrent/ConcurrentMap; 476
+Landroid/app/UriGrantsManager;.IUriGrantsManagerSingleton:Landroid/util/Singleton; 477
+Landroid/content/ContentProviderProxy; 478
+Landroid/os/DeadObjectException; 479
+Landroid/app/slice/SliceSpec; 479
+Landroid/database/sqlite/SQLiteDatabase; 480
+Ljava/util/Locale;.CHINA:Ljava/util/Locale; 481
+Ljava/util/Locale;.TAIWAN:Ljava/util/Locale; 481
+Ljava/util/Locale;.KOREA:Ljava/util/Locale; 481
+Ljava/util/Scanner; 482
+Ljava/math/BigDecimal; 483
+Ljava/security/interfaces/RSAPrivateCrtKey; 483
+Ljava/security/interfaces/RSAPrivateKey; 483
+Lcom/android/server/backup/AccountSyncSettingsBackupHelper;.KEY_ACCOUNT_TYPE:Ljava/lang/String; 483
+Landroid/util/UtilConfig; 484
+Ljava/net/ResponseCache; 485
+Landroid/content/ReceiverCallNotAllowedException; 486
+Landroid/app/ReceiverRestrictedContext; 487
+Landroid/os/strictmode/CredentialProtectedWhileLockedViolation; 488
+Landroid/app/Application; 489
+Ljava/util/NoSuchElementException; 490
+Landroid/os/Messenger; 491
+Landroid/telephony/TelephonyCallback$DataEnabledListener; 491
+Landroid/system/StructLinger; 492
diff --git a/core/api/current.txt b/core/api/current.txt
index 7731fac..d1d7983 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -428,6 +428,7 @@
     field public static final int activityCloseExitAnimation = 16842939; // 0x10100bb
     field public static final int activityOpenEnterAnimation = 16842936; // 0x10100b8
     field public static final int activityOpenExitAnimation = 16842937; // 0x10100b9
+    field @FlaggedApi("android.media.tv.flags.enable_ad_service_fw") public static final int adServiceTypes;
     field public static final int addPrintersActivity = 16843750; // 0x10103e6
     field public static final int addStatesFromChildren = 16842992; // 0x10100f0
     field public static final int adjustViewBounds = 16843038; // 0x101011e
@@ -1216,6 +1217,7 @@
     field public static final int opticalInsetLeft = 16844168; // 0x1010588
     field public static final int opticalInsetRight = 16844170; // 0x101058a
     field public static final int opticalInsetTop = 16844169; // 0x1010589
+    field @FlaggedApi("android.content.pm.sdk_lib_independence") public static final int optional;
     field public static final int order = 16843242; // 0x10101ea
     field public static final int orderInCategory = 16843231; // 0x10101df
     field public static final int ordering = 16843490; // 0x10102e2
@@ -4467,7 +4469,7 @@
     method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu, int);
     method public android.net.Uri onProvideReferrer();
     method public void onRequestPermissionsResult(int, @NonNull String[], @NonNull int[]);
-    method @FlaggedApi("android.permission.flags.device_aware_permission_apis") public void onRequestPermissionsResult(int, @NonNull String[], @NonNull int[], int);
+    method @FlaggedApi("android.permission.flags.device_aware_permission_apis_enabled") public void onRequestPermissionsResult(int, @NonNull String[], @NonNull int[], int);
     method @CallSuper protected void onRestart();
     method protected void onRestoreInstanceState(@NonNull android.os.Bundle);
     method public void onRestoreInstanceState(@Nullable android.os.Bundle, @Nullable android.os.PersistableBundle);
@@ -4509,14 +4511,14 @@
     method public android.view.DragAndDropPermissions requestDragAndDropPermissions(android.view.DragEvent);
     method public void requestFullscreenMode(int, @Nullable android.os.OutcomeReceiver<java.lang.Void,java.lang.Throwable>);
     method public final void requestPermissions(@NonNull String[], int);
-    method @FlaggedApi("android.permission.flags.device_aware_permission_apis") public final void requestPermissions(@NonNull String[], int, int);
+    method @FlaggedApi("android.permission.flags.device_aware_permission_apis_enabled") public final void requestPermissions(@NonNull String[], int, int);
     method public final void requestShowKeyboardShortcuts();
     method @Deprecated public boolean requestVisibleBehind(boolean);
     method public final boolean requestWindowFeature(int);
     method @NonNull public final <T extends android.view.View> T requireViewById(@IdRes int);
     method public final void runOnUiThread(Runnable);
     method public void setActionBar(@Nullable android.widget.Toolbar);
-    method public void setAllowCrossUidActivitySwitchFromBelow(boolean);
+    method @FlaggedApi("android.security.asm_restrictions_enabled") public void setAllowCrossUidActivitySwitchFromBelow(boolean);
     method public void setContentTransitionManager(android.transition.TransitionManager);
     method public void setContentView(@LayoutRes int);
     method public void setContentView(android.view.View);
@@ -4557,7 +4559,7 @@
     method public void setVrModeEnabled(boolean, @NonNull android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
     method public boolean shouldDockBigOverlays();
     method public boolean shouldShowRequestPermissionRationale(@NonNull String);
-    method @FlaggedApi("android.permission.flags.device_aware_permission_apis") public boolean shouldShowRequestPermissionRationale(@NonNull String, int);
+    method @FlaggedApi("android.permission.flags.device_aware_permission_apis_enabled") public boolean shouldShowRequestPermissionRationale(@NonNull String, int);
     method public boolean shouldUpRecreateTask(android.content.Intent);
     method public boolean showAssist(android.os.Bundle);
     method @Deprecated public final void showDialog(int);
@@ -5284,9 +5286,10 @@
     field public static final int START_TIMESTAMP_RESERVED_RANGE_DEVELOPER_START = 21; // 0x15
     field public static final int START_TIMESTAMP_RESERVED_RANGE_SYSTEM = 20; // 0x14
     field public static final int START_TIMESTAMP_SURFACEFLINGER_COMPOSITION_COMPLETE = 7; // 0x7
-    field public static final int START_TYPE_COLD = 0; // 0x0
-    field public static final int START_TYPE_HOT = 2; // 0x2
-    field public static final int START_TYPE_WARM = 1; // 0x1
+    field public static final int START_TYPE_COLD = 1; // 0x1
+    field public static final int START_TYPE_HOT = 3; // 0x3
+    field public static final int START_TYPE_UNSET = 0; // 0x0
+    field public static final int START_TYPE_WARM = 2; // 0x2
   }
 
   public final class AsyncNotedAppOp implements android.os.Parcelable {
@@ -9706,9 +9709,9 @@
     method @RequiresPermission(android.Manifest.permission.DELIVER_COMPANION_MESSAGES) public final void detachSystemDataTransport(int) throws android.companion.DeviceNotAssociatedException;
     method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
     method @Deprecated @MainThread public void onDeviceAppeared(@NonNull String);
-    method @Deprecated @MainThread public void onDeviceAppeared(@NonNull android.companion.AssociationInfo);
+    method @MainThread public void onDeviceAppeared(@NonNull android.companion.AssociationInfo);
     method @Deprecated @MainThread public void onDeviceDisappeared(@NonNull String);
-    method @Deprecated @MainThread public void onDeviceDisappeared(@NonNull android.companion.AssociationInfo);
+    method @MainThread public void onDeviceDisappeared(@NonNull android.companion.AssociationInfo);
     method @FlaggedApi("android.companion.device_presence") @MainThread public void onDeviceEvent(@NonNull android.companion.AssociationInfo, int);
     field @FlaggedApi("android.companion.device_presence") public static final int DEVICE_EVENT_BLE_APPEARED = 0; // 0x0
     field @FlaggedApi("android.companion.device_presence") public static final int DEVICE_EVENT_BLE_DISAPPEARED = 1; // 0x1
@@ -9838,7 +9841,7 @@
     method public int describeContents();
     method public void enforceCallingUid();
     method @Nullable public String getAttributionTag();
-    method @FlaggedApi("android.permission.flags.device_aware_permission_apis") public int getDeviceId();
+    method @FlaggedApi("android.permission.flags.device_aware_permission_apis_enabled") public int getDeviceId();
     method @Nullable public android.content.AttributionSource getNext();
     method @Nullable public String getPackageName();
     method public int getPid();
@@ -9854,7 +9857,7 @@
     ctor public AttributionSource.Builder(@NonNull android.content.AttributionSource);
     method @NonNull public android.content.AttributionSource build();
     method @NonNull public android.content.AttributionSource.Builder setAttributionTag(@Nullable String);
-    method @FlaggedApi("android.permission.flags.device_aware_permission_apis") @NonNull public android.content.AttributionSource.Builder setDeviceId(int);
+    method @FlaggedApi("android.permission.flags.device_aware_permission_apis_enabled") @NonNull public android.content.AttributionSource.Builder setDeviceId(int);
     method @NonNull public android.content.AttributionSource.Builder setNext(@Nullable android.content.AttributionSource);
     method @FlaggedApi("android.permission.flags.set_next_attribution_source") @NonNull public android.content.AttributionSource.Builder setNextAttributionSource(@NonNull android.content.AttributionSource);
     method @NonNull public android.content.AttributionSource.Builder setPackageName(@Nullable String);
@@ -12604,6 +12607,7 @@
     method public boolean isStagedSessionApplied();
     method public boolean isStagedSessionFailed();
     method public boolean isStagedSessionReady();
+    method @FlaggedApi("android.content.pm.archiving") public boolean isUnarchival();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.content.pm.PackageInstaller.SessionInfo> CREATOR;
     field public static final int INVALID_ID = -1; // 0xffffffff
@@ -13294,6 +13298,7 @@
     method @NonNull public java.util.List<android.content.pm.VersionedPackage> getDependentPackages();
     method @IntRange(from=0xffffffff) public long getLongVersion();
     method public String getName();
+    method @FlaggedApi("android.content.pm.sdk_lib_independence") @NonNull public java.util.List<android.content.pm.VersionedPackage> getOptionalDependentPackages();
     method public int getType();
     method @Deprecated @IntRange(from=0xffffffff) public int getVersion();
     method public void writeToParcel(android.os.Parcel, int);
@@ -18787,6 +18792,7 @@
     method @NonNull public java.util.List<android.hardware.camera2.CaptureRequest.Key<?>> getAvailableCaptureRequestKeys();
     method @NonNull public java.util.List<android.hardware.camera2.CaptureResult.Key<?>> getAvailableCaptureResultKeys();
     method public java.util.List<android.hardware.camera2.CaptureRequest.Key<?>> getAvailablePhysicalCameraRequestKeys();
+    method @FlaggedApi("com.android.internal.camera.flags.feature_combination_query") @NonNull public java.util.List<android.hardware.camera2.CameraCharacteristics.Key<?>> getAvailableSessionCharacteristicsKeys();
     method public java.util.List<android.hardware.camera2.CaptureRequest.Key<?>> getAvailableSessionKeys();
     method @NonNull public java.util.List<android.hardware.camera2.CameraCharacteristics.Key<?>> getKeys();
     method @NonNull public java.util.List<android.hardware.camera2.CameraCharacteristics.Key<?>> getKeysNeedingPermission();
@@ -18811,6 +18817,7 @@
     field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES;
     field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AWB_AVAILABLE_MODES;
     field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Boolean> CONTROL_AWB_LOCK_AVAILABLE;
+    field @FlaggedApi("com.android.internal.camera.flags.camera_ae_mode_low_light_boost") @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.Range<java.lang.Float>> CONTROL_LOW_LIGHT_BOOST_INFO_LUMINANCE_RANGE;
     field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> CONTROL_MAX_REGIONS_AE;
     field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> CONTROL_MAX_REGIONS_AF;
     field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> CONTROL_MAX_REGIONS_AWB;
@@ -18939,6 +18946,7 @@
     method @Deprecated public abstract void createReprocessableCaptureSessionByConfigurations(@NonNull android.hardware.camera2.params.InputConfiguration, @NonNull java.util.List<android.hardware.camera2.params.OutputConfiguration>, @NonNull android.hardware.camera2.CameraCaptureSession.StateCallback, @Nullable android.os.Handler) throws android.hardware.camera2.CameraAccessException;
     method public int getCameraAudioRestriction() throws android.hardware.camera2.CameraAccessException;
     method @NonNull public abstract String getId();
+    method @FlaggedApi("com.android.internal.camera.flags.feature_combination_query") @NonNull public android.hardware.camera2.CameraCharacteristics getSessionCharacteristics(@NonNull android.hardware.camera2.params.SessionConfiguration) throws android.hardware.camera2.CameraAccessException;
     method @Deprecated public boolean isSessionConfigurationSupported(@NonNull android.hardware.camera2.params.SessionConfiguration) throws android.hardware.camera2.CameraAccessException;
     method public void setCameraAudioRestriction(int) throws android.hardware.camera2.CameraAccessException;
     field public static final int AUDIO_RESTRICTION_NONE = 0; // 0x0
@@ -19098,6 +19106,7 @@
     field public static final int CONTROL_AE_MODE_ON_AUTO_FLASH = 2; // 0x2
     field public static final int CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE = 4; // 0x4
     field public static final int CONTROL_AE_MODE_ON_EXTERNAL_FLASH = 5; // 0x5
+    field @FlaggedApi("com.android.internal.camera.flags.camera_ae_mode_low_light_boost") public static final int CONTROL_AE_MODE_ON_LOW_LIGHT_BOOST_BRIGHTNESS_PRIORITY = 6; // 0x6
     field public static final int CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL = 2; // 0x2
     field public static final int CONTROL_AE_PRECAPTURE_TRIGGER_IDLE = 0; // 0x0
     field public static final int CONTROL_AE_PRECAPTURE_TRIGGER_START = 1; // 0x1
@@ -19163,6 +19172,8 @@
     field public static final int CONTROL_EXTENDED_SCENE_MODE_BOKEH_CONTINUOUS = 2; // 0x2
     field public static final int CONTROL_EXTENDED_SCENE_MODE_BOKEH_STILL_CAPTURE = 1; // 0x1
     field public static final int CONTROL_EXTENDED_SCENE_MODE_DISABLED = 0; // 0x0
+    field @FlaggedApi("com.android.internal.camera.flags.camera_ae_mode_low_light_boost") public static final int CONTROL_LOW_LIGHT_BOOST_STATE_ACTIVE = 1; // 0x1
+    field @FlaggedApi("com.android.internal.camera.flags.camera_ae_mode_low_light_boost") public static final int CONTROL_LOW_LIGHT_BOOST_STATE_INACTIVE = 0; // 0x0
     field public static final int CONTROL_MODE_AUTO = 1; // 0x1
     field public static final int CONTROL_MODE_OFF = 0; // 0x0
     field public static final int CONTROL_MODE_OFF_KEEP_STATE = 3; // 0x3
@@ -19483,6 +19494,7 @@
     field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_EFFECT_MODE;
     field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Boolean> CONTROL_ENABLE_ZSL;
     field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_EXTENDED_SCENE_MODE;
+    field @FlaggedApi("com.android.internal.camera.flags.camera_ae_mode_low_light_boost") @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_LOW_LIGHT_BOOST_STATE;
     field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_MODE;
     field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_POST_RAW_SENSITIVITY_BOOST;
     field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_SCENE_MODE;
@@ -36903,6 +36915,7 @@
     field public static final String ACTION_REGIONAL_PREFERENCES_SETTINGS = "android.settings.REGIONAL_PREFERENCES_SETTINGS";
     field public static final String ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
     field public static final String ACTION_REQUEST_MANAGE_MEDIA = "android.settings.REQUEST_MANAGE_MEDIA";
+    field @FlaggedApi("com.android.media.flags.enable_privileged_routing_for_media_routing_control") public static final String ACTION_REQUEST_MEDIA_ROUTING_CONTROL = "android.settings.REQUEST_MEDIA_ROUTING_CONTROL";
     field public static final String ACTION_REQUEST_SCHEDULE_EXACT_ALARM = "android.settings.REQUEST_SCHEDULE_EXACT_ALARM";
     field public static final String ACTION_REQUEST_SET_AUTOFILL_SERVICE = "android.settings.REQUEST_SET_AUTOFILL_SERVICE";
     field public static final String ACTION_SEARCH_SETTINGS = "android.search.action.SEARCH_SETTINGS";
@@ -39062,6 +39075,7 @@
 
   public class NetworkSecurityPolicy {
     method public static android.security.NetworkSecurityPolicy getInstance();
+    method @FlaggedApi("android.security.certificate_transparency_configuration") public boolean isCertificateTransparencyVerificationRequired(@NonNull String);
     method public boolean isCleartextTrafficPermitted();
     method public boolean isCleartextTrafficPermitted(String);
   }
@@ -39298,7 +39312,7 @@
     method @Nullable public java.util.Date getKeyValidityStart();
     method @NonNull public String getKeystoreAlias();
     method public int getMaxUsageCount();
-    method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public java.util.Set<java.lang.String> getMgf1Digests();
+    method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public java.util.Set<java.lang.String> getMgf1Digests();
     method public int getPurposes();
     method @NonNull public String[] getSignaturePaddings();
     method public int getUserAuthenticationType();
@@ -39306,7 +39320,7 @@
     method public boolean isDevicePropertiesAttestationIncluded();
     method @NonNull public boolean isDigestsSpecified();
     method public boolean isInvalidatedByBiometricEnrollment();
-    method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public boolean isMgf1DigestsSpecified();
+    method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public boolean isMgf1DigestsSpecified();
     method public boolean isRandomizedEncryptionRequired();
     method public boolean isStrongBoxBacked();
     method public boolean isUnlockedDeviceRequired();
@@ -39338,7 +39352,7 @@
     method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setKeyValidityForOriginationEnd(java.util.Date);
     method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setKeyValidityStart(java.util.Date);
     method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setMaxUsageCount(int);
-    method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setMgf1Digests(@NonNull java.lang.String...);
+    method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setMgf1Digests(@NonNull java.lang.String...);
     method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setRandomizedEncryptionRequired(boolean);
     method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setSignaturePaddings(java.lang.String...);
     method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setUnlockedDeviceRequired(boolean);
@@ -39443,14 +39457,14 @@
     method @Nullable public java.util.Date getKeyValidityForOriginationEnd();
     method @Nullable public java.util.Date getKeyValidityStart();
     method public int getMaxUsageCount();
-    method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public java.util.Set<java.lang.String> getMgf1Digests();
+    method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public java.util.Set<java.lang.String> getMgf1Digests();
     method public int getPurposes();
     method @NonNull public String[] getSignaturePaddings();
     method public int getUserAuthenticationType();
     method public int getUserAuthenticationValidityDurationSeconds();
     method public boolean isDigestsSpecified();
     method public boolean isInvalidatedByBiometricEnrollment();
-    method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public boolean isMgf1DigestsSpecified();
+    method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public boolean isMgf1DigestsSpecified();
     method public boolean isRandomizedEncryptionRequired();
     method public boolean isUnlockedDeviceRequired();
     method public boolean isUserAuthenticationRequired();
@@ -39472,7 +39486,7 @@
     method @NonNull public android.security.keystore.KeyProtection.Builder setKeyValidityForOriginationEnd(java.util.Date);
     method @NonNull public android.security.keystore.KeyProtection.Builder setKeyValidityStart(java.util.Date);
     method @NonNull public android.security.keystore.KeyProtection.Builder setMaxUsageCount(int);
-    method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public android.security.keystore.KeyProtection.Builder setMgf1Digests(@Nullable java.lang.String...);
+    method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public android.security.keystore.KeyProtection.Builder setMgf1Digests(@Nullable java.lang.String...);
     method @NonNull public android.security.keystore.KeyProtection.Builder setRandomizedEncryptionRequired(boolean);
     method @NonNull public android.security.keystore.KeyProtection.Builder setSignaturePaddings(java.lang.String...);
     method @NonNull public android.security.keystore.KeyProtection.Builder setUnlockedDeviceRequired(boolean);
@@ -43358,6 +43372,9 @@
     field public static final String KEY_MMS_UA_PROF_URL_STRING = "uaProfUrl";
     field public static final String KEY_MMS_USER_AGENT_STRING = "userAgent";
     field public static final String KEY_MONTHLY_DATA_CYCLE_DAY_INT = "monthly_data_cycle_day_int";
+    field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String KEY_NTN_LTE_RSRP_THRESHOLDS_INT_ARRAY = "ntn_lte_rsrp_thresholds_int_array";
+    field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String KEY_NTN_LTE_RSRQ_THRESHOLDS_INT_ARRAY = "ntn_lte_rsrq_thresholds_int_array";
+    field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String KEY_NTN_LTE_RSSNR_THRESHOLDS_INT_ARRAY = "ntn_lte_rssnr_thresholds_int_array";
     field public static final String KEY_ONLY_AUTO_SELECT_IN_HOME_NETWORK_BOOL = "only_auto_select_in_home_network";
     field public static final String KEY_ONLY_SINGLE_DC_ALLOWED_INT_ARRAY = "only_single_dc_allowed_int_array";
     field public static final String KEY_OPERATOR_SELECTION_EXPAND_BOOL = "operator_selection_expand_bool";
@@ -43372,6 +43389,7 @@
     field public static final String KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSSNR_INT = "opportunistic_network_exit_threshold_rssnr_int";
     field public static final String KEY_OPPORTUNISTIC_NETWORK_MAX_BACKOFF_TIME_LONG = "opportunistic_network_max_backoff_time_long";
     field public static final String KEY_OPPORTUNISTIC_NETWORK_PING_PONG_TIME_LONG = "opportunistic_network_ping_pong_time_long";
+    field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String KEY_PARAMETERS_USED_FOR_NTN_LTE_SIGNAL_BAR_INT = "parameters_used_for_ntn_lte_signal_bar_int";
     field public static final String KEY_PING_TEST_BEFORE_DATA_SWITCH_BOOL = "ping_test_before_data_switch_bool";
     field public static final String KEY_PREFER_2G_BOOL = "prefer_2g_bool";
     field public static final String KEY_PREMIUM_CAPABILITY_MAXIMUM_DAILY_NOTIFICATION_COUNT_INT = "premium_capability_maximum_daily_notification_count_int";
@@ -44708,12 +44726,12 @@
     field public static final int SCAN_TYPE_PERIODIC = 1; // 0x1
   }
 
-  public class PhoneNumberFormattingTextWatcher implements android.text.TextWatcher {
-    ctor public PhoneNumberFormattingTextWatcher();
-    ctor public PhoneNumberFormattingTextWatcher(String);
-    method public void afterTextChanged(android.text.Editable);
-    method public void beforeTextChanged(CharSequence, int, int, int);
-    method public void onTextChanged(CharSequence, int, int, int);
+  @Deprecated public class PhoneNumberFormattingTextWatcher implements android.text.TextWatcher {
+    ctor @Deprecated public PhoneNumberFormattingTextWatcher();
+    ctor @Deprecated @WorkerThread public PhoneNumberFormattingTextWatcher(String);
+    method @Deprecated public void afterTextChanged(android.text.Editable);
+    method @Deprecated public void beforeTextChanged(CharSequence, int, int, int);
+    method @Deprecated public void onTextChanged(CharSequence, int, int, int);
   }
 
   public class PhoneNumberUtils {
@@ -53868,9 +53886,11 @@
     method @Deprecated public android.view.Display getDefaultDisplay();
     method @NonNull public default android.view.WindowMetrics getMaximumWindowMetrics();
     method public default boolean isCrossWindowBlurEnabled();
+    method @FlaggedApi("com.android.window.flags.trusted_presentation_listener_for_window") public default void registerTrustedPresentationListener(@NonNull android.os.IBinder, @NonNull android.window.TrustedPresentationThresholds, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
     method public default void removeCrossWindowBlurEnabledListener(@NonNull java.util.function.Consumer<java.lang.Boolean>);
     method public default void removeProposedRotationListener(@NonNull java.util.function.IntConsumer);
     method public void removeViewImmediate(android.view.View);
+    method @FlaggedApi("com.android.window.flags.trusted_presentation_listener_for_window") public default void unregisterTrustedPresentationListener(@NonNull java.util.function.Consumer<java.lang.Boolean>);
     field public static final String PROPERTY_ACTIVITY_EMBEDDING_ALLOW_SYSTEM_OVERRIDE = "android.window.PROPERTY_ACTIVITY_EMBEDDING_ALLOW_SYSTEM_OVERRIDE";
     field public static final String PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED = "android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED";
     field public static final String PROPERTY_CAMERA_COMPAT_ALLOW_FORCE_ROTATION = "android.window.PROPERTY_CAMERA_COMPAT_ALLOW_FORCE_ROTATION";
@@ -60851,6 +60871,16 @@
     method public void markSyncReady();
   }
 
+  @FlaggedApi("com.android.window.flags.trusted_presentation_listener_for_window") public final class TrustedPresentationThresholds implements android.os.Parcelable {
+    ctor @FlaggedApi("com.android.window.flags.trusted_presentation_listener_for_window") public TrustedPresentationThresholds(@FloatRange(from=0.0f, fromInclusive=false, to=1.0f) float, @FloatRange(from=0.0f, fromInclusive=false, to=1.0f) float, @IntRange(from=1) int);
+    method @FlaggedApi("com.android.window.flags.trusted_presentation_listener_for_window") public int describeContents();
+    method @FlaggedApi("com.android.window.flags.trusted_presentation_listener_for_window") public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @FlaggedApi("com.android.window.flags.trusted_presentation_listener_for_window") @NonNull public static final android.os.Parcelable.Creator<android.window.TrustedPresentationThresholds> CREATOR;
+    field @FlaggedApi("com.android.window.flags.trusted_presentation_listener_for_window") @FloatRange(from=0.0f, fromInclusive=false, to=1.0f) public final float minAlpha;
+    field @FlaggedApi("com.android.window.flags.trusted_presentation_listener_for_window") @FloatRange(from=0.0f, fromInclusive=false, to=1.0f) public final float minFractionRendered;
+    field @FlaggedApi("com.android.window.flags.trusted_presentation_listener_for_window") @IntRange(from=1) public final int stabilityRequirementMs;
+  }
+
 }
 
 package javax.microedition.khronos.egl {
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index e7803fb..de330de 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -6,7 +6,6 @@
     field public static final String CONTROL_AUTOMOTIVE_GNSS = "android.permission.CONTROL_AUTOMOTIVE_GNSS";
     field public static final String GET_INTENT_SENDER_INTENT = "android.permission.GET_INTENT_SENDER_INTENT";
     field public static final String MAKE_UID_VISIBLE = "android.permission.MAKE_UID_VISIBLE";
-    field @FlaggedApi("android.companion.flags.companion_transport_apis") public static final String USE_COMPANION_TRANSPORTS = "android.permission.USE_COMPANION_TRANSPORTS";
   }
 
 }
@@ -82,29 +81,6 @@
 
 }
 
-package android.companion {
-
-  public final class CompanionDeviceManager {
-    method @FlaggedApi("android.companion.companion_transport_apis") @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS) public void addOnMessageReceivedListener(@NonNull java.util.concurrent.Executor, int, @NonNull android.companion.CompanionDeviceManager.OnMessageReceivedListener);
-    method @FlaggedApi("android.companion.companion_transport_apis") @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS) public void addOnTransportsChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.companion.CompanionDeviceManager.OnTransportsChangedListener);
-    method @FlaggedApi("android.companion.companion_transport_apis") @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS) public void removeOnMessageReceivedListener(int, @NonNull android.companion.CompanionDeviceManager.OnMessageReceivedListener);
-    method @FlaggedApi("android.companion.companion_transport_apis") @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS) public void removeOnTransportsChangedListener(@NonNull android.companion.CompanionDeviceManager.OnTransportsChangedListener);
-    method @FlaggedApi("android.companion.companion_transport_apis") @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS) public void sendMessage(int, @NonNull byte[], @NonNull int[]);
-    field @FlaggedApi("android.companion.companion_transport_apis") public static final int MESSAGE_REQUEST_CONTEXT_SYNC = 1667729539; // 0x63678883
-    field @FlaggedApi("android.companion.companion_transport_apis") public static final int MESSAGE_REQUEST_PERMISSION_RESTORE = 1669491075; // 0x63826983
-    field @FlaggedApi("android.companion.companion_transport_apis") public static final int MESSAGE_REQUEST_REMOTE_AUTHENTICATION = 1669494629; // 0x63827765
-  }
-
-  @FlaggedApi("android.companion.companion_transport_apis") public static interface CompanionDeviceManager.OnMessageReceivedListener {
-    method public void onMessageReceived(int, @NonNull byte[]);
-  }
-
-  @FlaggedApi("android.companion.companion_transport_apis") public static interface CompanionDeviceManager.OnTransportsChangedListener {
-    method public void onTransportsChanged(@NonNull java.util.List<android.companion.AssociationInfo>);
-  }
-
-}
-
 package android.content {
 
   public abstract class ContentProvider implements android.content.ComponentCallbacks2 {
@@ -136,6 +112,7 @@
 package android.content.pm {
 
   public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
+    method @FlaggedApi("android.content.pm.sdk_lib_independence") @NonNull public java.util.List<android.content.pm.SharedLibraryInfo> getOptionalSharedLibraryInfos();
     method @NonNull public java.util.List<android.content.pm.SharedLibraryInfo> getSharedLibraryInfos();
     field public static final int HIDDEN_API_ENFORCEMENT_DEFAULT = -1; // 0xffffffff
     field public static final int HIDDEN_API_ENFORCEMENT_DISABLED = 0; // 0x0
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 378a18c..fc0fb35 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -251,6 +251,7 @@
     field public static final String OBSERVE_SENSOR_PRIVACY = "android.permission.OBSERVE_SENSOR_PRIVACY";
     field public static final String OPEN_ACCESSIBILITY_DETAILS_SETTINGS = "android.permission.OPEN_ACCESSIBILITY_DETAILS_SETTINGS";
     field public static final String OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD = "android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD";
+    field @FlaggedApi("com.android.input.flags.override_key_behavior_permission_apis") public static final String OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW = "android.permission.OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW";
     field public static final String PACKAGE_VERIFICATION_AGENT = "android.permission.PACKAGE_VERIFICATION_AGENT";
     field public static final String PACKET_KEEPALIVE_OFFLOAD = "android.permission.PACKET_KEEPALIVE_OFFLOAD";
     field public static final String PEERS_MAC_ADDRESS = "android.permission.PEERS_MAC_ADDRESS";
@@ -302,6 +303,7 @@
     field public static final String RECEIVE_EMERGENCY_BROADCAST = "android.permission.RECEIVE_EMERGENCY_BROADCAST";
     field @FlaggedApi("android.permission.flags.voice_activation_permission_apis") public static final String RECEIVE_SANDBOXED_DETECTION_TRAINING_DATA = "android.permission.RECEIVE_SANDBOXED_DETECTION_TRAINING_DATA";
     field @FlaggedApi("android.permission.flags.voice_activation_permission_apis") public static final String RECEIVE_SANDBOX_TRIGGER_AUDIO = "android.permission.RECEIVE_SANDBOX_TRIGGER_AUDIO";
+    field @FlaggedApi("com.android.server.notification.flags.redact_otp_notifications_from_untrusted_listeners") public static final String RECEIVE_SENSITIVE_NOTIFICATIONS = "android.permission.RECEIVE_SENSITIVE_NOTIFICATIONS";
     field public static final String RECEIVE_WIFI_CREDENTIAL_CHANGE = "android.permission.RECEIVE_WIFI_CREDENTIAL_CHANGE";
     field public static final String RECORD_BACKGROUND_AUDIO = "android.permission.RECORD_BACKGROUND_AUDIO";
     field public static final String RECOVERY = "android.permission.RECOVERY";
@@ -417,6 +419,7 @@
     field public static final int allowClearUserDataOnFailedRestore = 16844288; // 0x1010600
     field public static final int gameSessionService = 16844373; // 0x1010655
     field public static final int hotwordDetectionService = 16844326; // 0x1010626
+    field @FlaggedApi("android.companion.virtual.flags.vdm_custom_ime") public static final int isVirtualDeviceOnly;
     field public static final int isVrOnly = 16844152; // 0x1010578
     field public static final int minExtensionVersion = 16844305; // 0x1010611
     field public static final int playHomeTransitionSound = 16844358; // 0x1010646
@@ -654,6 +657,7 @@
     field public static final String OPSTR_PLAY_AUDIO = "android:play_audio";
     field public static final String OPSTR_POST_NOTIFICATION = "android:post_notification";
     field public static final String OPSTR_PROJECT_MEDIA = "android:project_media";
+    field @FlaggedApi("android.view.contentprotection.flags.rapid_clear_notifications_by_listener_app_op_enabled") public static final String OPSTR_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER = "android:rapid_clear_notifications_by_listener";
     field public static final String OPSTR_READ_CLIPBOARD = "android:read_clipboard";
     field public static final String OPSTR_READ_ICC_SMS = "android:read_icc_sms";
     field public static final String OPSTR_READ_MEDIA_AUDIO = "android:read_media_audio";
@@ -3230,6 +3234,7 @@
     method @FlaggedApi("android.companion.virtual.flags.dynamic_policy") @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void removeActivityPolicyExemption(@NonNull android.content.ComponentName);
     method public void removeSoundEffectListener(@NonNull android.companion.virtual.VirtualDeviceManager.SoundEffectListener);
     method @FlaggedApi("android.companion.virtual.flags.dynamic_policy") @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void setDevicePolicy(int, int);
+    method @FlaggedApi("android.companion.virtual.flags.vdm_custom_ime") @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void setDisplayImePolicy(int, int);
     method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void setShowPointerIcon(boolean);
     method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void unregisterIntentInterceptor(@NonNull android.companion.virtual.VirtualDeviceManager.IntentInterceptorCallback);
   }
@@ -3246,6 +3251,7 @@
     method @Deprecated public int getDefaultNavigationPolicy();
     method public int getDevicePolicy(int);
     method @FlaggedApi("android.companion.virtual.flags.vdm_custom_home") @Nullable public android.content.ComponentName getHomeComponent();
+    method @FlaggedApi("android.companion.virtual.flags.vdm_custom_ime") @Nullable public android.content.ComponentName getInputMethodComponent();
     method public int getLockState();
     method @Nullable public String getName();
     method @NonNull public java.util.Set<android.os.UserHandle> getUsersWithMatchingAccounts();
@@ -3279,6 +3285,7 @@
     method @Deprecated @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setBlockedCrossTaskNavigations(@NonNull java.util.Set<android.content.ComponentName>);
     method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setDevicePolicy(int, int);
     method @FlaggedApi("android.companion.virtual.flags.vdm_custom_home") @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setHomeComponent(@Nullable android.content.ComponentName);
+    method @FlaggedApi("android.companion.virtual.flags.vdm_custom_ime") @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setInputMethodComponent(@Nullable android.content.ComponentName);
     method @NonNull @RequiresPermission(value=android.Manifest.permission.ADD_ALWAYS_UNLOCKED_DISPLAY, conditional=true) public android.companion.virtual.VirtualDeviceParams.Builder setLockState(int);
     method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setName(@NonNull String);
     method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setUsersWithMatchingAccounts(@NonNull java.util.Set<android.os.UserHandle>);
@@ -4004,7 +4011,7 @@
     field public static final int DELETE_FAILED_OWNER_BLOCKED = -4; // 0xfffffffc
     field public static final int DELETE_KEEP_DATA = 1; // 0x1
     field public static final int DELETE_SUCCEEDED = 1; // 0x1
-    field @FlaggedApi("android.permission.flags.device_aware_permission_apis") public static final String EXTRA_REQUEST_PERMISSIONS_DEVICE_ID = "android.content.pm.extra.REQUEST_PERMISSIONS_DEVICE_ID";
+    field @FlaggedApi("android.permission.flags.device_aware_permission_apis_enabled") public static final String EXTRA_REQUEST_PERMISSIONS_DEVICE_ID = "android.content.pm.extra.REQUEST_PERMISSIONS_DEVICE_ID";
     field public static final String EXTRA_REQUEST_PERMISSIONS_LEGACY_ACCESS_PERMISSION_NAMES = "android.content.pm.extra.REQUEST_PERMISSIONS_LEGACY_ACCESS_PERMISSION_NAMES";
     field public static final String EXTRA_REQUEST_PERMISSIONS_NAMES = "android.content.pm.extra.REQUEST_PERMISSIONS_NAMES";
     field public static final String EXTRA_REQUEST_PERMISSIONS_RESULTS = "android.content.pm.extra.REQUEST_PERMISSIONS_RESULTS";
@@ -4086,6 +4093,7 @@
     field @Deprecated public static final int MASK_PERMISSION_FLAGS = 255; // 0xff
     field public static final int MATCH_ANY_USER = 4194304; // 0x400000
     field public static final int MATCH_CLONE_PROFILE = 536870912; // 0x20000000
+    field @FlaggedApi("android.content.pm.fix_duplicated_flags") public static final long MATCH_CLONE_PROFILE_LONG = 17179869184L; // 0x400000000L
     field public static final int MATCH_FACTORY_ONLY = 2097152; // 0x200000
     field public static final int MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS = 536870912; // 0x20000000
     field public static final int MATCH_INSTANT = 8388608; // 0x800000
@@ -4109,7 +4117,7 @@
 
   public static interface PackageManager.OnPermissionsChangedListener {
     method public void onPermissionsChanged(int);
-    method @FlaggedApi("android.permission.flags.device_aware_permission_apis") public default void onPermissionsChanged(int, @NonNull String);
+    method @FlaggedApi("android.permission.flags.device_aware_permission_apis_enabled") public default void onPermissionsChanged(int, @NonNull String);
   }
 
   public static final class PackageManager.UninstallCompleteCallback implements android.os.Parcelable {
@@ -4191,12 +4199,15 @@
 
   public final class UserProperties implements android.os.Parcelable {
     method public int describeContents();
+    method public int getCrossProfileContentSharingStrategy();
     method public int getShowInQuietMode();
     method public int getShowInSharingSurfaces();
     method public boolean isCredentialShareableWithParent();
     method public boolean isMediaSharedWithParent();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.UserProperties> CREATOR;
+    field public static final int CROSS_PROFILE_CONTENT_SHARING_DELEGATE_FROM_PARENT = 1; // 0x1
+    field public static final int CROSS_PROFILE_CONTENT_SHARING_NO_DELEGATION = 0; // 0x0
     field public static final int SHOW_IN_QUIET_MODE_DEFAULT = 2; // 0x2
     field public static final int SHOW_IN_QUIET_MODE_HIDDEN = 1; // 0x1
     field public static final int SHOW_IN_QUIET_MODE_PAUSED = 0; // 0x0
@@ -4532,6 +4543,7 @@
 
   @FlaggedApi("com.android.internal.camera.flags.concert_mode") public static final class RequestProcessor.Request {
     ctor @FlaggedApi("com.android.internal.camera.flags.concert_mode") public RequestProcessor.Request(@NonNull java.util.List<java.lang.Integer>, @NonNull java.util.List<android.util.Pair<android.hardware.camera2.CaptureRequest.Key,java.lang.Object>>, int);
+    method @FlaggedApi("com.android.internal.camera.flags.concert_mode") @NonNull public java.util.List<android.util.Pair<android.hardware.camera2.CaptureRequest.Key,java.lang.Object>> getParameters();
   }
 
   @FlaggedApi("com.android.internal.camera.flags.concert_mode") public static interface RequestProcessor.RequestCallback {
@@ -9867,8 +9879,8 @@
     method @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public java.util.List<java.lang.String> getSubsetAids();
     method @FlaggedApi("android.nfc.enable_nfc_mainline") public int getUid();
     method @FlaggedApi("android.nfc.enable_nfc_mainline") public boolean hasCategory(@NonNull String);
+    method @FlaggedApi("android.nfc.enable_nfc_mainline") public boolean isCategoryOtherServiceEnabled();
     method @FlaggedApi("android.nfc.enable_nfc_mainline") public boolean isOnHost();
-    method @FlaggedApi("android.nfc.enable_nfc_mainline") public boolean isOtherServiceEnabled();
     method @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public CharSequence loadAppLabel(@NonNull android.content.pm.PackageManager);
     method @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public android.graphics.drawable.Drawable loadBanner(@NonNull android.content.pm.PackageManager);
     method @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public android.graphics.drawable.Drawable loadIcon(@NonNull android.content.pm.PackageManager);
@@ -9877,9 +9889,9 @@
     method @FlaggedApi("android.nfc.enable_nfc_mainline") public boolean requiresScreenOn();
     method @FlaggedApi("android.nfc.enable_nfc_mainline") public boolean requiresUnlock();
     method @FlaggedApi("android.nfc.enable_nfc_mainline") public void resetOffHostSecureElement();
+    method @FlaggedApi("android.nfc.enable_nfc_mainline") public void setCategoryOtherServiceEnabled(boolean);
     method @FlaggedApi("android.nfc.enable_nfc_mainline") public void setDynamicAidGroup(@NonNull android.nfc.cardemulation.AidGroup);
     method @FlaggedApi("android.nfc.enable_nfc_mainline") public void setOffHostSecureElement(@NonNull String);
-    method @FlaggedApi("android.nfc.enable_nfc_mainline") public void setOtherServiceEnabled(boolean);
     method @FlaggedApi("android.nfc.enable_nfc_mainline") public void writeToParcel(@NonNull android.os.Parcel, int);
     field @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public static final android.os.Parcelable.Creator<android.nfc.cardemulation.ApduServiceInfo> CREATOR;
   }
@@ -10917,13 +10929,13 @@
     method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_APP_HIBERNATION) public void onGetUnusedAppCount(@NonNull java.util.function.IntConsumer);
     method @BinderThread public abstract void onGrantOrUpgradeDefaultRuntimePermissions(@NonNull Runnable);
     method @Deprecated @BinderThread public void onOneTimePermissionSessionTimeout(@NonNull String);
-    method @FlaggedApi("android.permission.flags.device_aware_permission_apis") @BinderThread public void onOneTimePermissionSessionTimeout(@NonNull String, int);
+    method @FlaggedApi("android.permission.flags.device_aware_permission_apis_enabled") @BinderThread public void onOneTimePermissionSessionTimeout(@NonNull String, int);
     method @Deprecated @BinderThread public void onRestoreDelayedRuntimePermissionsBackup(@NonNull String, @NonNull android.os.UserHandle, @NonNull java.util.function.Consumer<java.lang.Boolean>);
     method @Deprecated @BinderThread public void onRestoreRuntimePermissionsBackup(@NonNull android.os.UserHandle, @NonNull java.io.InputStream, @NonNull Runnable);
     method @BinderThread public abstract void onRevokeRuntimePermission(@NonNull String, @NonNull String, @NonNull Runnable);
     method @BinderThread public abstract void onRevokeRuntimePermissions(@NonNull java.util.Map<java.lang.String,java.util.List<java.lang.String>>, boolean, int, @NonNull String, @NonNull java.util.function.Consumer<java.util.Map<java.lang.String,java.util.List<java.lang.String>>>);
     method @Deprecated @BinderThread public void onRevokeSelfPermissionsOnKill(@NonNull String, @NonNull java.util.List<java.lang.String>, @NonNull Runnable);
-    method @FlaggedApi("android.permission.flags.device_aware_permission_apis") @BinderThread public void onRevokeSelfPermissionsOnKill(@NonNull String, @NonNull java.util.List<java.lang.String>, int, @NonNull Runnable);
+    method @FlaggedApi("android.permission.flags.device_aware_permission_apis_enabled") @BinderThread public void onRevokeSelfPermissionsOnKill(@NonNull String, @NonNull java.util.List<java.lang.String>, int, @NonNull Runnable);
     method @Deprecated @BinderThread public abstract void onSetRuntimePermissionGrantStateByDeviceAdmin(@NonNull String, @NonNull String, @NonNull String, int, @NonNull java.util.function.Consumer<java.lang.Boolean>);
     method @BinderThread public void onSetRuntimePermissionGrantStateByDeviceAdmin(@NonNull String, @NonNull android.permission.AdminPermissionControlParams, @NonNull java.util.function.Consumer<java.lang.Boolean>);
     method @BinderThread public void onStageAndApplyRuntimePermissionsBackup(@NonNull android.os.UserHandle, @NonNull java.io.InputStream, @NonNull Runnable);
@@ -12919,6 +12931,7 @@
     field public static final int CONFIDENCE_LEVEL_LOW = 1; // 0x1
     field public static final int CONFIDENCE_LEVEL_MEDIUM = 2; // 0x2
     field public static final int CONFIDENCE_LEVEL_NONE = 0; // 0x0
+    field @FlaggedApi("android.service.voice.flags.allow_hotword_bump_egress") public static final int CONFIDENCE_LEVEL_VERY_HIGH = 4; // 0x4
     field @NonNull public static final android.os.Parcelable.Creator<android.service.voice.HotwordRejectedResult> CREATOR;
   }
 
@@ -13040,7 +13053,7 @@
     method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_HOTWORD_DETECTION) public final android.service.voice.HotwordDetector createHotwordDetector(@Nullable android.os.PersistableBundle, @Nullable android.os.SharedMemory, @NonNull java.util.concurrent.Executor, @NonNull android.service.voice.HotwordDetector.Callback);
     method @NonNull @RequiresPermission("android.permission.MANAGE_VOICE_KEYPHRASES") public final android.media.voice.KeyphraseModelManager createKeyphraseModelManager();
     method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_HOTWORD_DETECTION) public final android.service.voice.VisualQueryDetector createVisualQueryDetector(@Nullable android.os.PersistableBundle, @Nullable android.os.SharedMemory, @NonNull java.util.concurrent.Executor, @NonNull android.service.voice.VisualQueryDetector.Callback);
-    method @FlaggedApi("android.service.voice.flags.allow_training_data_egress_from_hds") @RequiresPermission(android.Manifest.permission.MANAGE_HOTWORD_DETECTION) public void setIsReceiveSandboxedTrainingDataAllowed(boolean);
+    method @FlaggedApi("android.service.voice.flags.allow_training_data_egress_from_hds") @RequiresPermission(android.Manifest.permission.MANAGE_HOTWORD_DETECTION) public void setShouldReceiveSandboxedTrainingData(boolean);
   }
 
 }
@@ -13690,6 +13703,7 @@
     method @NonNull public java.util.List<java.lang.Boolean> areCarrierIdentifiersAllowed(@NonNull java.util.List<android.service.carrier.CarrierIdentifier>);
     method public int describeContents();
     method @NonNull public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers();
+    method @FlaggedApi("com.android.internal.telephony.flags.carrier_restriction_status") public int getCarrierRestrictionStatus();
     method public int getDefaultCarrierRestriction();
     method @NonNull public java.util.List<android.service.carrier.CarrierIdentifier> getExcludedCarriers();
     method public int getMultiSimPolicy();
@@ -14584,6 +14598,7 @@
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAnyRadioPoweredOn();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isApnMetered(int);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isApplicationOnUicc(int);
+    method @FlaggedApi("com.android.internal.telephony.flags.enable_identifier_disclosure_transparency") @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isCellularIdentifierDisclosureNotificationsEnabled();
     method public boolean isDataConnectivityPossible();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isDataEnabledForApn(int);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isEmergencyAssistanceEnabled();
@@ -14631,6 +14646,7 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataActivationState(int);
     method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(int, boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataRoamingEnabled(boolean);
+    method @FlaggedApi("com.android.internal.telephony.flags.enable_identifier_disclosure_transparency") @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setEnableCellularIdentifierDisclosureNotifications(boolean);
     method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.PinResult setIccLockEnabled(boolean, @NonNull String);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMobileDataPolicyEnabled(int, boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMultiSimCarrierRestriction(boolean);
@@ -16974,7 +16990,7 @@
     method @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") @NonNull @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public java.util.Set<java.lang.Integer> getSatelliteAttachRestrictionReasonsForCarrier(int);
     method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void pollPendingSatelliteDatagrams(@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 provisionSatelliteService(@NonNull String, @NonNull byte[], @Nullable android.os.CancellationSignal, @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 int registerForNtnSignalStrengthChanged(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.NtnSignalStrengthCallback);
+    method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void registerForNtnSignalStrengthChanged(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.NtnSignalStrengthCallback) throws android.telephony.satellite.SatelliteManager.SatelliteException;
     method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public int registerForSatelliteCapabilitiesChanged(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.SatelliteCapabilitiesCallback);
     method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public int registerForSatelliteDatagram(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.SatelliteDatagramCallback);
     method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public int registerForSatelliteModemStateChanged(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.SatelliteStateCallback);
@@ -16986,7 +17002,7 @@
     method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void requestIsSatelliteEnabled(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Boolean,android.telephony.satellite.SatelliteManager.SatelliteException>);
     method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void requestIsSatelliteProvisioned(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Boolean,android.telephony.satellite.SatelliteManager.SatelliteException>);
     method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public void requestIsSatelliteSupported(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Boolean,android.telephony.satellite.SatelliteManager.SatelliteException>);
-    method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @NonNull @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void requestNtnSignalStrength(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.telephony.satellite.NtnSignalStrength,android.telephony.satellite.SatelliteManager.SatelliteException>);
+    method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void requestNtnSignalStrength(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.telephony.satellite.NtnSignalStrength,android.telephony.satellite.SatelliteManager.SatelliteException>);
     method @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void requestSatelliteAttachEnabledForCarrier(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 requestSatelliteCapabilities(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.telephony.satellite.SatelliteCapabilities,android.telephony.satellite.SatelliteManager.SatelliteException>);
     method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void requestSatelliteEnabled(boolean, boolean, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
@@ -17169,6 +17185,9 @@
     method @NonNull public default java.util.List<android.content.ComponentName> notifyScreenshotListeners(int);
     method public default void registerTaskFpsCallback(@IntRange(from=0) int, @NonNull java.util.concurrent.Executor, @NonNull android.window.TaskFpsCallback);
     method public default void unregisterTaskFpsCallback(@NonNull android.window.TaskFpsCallback);
+    field public static final int DISPLAY_IME_POLICY_FALLBACK_DISPLAY = 1; // 0x1
+    field public static final int DISPLAY_IME_POLICY_HIDE = 2; // 0x2
+    field public static final int DISPLAY_IME_POLICY_LOCAL = 0; // 0x0
   }
 
   public static class WindowManager.LayoutParams extends android.view.ViewGroup.LayoutParams implements android.os.Parcelable {
@@ -17289,6 +17308,10 @@
 
 package android.view.inputmethod {
 
+  public final class InputMethodInfo implements android.os.Parcelable {
+    method @FlaggedApi("android.companion.virtual.flags.vdm_custom_ime") public boolean isVirtualDeviceOnly();
+  }
+
   public final class InputMethodManager {
     method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public android.view.inputmethod.InputMethodInfo getCurrentInputMethodInfoAsUser(@NonNull android.os.UserHandle);
   }
diff --git a/core/api/system-lint-baseline.txt b/core/api/system-lint-baseline.txt
index dec1ee5..cef11bb 100644
--- a/core/api/system-lint-baseline.txt
+++ b/core/api/system-lint-baseline.txt
@@ -1909,6 +1909,8 @@
     SAM-compatible parameters (such as parameter 1, "listener", in android.view.accessibility.AccessibilityManager.addAccessibilityStateChangeListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.view.accessibility.AccessibilityManager#addTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener, android.os.Handler):
     SAM-compatible parameters (such as parameter 1, "listener", in android.view.accessibility.AccessibilityManager.addTouchExplorationStateChangeListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.view.inputmethod.InputMethodInfo#dump(android.util.Printer, String):
+    SAM-compatible parameters (such as parameter 1, "pw", in android.view.inputmethod.InputMethodInfo.dump) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.webkit.WebChromeClient#onShowFileChooser(android.webkit.WebView, android.webkit.ValueCallback<android.net.Uri[]>, android.webkit.WebChromeClient.FileChooserParams):
     SAM-compatible parameters (such as parameter 2, "filePathCallback", in android.webkit.WebChromeClient.onShowFileChooser) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 98a78cf..1a0e20c 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -2,6 +2,7 @@
 package android {
 
   public static final class Manifest.permission {
+    field @FlaggedApi("com.android.server.accessibility.motion_event_observing") public static final String ACCESSIBILITY_MOTION_EVENT_OBSERVING = "android.permission.ACCESSIBILITY_MOTION_EVENT_OBSERVING";
     field public static final String ACCESS_NOTIFICATIONS = "android.permission.ACCESS_NOTIFICATIONS";
     field public static final String ACTIVITY_EMBEDDING = "android.permission.ACTIVITY_EMBEDDING";
     field public static final String ADJUST_RUNTIME_PERMISSIONS_POLICY = "android.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY";
@@ -99,6 +100,8 @@
 
   public class AccessibilityServiceInfo implements android.os.Parcelable {
     method @NonNull public android.content.ComponentName getComponentName();
+    method @FlaggedApi("android.view.accessibility.motion_event_observing") public int getObservedMotionEventSources();
+    method @FlaggedApi("android.view.accessibility.motion_event_observing") public void setObservedMotionEventSources(int);
   }
 
 }
@@ -259,6 +262,7 @@
     field public static final String OPSTR_ACTIVITY_RECOGNITION_SOURCE = "android:activity_recognition_source";
     field public static final String OPSTR_MANAGE_ONGOING_CALLS = "android:manage_ongoing_calls";
     field public static final String OPSTR_RECORD_AUDIO_HOTWORD = "android:record_audio_hotword";
+    field public static final String OPSTR_RESERVED_FOR_TESTING = "android:reserved_for_testing";
     field public static final String OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER = "android:use_icc_auth_with_device_identifier";
     field public static final int OP_COARSE_LOCATION = 0; // 0x0
     field public static final int OP_RECORD_AUDIO = 27; // 0x1b
@@ -878,7 +882,6 @@
 
   public final class CompanionDeviceManager {
     method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public void enableSecureTransport(boolean);
-    field @FlaggedApi("android.companion.companion_transport_apis") public static final int MESSAGE_REQUEST_PING = 1669362552; // 0x63807378
   }
 
   public abstract class CompanionDeviceService extends android.app.Service {
@@ -902,7 +905,7 @@
     ctor public AttributionSource(int, @Nullable String, @Nullable String, @NonNull android.os.IBinder);
     ctor public AttributionSource(int, @Nullable String, @Nullable String, @Nullable java.util.Set<java.lang.String>, @Nullable android.content.AttributionSource);
     ctor @FlaggedApi("android.permission.flags.attribution_source_constructor") public AttributionSource(int, int, @Nullable String, @Nullable String, @NonNull android.os.IBinder, @Nullable String[], @Nullable android.content.AttributionSource);
-    ctor @FlaggedApi("android.permission.flags.device_aware_permission_apis") public AttributionSource(int, int, @Nullable String, @Nullable String, @NonNull android.os.IBinder, @Nullable String[], int, @Nullable android.content.AttributionSource);
+    ctor @FlaggedApi("android.permission.flags.device_aware_permission_apis_enabled") public AttributionSource(int, int, @Nullable String, @Nullable String, @NonNull android.os.IBinder, @Nullable String[], int, @Nullable android.content.AttributionSource);
     method public void enforceCallingPid();
   }
 
@@ -1165,6 +1168,7 @@
   public static final class UserProperties.Builder {
     ctor public UserProperties.Builder();
     method @NonNull public android.content.pm.UserProperties build();
+    method @NonNull public android.content.pm.UserProperties.Builder setCrossProfileContentSharingStrategy(int);
     method @NonNull public android.content.pm.UserProperties.Builder setShowInQuietMode(int);
     method @NonNull public android.content.pm.UserProperties.Builder setShowInSharingSurfaces(int);
   }
@@ -3617,9 +3621,6 @@
     method public default void setShouldShowWithInsecureKeyguard(int, boolean);
     method public default boolean shouldShowSystemDecors(int);
     method @Nullable public default android.graphics.Bitmap snapshotTaskForRecents(@IntRange(from=0) int);
-    field public static final int DISPLAY_IME_POLICY_FALLBACK_DISPLAY = 1; // 0x1
-    field public static final int DISPLAY_IME_POLICY_HIDE = 2; // 0x2
-    field public static final int DISPLAY_IME_POLICY_LOCAL = 0; // 0x0
     field public static final int LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP = 600; // 0x258
   }
 
diff --git a/core/java/android/accessibilityservice/AccessibilityGestureEvent.java b/core/java/android/accessibilityservice/AccessibilityGestureEvent.java
index 8e01779..15e29c2 100644
--- a/core/java/android/accessibilityservice/AccessibilityGestureEvent.java
+++ b/core/java/android/accessibilityservice/AccessibilityGestureEvent.java
@@ -150,12 +150,13 @@
     private final int mDisplayId;
     private List<MotionEvent> mMotionEvents = new ArrayList<>();
 
-/**
- * Constructs an AccessibilityGestureEvent to be dispatched to an accessibility service.
- * @param gestureId the id number of the gesture.
- * @param displayId the display on which this gesture was performed.
- * @param motionEvents the motion events that lead to this gesture.
- */
+    /**
+     * Constructs an AccessibilityGestureEvent to be dispatched to an accessibility service.
+     *
+     * @param gestureId    the id number of the gesture.
+     * @param displayId    the display on which this gesture was performed.
+     * @param motionEvents the motion events that lead to this gesture.
+     */
     public AccessibilityGestureEvent(
             int gestureId, int displayId, @NonNull List<MotionEvent> motionEvents) {
         mGestureId = gestureId;
@@ -205,6 +206,29 @@
         return mMotionEvents;
     }
 
+    /**
+     * When we asynchronously use {@link AccessibilityGestureEvent}, we should make a copy,
+     * because motionEvent may be recycled before we use async.
+     *
+     * @hide
+     */
+    @NonNull
+    public AccessibilityGestureEvent copyForAsync() {
+        return new AccessibilityGestureEvent(mGestureId, mDisplayId,
+                mMotionEvents.stream().map(MotionEvent::copy).toList());
+    }
+
+    /**
+     * After we use {@link AccessibilityGestureEvent} asynchronously, we should recycle the
+     * MotionEvent, avoid memory leaks.
+     *
+     * @hide
+     */
+    public void recycle() {
+        mMotionEvents.forEach(MotionEvent::recycle);
+        mMotionEvents.clear();
+    }
+
     @NonNull
     @Override
     public String toString() {
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index 8ad6ea2..fc342fa 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -20,6 +20,7 @@
 import static android.accessibilityservice.util.AccessibilityUtils.loadSafeAnimatedImage;
 import static android.content.pm.PackageManager.FEATURE_FINGERPRINT;
 
+import android.annotation.FlaggedApi;
 import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
@@ -53,6 +54,7 @@
 import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.Flags;
 
 import com.android.internal.R;
 import com.android.internal.compat.IPlatformCompat;
@@ -630,7 +632,8 @@
             InputDevice.SOURCE_TOUCH_NAVIGATION,
             InputDevice.SOURCE_ROTARY_ENCODER,
             InputDevice.SOURCE_JOYSTICK,
-            InputDevice.SOURCE_SENSOR
+            InputDevice.SOURCE_SENSOR,
+            InputDevice.SOURCE_TOUCHSCREEN
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface MotionEventSources {}
@@ -642,6 +645,8 @@
     @MotionEventSources
     private int mMotionEventSources = 0;
 
+    private int mObservedMotionEventSources = 0;
+
     /**
      * Creates a new instance.
      */
@@ -817,6 +822,9 @@
         mInteractiveUiTimeout = other.mInteractiveUiTimeout;
         flags = other.flags;
         mMotionEventSources = other.mMotionEventSources;
+        if (Flags.motionEventObserving()) {
+            setObservedMotionEventSources(other.mObservedMotionEventSources);
+        }
         // NOTE: Ensure that only properties that are safe to be modified by the service itself
         // are included here (regardless of hidden setters, etc.).
     }
@@ -1024,16 +1032,75 @@
      */
     public void setMotionEventSources(@MotionEventSources int motionEventSources) {
         mMotionEventSources = motionEventSources;
+        mObservedMotionEventSources = 0;
+    }
+
+    /**
+     * Sets the bit mask of {@link android.view.InputDevice} sources that the accessibility service
+     * wants to observe generic {@link android.view.MotionEvent}s from if it has already requested
+     * to listen to them using {@link #setMotionEventSources(int)}. Events from these sources will
+     * be sent to the rest of the input pipeline without being consumed by accessibility services.
+     * This service will still be able to see them.
+     *
+     * <p><strong>Note:</strong> you will need to call this function every time you call {@link
+     * #setMotionEventSources(int)}. Calling {@link #setMotionEventSources(int)} clears the list of
+     * observed motion event sources for this service.
+     *
+     * <p><strong>Note:</strong> {@link android.view.InputDevice} sources contain source class bits
+     * that complicate bitwise flag removal operations. To remove a specific source you should
+     * rebuild the entire value using bitwise OR operations on the individual source constants.
+     *
+     * <p>Including an {@link android.view.InputDevice} source that does not send {@link
+     * android.view.MotionEvent}s is effectively a no-op for that source, since you will not receive
+     * any events from that source.
+     *
+     * <p><strong>Note:</strong> Calling this function with a source that has not been listened to
+     * using {@link #setMotionEventSources(int)} will throw an exception.
+     *
+     * @see AccessibilityService#onMotionEvent
+     * @see #MotionEventSources
+     * @see #setMotionEventSources(int)
+     * @hide
+     */
+    @FlaggedApi(Flags.FLAG_MOTION_EVENT_OBSERVING)
+    @TestApi
+    public void setObservedMotionEventSources(int observedMotionEventSources) {
+        // Confirm that any sources requested here have already been requested for listening.
+        if ((observedMotionEventSources & ~mMotionEventSources) != 0) {
+            String message =
+                    String.format(
+                            "Requested motion event sources for listening = 0x%x but requested"
+                                    + " motion event sources for observing = 0x%x.",
+                            mMotionEventSources, observedMotionEventSources);
+            throw new IllegalArgumentException(message);
+        }
+        mObservedMotionEventSources = observedMotionEventSources;
+    }
+
+    /**
+     * Returns the bit mask of {@link android.view.InputDevice} sources that the accessibility
+     * service wants to observe generic {@link android.view.MotionEvent}s from if it has already
+     * requested to listen to them using {@link #setMotionEventSources(int)}. Events from these
+     * sources will be sent to the rest of the input pipeline without being consumed by
+     * accessibility services. This service will still be able to see them.
+     *
+     * @hide
+     */
+    @FlaggedApi(Flags.FLAG_MOTION_EVENT_OBSERVING)
+    @MotionEventSources
+    @TestApi
+    public int getObservedMotionEventSources() {
+        return mObservedMotionEventSources;
     }
 
     /**
      * The localized summary of the accessibility service.
-     * <p>
-     *    <strong>Statically set from
-     *    {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong>
-     * </p>
-     * @return The localized summary if available, and {@code null} if a summary
-     * has not been provided.
+     *
+     * <p><strong>Statically set from {@link AccessibilityService#SERVICE_META_DATA
+     * meta-data}.</strong>
+     *
+     * @return The localized summary if available, and {@code null} if a summary has not been
+     *     provided.
      */
     public CharSequence loadSummary(PackageManager packageManager) {
         if (mSummaryResId == 0) {
@@ -1260,6 +1327,7 @@
         parcel.writeString(mTileServiceName);
         parcel.writeInt(mIntroResId);
         parcel.writeInt(mMotionEventSources);
+        parcel.writeInt(mObservedMotionEventSources);
     }
 
     private void initFromParcel(Parcel parcel) {
@@ -1285,6 +1353,8 @@
         mTileServiceName = parcel.readString();
         mIntroResId = parcel.readInt();
         mMotionEventSources = parcel.readInt();
+        // use the setter here because it throws an exception for invalid values.
+        setObservedMotionEventSources(parcel.readInt());
     }
 
     @Override
diff --git a/core/java/android/accessibilityservice/AccessibilityTrace.java b/core/java/android/accessibilityservice/AccessibilityTrace.java
index 7700b33..87304c8 100644
--- a/core/java/android/accessibilityservice/AccessibilityTrace.java
+++ b/core/java/android/accessibilityservice/AccessibilityTrace.java
@@ -36,7 +36,7 @@
             "IAccessibilityInteractionConnectionCallback";
     String NAME_REMOTE_MAGNIFICATION_ANIMATION_CALLBACK = "IRemoteMagnificationAnimationCallback";
     String NAME_MAGNIFICATION_CONNECTION = "IMagnificationConnection";
-    String NAME_WINDOW_MAGNIFICATION_CONNECTION_CALLBACK = "IWindowMagnificationConnectionCallback";
+    String NAME_MAGNIFICATION_CONNECTION_CALLBACK = "IMagnificationConnectionCallback";
     String NAME_WINDOW_MANAGER_INTERNAL = "WindowManagerInternal";
     String NAME_WINDOWS_FOR_ACCESSIBILITY_CALLBACK = "WindowsForAccessibilityCallback";
     String NAME_MAGNIFICATION_CALLBACK = "MagnificationCallbacks";
@@ -59,7 +59,7 @@
     long FLAGS_ACCESSIBILITY_INTERACTION_CONNECTION_CALLBACK = 0x0000000000000020L;
     long FLAGS_REMOTE_MAGNIFICATION_ANIMATION_CALLBACK = 0x0000000000000040L;
     long FLAGS_MAGNIFICATION_CONNECTION = 0x0000000000000080L;
-    long FLAGS_WINDOW_MAGNIFICATION_CONNECTION_CALLBACK = 0x0000000000000100L;
+    long FLAGS_MAGNIFICATION_CONNECTION_CALLBACK = 0x0000000000000100L;
     long FLAGS_WINDOW_MANAGER_INTERNAL = 0x0000000000000200L;
     long FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK = 0x0000000000000400L;
     long FLAGS_MAGNIFICATION_CALLBACK = 0x0000000000000800L;
@@ -100,8 +100,8 @@
             new AbstractMap.SimpleEntry<String, Long>(
                     NAME_MAGNIFICATION_CONNECTION, FLAGS_MAGNIFICATION_CONNECTION),
             new AbstractMap.SimpleEntry<String, Long>(
-                    NAME_WINDOW_MAGNIFICATION_CONNECTION_CALLBACK,
-                    FLAGS_WINDOW_MAGNIFICATION_CONNECTION_CALLBACK),
+                    NAME_MAGNIFICATION_CONNECTION_CALLBACK,
+                    FLAGS_MAGNIFICATION_CONNECTION_CALLBACK),
             new AbstractMap.SimpleEntry<String, Long>(
                     NAME_WINDOW_MANAGER_INTERNAL, FLAGS_WINDOW_MANAGER_INTERNAL),
             new AbstractMap.SimpleEntry<String, Long>(
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index c52d27ea..5674a10 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -3061,10 +3061,10 @@
     }
 
     /**
-     * Request to put the a freeform activity into fullscreen. This will only be allowed if the
-     * activity is on a freeform display, such as a desktop device. The requester has to be the
-     * top-most activity of the focused display, and the request should be a response to a user
-     * input. When getting fullscreen and receiving corresponding
+     * Request to put the freeform activity into fullscreen. The requester has to be the top-most
+     * activity of the focused display which can be verified using
+     * {@link #onTopResumedActivityChanged(boolean)}. The request should also be a response to a
+     * user input. When getting fullscreen and receiving corresponding
      * {@link #onConfigurationChanged(Configuration)} and
      * {@link #onMultiWindowModeChanged(boolean, Configuration)}, the activity should relayout
      * itself and the system bars' visibilities can be controlled as usual fullscreen apps.
@@ -3072,11 +3072,6 @@
      * Calling it again with the exit request can restore the activity to the previous status.
      * This will only happen when it got into fullscreen through this API.
      *
-     * If an app wants to be in fullscreen always, it should claim as not being resizable
-     * by setting
-     * <a href="https://developer.android.com/guide/topics/large-screens/multi-window-support#resizeableActivity">
-     * {@code android:resizableActivity="false"}</a> instead of calling this API.
-     *
      * @param request Can be {@link #FULLSCREEN_MODE_REQUEST_ENTER} or
      *                {@link #FULLSCREEN_MODE_REQUEST_EXIT} to indicate this request is to get
      *                fullscreen or get restored.
@@ -5572,7 +5567,7 @@
      * @see #shouldShowRequestPermissionRationale
      * @see Context#DEVICE_ID_DEFAULT
      */
-    @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS)
+    @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
     public final void requestPermissions(@NonNull String[] permissions, int requestCode,
             int deviceId) {
         if (requestCode < 0) {
@@ -5645,7 +5640,7 @@
      *
      * @see #requestPermissions
      */
-    @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS)
+    @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
     public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
             @NonNull int[] grantResults, int deviceId) {
         onRequestPermissionsResult(requestCode, permissions, grantResults);
@@ -5678,7 +5673,7 @@
      * @see #requestPermissions
      * @see #onRequestPermissionsResult
      */
-    @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS)
+    @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
     public boolean shouldShowRequestPermissionRationale(@NonNull String permission, int deviceId) {
         final PackageManager packageManager = getDeviceId() == deviceId ? getPackageManager()
                 : createDeviceContext(deviceId).getPackageManager();
@@ -6884,8 +6879,8 @@
      * application package was involved.
      *
      * <p>If called while inside the handling of {@link #onNewIntent}, this function will
-     * return the referrer that submitted that new intent to the activity.  Otherwise, it
-     * always returns the referrer of the original Intent.</p>
+     * return the referrer that submitted that new intent to the activity only after
+     * {@link #setIntent(Intent)} is called with the provided intent.</p>
      *
      * <p>Note that this is <em>not</em> a security feature -- you can not trust the
      * referrer information, applications can spoof it.</p>
@@ -9387,6 +9382,7 @@
      * @param allowed {@code true} to disable the UID restrictions; {@code false} to revert back to
      *                            the default behaviour
      */
+    @FlaggedApi(android.security.Flags.FLAG_ASM_RESTRICTIONS_ENABLED)
     public void setAllowCrossUidActivitySwitchFromBelow(boolean allowed) {
         ActivityClient.getInstance().setAllowCrossUidActivitySwitchFromBelow(mToken, allowed);
     }
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index adaaee2..6ddb36a 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1544,11 +1544,12 @@
         @Override
         public void dumpMemInfo(ParcelFileDescriptor pfd, Debug.MemoryInfo mem, boolean checkin,
                 boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly,
-                boolean dumpUnreachable, String[] args) {
+                boolean dumpUnreachable, boolean dumpAllocatorStats, String[] args) {
             FileOutputStream fout = new FileOutputStream(pfd.getFileDescriptor());
             PrintWriter pw = new FastPrintWriter(fout);
             try {
-                dumpMemInfo(pw, mem, checkin, dumpFullInfo, dumpDalvik, dumpSummaryOnly, dumpUnreachable);
+                dumpMemInfo(pw, mem, checkin, dumpFullInfo, dumpDalvik, dumpSummaryOnly,
+                            dumpUnreachable, dumpAllocatorStats);
             } finally {
                 pw.flush();
                 IoUtils.closeQuietly(pfd);
@@ -1557,7 +1558,8 @@
 
         @NeverCompile
         private void dumpMemInfo(PrintWriter pw, Debug.MemoryInfo memInfo, boolean checkin,
-                boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly, boolean dumpUnreachable) {
+                boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly,
+                boolean dumpUnreachable, boolean dumpAllocatorStats) {
             long nativeMax = Debug.getNativeHeapSize() / 1024;
             long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
             long nativeFree = Debug.getNativeHeapFreeSize() / 1024;
@@ -1710,6 +1712,9 @@
                 pw.println(" Unreachable memory");
                 pw.print(Debug.getUnreachableMemory(100, showContents));
             }
+            if (dumpAllocatorStats) {
+                Debug.logAllocatorStats();
+            }
         }
 
         @NeverCompile
@@ -4072,7 +4077,7 @@
         final LoadedApk sdkApk = getPackageInfo(
                 contextInfo.getSdkApplicationInfo(),
                 r.packageInfo.getCompatibilityInfo(),
-                ActivityContextInfo.CONTEXT_FLAGS);
+                contextInfo.getContextFlags());
 
         final ContextImpl activityContext = ContextImpl.createActivityContext(
                 this, sdkApk, r.activityInfo, r.token, displayId, r.overrideConfig);
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 71fe47e..4b24b1f 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -16,8 +16,9 @@
 
 package android.app;
 
-import static android.view.contentprotection.flags.Flags.FLAG_CREATE_ACCESSIBILITY_OVERLAY_APP_OP_ENABLED;
 import static android.permission.flags.Flags.FLAG_OP_ENABLE_MOBILE_DATA_BY_USER;
+import static android.view.contentprotection.flags.Flags.FLAG_CREATE_ACCESSIBILITY_OVERLAY_APP_OP_ENABLED;
+import static android.view.contentprotection.flags.Flags.FLAG_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER_APP_OP_ENABLED;
 
 import static java.lang.Long.max;
 
@@ -1508,6 +1509,7 @@
      */
     public static final int OP_CREATE_ACCESSIBILITY_OVERLAY =
             AppProtoEnums.APP_OP_CREATE_ACCESSIBILITY_OVERLAY;
+
     /**
      * Indicate that the user has enabled or disabled mobile data
      * @hide
@@ -1521,9 +1523,25 @@
      */
     public static final int OP_MEDIA_ROUTING_CONTROL = AppProtoEnums.APP_OP_MEDIA_ROUTING_CONTROL;
 
+    /**
+     * Op code for use by tests to avoid interfering history logs that the wider system might
+     * trigger.
+     *
+     * @hide
+     */
+    public static final int OP_RESERVED_FOR_TESTING = AppProtoEnums.APP_OP_RESERVED_FOR_TESTING;
+
+    /**
+     * Rapid clearing of notifications by a notification listener, see b/289080543 for details
+     *
+     * @hide
+     */
+    public static final int OP_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER =
+            AppProtoEnums.APP_OP_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER;
+
     /** @hide */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public static final int _NUM_OP = 141;
+    public static final int _NUM_OP = 143;
 
     /**
      * All app ops represented as strings.
@@ -1671,6 +1689,8 @@
             OPSTR_CREATE_ACCESSIBILITY_OVERLAY,
             OPSTR_MEDIA_ROUTING_CONTROL,
             OPSTR_ENABLE_MOBILE_DATA_BY_USER,
+            OPSTR_RESERVED_FOR_TESTING,
+            OPSTR_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER,
     })
     public @interface AppOpString {}
 
@@ -2321,6 +2341,7 @@
     @FlaggedApi(FLAG_CREATE_ACCESSIBILITY_OVERLAY_APP_OP_ENABLED)
     public static final String OPSTR_CREATE_ACCESSIBILITY_OVERLAY =
             "android:create_accessibility_overlay";
+
     /**
      * Indicate that the user has enabled or disabled mobile data
      * @hide
@@ -2330,6 +2351,27 @@
     public static final String OPSTR_ENABLE_MOBILE_DATA_BY_USER =
             "android:enable_mobile_data_by_user";
 
+    /**
+     * Reserved for use by appop tests so that operations done legitimately by the platform don't
+     * interfere with expected results. Platform code should never use this.
+     *
+     * @hide
+     */
+    @TestApi
+    @SuppressLint("UnflaggedApi")
+    public static final String OPSTR_RESERVED_FOR_TESTING =
+            "android:reserved_for_testing";
+
+    /**
+     * Rapid clearing of notifications by a notification listener, see b/289080543 for details
+     *
+     * @hide
+     */
+    @SystemApi
+    @FlaggedApi(FLAG_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER_APP_OP_ENABLED)
+    public static final String OPSTR_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER =
+            "android:rapid_clear_notifications_by_listener";
+
     /** {@link #sAppOpsToNote} not initialized yet for this op */
     private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0;
     /** Should not collect noting of this app-op in {@link #sAppOpsToNote} */
@@ -2887,6 +2929,12 @@
                 .setPermission(Manifest.permission.MEDIA_ROUTING_CONTROL).build(),
         new AppOpInfo.Builder(OP_ENABLE_MOBILE_DATA_BY_USER, OPSTR_ENABLE_MOBILE_DATA_BY_USER,
                 "ENABLE_MOBILE_DATA_BY_USER").setDefaultMode(AppOpsManager.MODE_ALLOWED).build(),
+        new AppOpInfo.Builder(OP_RESERVED_FOR_TESTING, OPSTR_RESERVED_FOR_TESTING,
+                "OP_RESERVED_FOR_TESTING").setDefaultMode(AppOpsManager.MODE_ALLOWED).build(),
+        new AppOpInfo.Builder(OP_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER,
+                OPSTR_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER,
+                "RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER")
+                .setDefaultMode(AppOpsManager.MODE_ALLOWED).build(),
     };
 
     // The number of longs needed to form a full bitmask of app ops
diff --git a/core/java/android/app/ApplicationStartInfo.java b/core/java/android/app/ApplicationStartInfo.java
index c8317c8..656feb0 100644
--- a/core/java/android/app/ApplicationStartInfo.java
+++ b/core/java/android/app/ApplicationStartInfo.java
@@ -104,14 +104,17 @@
     /** Process started due to Activity started for any reason not explicitly listed. */
     public static final int START_REASON_START_ACTIVITY = 11;
 
+    /** Start type not yet set. */
+    public static final int START_TYPE_UNSET = 0;
+
     /** Process started from scratch. */
-    public static final int START_TYPE_COLD = 0;
+    public static final int START_TYPE_COLD = 1;
 
     /** Process retained minimally SavedInstanceState. */
-    public static final int START_TYPE_WARM = 1;
+    public static final int START_TYPE_WARM = 2;
 
     /** Process brought back to foreground. */
-    public static final int START_TYPE_HOT = 2;
+    public static final int START_TYPE_HOT = 3;
 
     /**
      * Default. The system always creates a new instance of the activity in the target task and
@@ -277,6 +280,7 @@
     @IntDef(
             prefix = {"START_TYPE_"},
             value = {
+                START_TYPE_UNSET,
                 START_TYPE_COLD,
                 START_TYPE_WARM,
                 START_TYPE_HOT,
@@ -769,6 +773,7 @@
 
     private static String startTypeToString(@StartType int startType) {
         return switch (startType) {
+            case START_TYPE_UNSET -> "UNSET";
             case START_TYPE_COLD -> "COLD";
             case START_TYPE_WARM -> "WARM";
             case START_TYPE_HOT -> "HOT";
diff --git a/core/java/android/app/AutomaticZenRule.java b/core/java/android/app/AutomaticZenRule.java
index d935449..343348b 100644
--- a/core/java/android/app/AutomaticZenRule.java
+++ b/core/java/android/app/AutomaticZenRule.java
@@ -16,6 +16,8 @@
 
 package android.app;
 
+import static com.android.internal.util.Preconditions.checkArgument;
+
 import android.annotation.DrawableRes;
 import android.annotation.FlaggedApi;
 import android.annotation.IntDef;
@@ -390,7 +392,7 @@
      */
     @FlaggedApi(Flags.FLAG_MODES_API)
     public void setType(@Type int type) {
-        mType = type;
+        mType = checkValidType(type);
     }
 
     /**
@@ -451,6 +453,24 @@
         mAllowManualInvocation = allowManualInvocation;
     }
 
+    /** @hide */
+    @FlaggedApi(Flags.FLAG_MODES_API)
+    public void validate() {
+        if (Flags.modesApi()) {
+            checkValidType(mType);
+        }
+    }
+
+    @FlaggedApi(Flags.FLAG_MODES_API)
+    @Type
+    private static int checkValidType(@Type int type) {
+        checkArgument(type >= TYPE_UNKNOWN && type <= TYPE_MANAGED,
+                "Rule type must be one of TYPE_UNKNOWN, TYPE_OTHER, TYPE_SCHEDULE_TIME, "
+                        + "TYPE_SCHEDULE_CALENDAR, TYPE_BEDTIME, TYPE_DRIVING, TYPE_IMMERSIVE, "
+                        + "TYPE_THEATER, or TYPE_MANAGED");
+        return type;
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -625,8 +645,8 @@
         }
 
         public Builder(@NonNull String name, @NonNull Uri conditionId) {
-            mName = name;
-            mConditionId = conditionId;
+            mName = Objects.requireNonNull(name);
+            mConditionId = Objects.requireNonNull(conditionId);
         }
 
         /**
@@ -703,10 +723,10 @@
         }
 
         /**
-         * Sets the type of the rule
+         * Sets the type of the rule.
          */
         public @NonNull Builder setType(@Type int type) {
-            mType = type;
+            mType = checkValidType(type);
             return this;
         }
 
@@ -714,7 +734,7 @@
          * Sets a user visible description of when this rule will be active
          * (see {@link Condition#STATE_TRUE}).
          *
-         * A description should be a (localized) string like "Mon-Fri, 9pm-7am" or
+         * <p>A description should be a (localized) string like "Mon-Fri, 9pm-7am" or
          * "When connected to [Car Name]".
          */
         public @NonNull Builder setTriggerDescription(@Nullable String description) {
diff --git a/core/java/android/app/FullscreenRequestHandler.java b/core/java/android/app/FullscreenRequestHandler.java
index 52f461d..c78c66a 100644
--- a/core/java/android/app/FullscreenRequestHandler.java
+++ b/core/java/android/app/FullscreenRequestHandler.java
@@ -16,8 +16,7 @@
 
 package android.app;
 
-import static android.app.Activity.FULLSCREEN_MODE_REQUEST_ENTER;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.Activity.FULLSCREEN_MODE_REQUEST_EXIT;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 
 import android.annotation.IntDef;
@@ -35,18 +34,14 @@
 public class FullscreenRequestHandler {
     @IntDef(prefix = { "RESULT_" }, value = {
             RESULT_APPROVED,
-            RESULT_FAILED_NOT_IN_FREEFORM,
             RESULT_FAILED_NOT_IN_FULLSCREEN_WITH_HISTORY,
-            RESULT_FAILED_NOT_DEFAULT_FREEFORM,
             RESULT_FAILED_NOT_TOP_FOCUSED
     })
     public @interface RequestResult {}
 
     public static final int RESULT_APPROVED = 0;
-    public static final int RESULT_FAILED_NOT_IN_FREEFORM = 1;
-    public static final int RESULT_FAILED_NOT_IN_FULLSCREEN_WITH_HISTORY = 2;
-    public static final int RESULT_FAILED_NOT_DEFAULT_FREEFORM = 3;
-    public static final int RESULT_FAILED_NOT_TOP_FOCUSED = 4;
+    public static final int RESULT_FAILED_NOT_IN_FULLSCREEN_WITH_HISTORY = 1;
+    public static final int RESULT_FAILED_NOT_TOP_FOCUSED = 2;
 
     public static final String REMOTE_CALLBACK_RESULT_KEY = "result";
 
@@ -85,17 +80,10 @@
             OutcomeReceiver<Void, Throwable> callback, int result) {
         Throwable e = null;
         switch (result) {
-            case RESULT_FAILED_NOT_IN_FREEFORM:
-                e = new IllegalStateException("The window is not a freeform window, the request "
-                        + "to get into fullscreen cannot be approved.");
-                break;
             case RESULT_FAILED_NOT_IN_FULLSCREEN_WITH_HISTORY:
                 e = new IllegalStateException("The window is not in fullscreen by calling the "
                         + "requestFullscreenMode API before, such that cannot be restored.");
                 break;
-            case RESULT_FAILED_NOT_DEFAULT_FREEFORM:
-                e = new IllegalStateException("The window is not launched in freeform by default.");
-                break;
             case RESULT_FAILED_NOT_TOP_FOCUSED:
                 e = new IllegalStateException("The window is not the top focused window.");
                 break;
@@ -109,11 +97,7 @@
     }
 
     private static int earlyCheckRequestMatchesWindowingMode(int request, int windowingMode) {
-        if (request == FULLSCREEN_MODE_REQUEST_ENTER) {
-            if (windowingMode != WINDOWING_MODE_FREEFORM) {
-                return RESULT_FAILED_NOT_IN_FREEFORM;
-            }
-        } else {
+        if (request == FULLSCREEN_MODE_REQUEST_EXIT) {
             if (windowingMode != WINDOWING_MODE_FULLSCREEN) {
                 return RESULT_FAILED_NOT_IN_FULLSCREEN_WITH_HISTORY;
             }
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index 75d8c10..5541e7a 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -129,7 +129,7 @@
     void scheduleTrimMemory(int level);
     void dumpMemInfo(in ParcelFileDescriptor fd, in Debug.MemoryInfo mem, boolean checkin,
             boolean dumpInfo, boolean dumpDalvik, boolean dumpSummaryOnly, boolean dumpUnreachable,
-            in String[] args);
+            boolean dumpAllocatorLogs, in String[] args);
     void dumpMemInfoProto(in ParcelFileDescriptor fd, in Debug.MemoryInfo mem,
             boolean dumpInfo, boolean dumpDalvik, boolean dumpSummaryOnly, boolean dumpUnreachable,
             in String[] args);
diff --git a/core/java/android/app/IGameManagerService.aidl b/core/java/android/app/IGameManagerService.aidl
index 9a818e4..bfec9430 100644
--- a/core/java/android/app/IGameManagerService.aidl
+++ b/core/java/android/app/IGameManagerService.aidl
@@ -52,4 +52,6 @@
     void removeGameModeListener(IGameModeListener gameModeListener);
     void addGameStateListener(IGameStateListener gameStateListener);
     void removeGameStateListener(IGameStateListener gameStateListener);
+    @EnforcePermission("MANAGE_GAME_MODE")
+    void toggleGameDefaultFrameRate(boolean isEnabled);
 }
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 1e538c5..4a6349b1 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -9381,7 +9381,7 @@
     @Deprecated
     @SystemApi
     @RequiresPermission(MANAGE_DEVICE_ADMINS)
-    public boolean setActiveProfileOwner(@NonNull ComponentName admin, @Deprecated String ownerName)
+    public boolean setActiveProfileOwner(@NonNull ComponentName admin, String ownerName)
             throws IllegalArgumentException {
         throwIfParentInstance("setActiveProfileOwner");
         if (mService != null) {
@@ -16640,6 +16640,7 @@
                 == DEVICE_OWNER_TYPE_FINANCED;
     }
 
+    // TODO(b/315298076): revert ag/25574027 and update the doc
     /**
      * Called by a device owner or profile owner of an organization-owned managed profile to enable
      * or disable USB data signaling for the device. When disabled, USB data connections
@@ -16649,12 +16650,11 @@
      * {@link #canUsbDataSignalingBeDisabled()} to check whether enabling or disabling USB data
      * signaling is supported on the device.
      *
-     * Starting from {@link Build.VERSION_CODES#VANILLA_ICE_CREAM}, after the USB data signaling
+     * Starting from Android 15, after the USB data signaling
      * policy has been set, {@link PolicyUpdateReceiver#onPolicySetResult(Context, String,
      * Bundle, TargetUser, PolicyUpdateResult)} will notify the admin on whether the policy was
      * successfully set or not. This callback will contain:
      * <ul>
-     * li> The policy identifier {@link DevicePolicyIdentifiers#USB_DATA_SIGNALING_POLICY}
      * <li> The {@link TargetUser} that this policy relates to
      * <li> The {@link PolicyUpdateResult}, which will be
      * {@link PolicyUpdateResult#RESULT_POLICY_SET} if the policy was successfully set or the
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index 6e45147..4cf9fca 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -16,6 +16,8 @@
 
 package android.appwidget;
 
+import static android.appwidget.flags.Flags.remoteAdapterConversion;
+
 import android.annotation.BroadcastBehavior;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -566,11 +568,9 @@
     private void tryAdapterConversion(
             FunctionalUtils.RemoteExceptionIgnoringConsumer<RemoteViews> action,
             RemoteViews original, String failureMsg) {
-        final boolean isConvertingAdapter = RemoteViews.isAdapterConversionEnabled()
+        if (remoteAdapterConversion()
                 && (mHasPostedLegacyLists = mHasPostedLegacyLists
-                        || (original != null && original.hasLegacyLists()));
-
-        if (isConvertingAdapter) {
+                        || (original != null && original.hasLegacyLists()))) {
             final RemoteViews viewsCopy = new RemoteViews(original);
             Runnable updateWidgetWithTask = () -> {
                 try {
@@ -587,13 +587,12 @@
             }
 
             updateWidgetWithTask.run();
-            return;
-        }
-
-        try {
-            action.acceptOrThrow(original);
-        } catch (RemoteException re) {
-            throw re.rethrowFromSystemServer();
+        } else {
+            try {
+                action.acceptOrThrow(original);
+            } catch (RemoteException re) {
+                throw re.rethrowFromSystemServer();
+            }
         }
     }
 
@@ -838,22 +837,20 @@
             return;
         }
 
-        if (!RemoteViews.isAdapterConversionEnabled()) {
+        if (remoteAdapterConversion()) {
+            if (Looper.myLooper() == Looper.getMainLooper()) {
+                mHasPostedLegacyLists = true;
+                createUpdateExecutorIfNull().execute(() -> notifyCollectionWidgetChange(
+                        appWidgetIds, viewId));
+            } else {
+                notifyCollectionWidgetChange(appWidgetIds, viewId);
+            }
+        } else {
             try {
                 mService.notifyAppWidgetViewDataChanged(mPackageName, appWidgetIds, viewId);
             } catch (RemoteException re) {
                 throw re.rethrowFromSystemServer();
             }
-
-            return;
-        }
-
-        if (Looper.myLooper() == Looper.getMainLooper()) {
-            mHasPostedLegacyLists = true;
-            createUpdateExecutorIfNull().execute(() -> notifyCollectionWidgetChange(appWidgetIds,
-                    viewId));
-        } else {
-            notifyCollectionWidgetChange(appWidgetIds, viewId);
         }
     }
 
diff --git a/core/java/android/appwidget/flags.aconfig b/core/java/android/appwidget/flags.aconfig
index 6a735a4..c95b864 100644
--- a/core/java/android/appwidget/flags.aconfig
+++ b/core/java/android/appwidget/flags.aconfig
@@ -6,3 +6,10 @@
   description: "Enable support for generated previews in AppWidgetManager"
   bug: "306546610"
 }
+
+flag {
+  name: "remote_adapter_conversion"
+  namespace: "app_widgets"
+  description: "Enable adapter conversion to RemoteCollectionItemsAdapter"
+  bug: "245950570"
+}
\ No newline at end of file
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index e4a03c5..b11840e 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -20,7 +20,6 @@
 import static android.Manifest.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION;
 import static android.Manifest.permission.REQUEST_COMPANION_PROFILE_COMPUTER;
 import static android.Manifest.permission.REQUEST_COMPANION_PROFILE_WATCH;
-import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
 
 import android.annotation.CallbackExecutor;
 import android.annotation.FlaggedApi;
@@ -37,6 +36,7 @@
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
+import android.app.ActivityOptions;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.bluetooth.BluetoothAdapter;
@@ -218,31 +218,24 @@
      *
      * @hide
      */
-    @FlaggedApi(Flags.FLAG_COMPANION_TRANSPORT_APIS)
-    @TestApi public static final int MESSAGE_REQUEST_PING = 0x63807378; // ?PIN
+    public static final int MESSAGE_REQUEST_PING = 0x63807378; // ?PIN
     /**
      * Message header assigned to the remote authentication handshakes.
      *
      * @hide
      */
-    @FlaggedApi(Flags.FLAG_COMPANION_TRANSPORT_APIS)
-    @SystemApi(client = MODULE_LIBRARIES)
     public static final int MESSAGE_REQUEST_REMOTE_AUTHENTICATION = 0x63827765; // ?RMA
     /**
      * Message header assigned to the telecom context sync metadata.
      *
      * @hide
      */
-    @FlaggedApi(Flags.FLAG_COMPANION_TRANSPORT_APIS)
-    @SystemApi(client = MODULE_LIBRARIES)
     public static final int MESSAGE_REQUEST_CONTEXT_SYNC = 0x63678883; // ?CXS
     /**
      * Message header assigned to the permission restore request.
      *
      * @hide
      */
-    @FlaggedApi(Flags.FLAG_COMPANION_TRANSPORT_APIS)
-    @SystemApi(client = MODULE_LIBRARIES)
     public static final int MESSAGE_REQUEST_PERMISSION_RESTORE = 0x63826983; // ?RES
 
     /**
@@ -709,7 +702,9 @@
             IntentSender intentSender = mService
                     .requestNotificationAccess(component, mContext.getUserId())
                     .getIntentSender();
-            mContext.startIntentSender(intentSender, null, 0, 0, 0);
+            mContext.startIntentSender(intentSender, null, 0, 0, 0,
+                    ActivityOptions.makeBasic().setPendingIntentBackgroundActivityStartMode(
+                            ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED).toBundle());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         } catch (IntentSender.SendIntentException e) {
@@ -902,8 +897,6 @@
      *
      * @hide
      */
-    @FlaggedApi(Flags.FLAG_COMPANION_TRANSPORT_APIS)
-    @SystemApi(client = MODULE_LIBRARIES)
     public interface OnTransportsChangedListener {
         /**
          * Invoked when a transport is attached or detached.
@@ -922,8 +915,6 @@
      *
      * @hide
      */
-    @FlaggedApi(Flags.FLAG_COMPANION_TRANSPORT_APIS)
-    @SystemApi(client = MODULE_LIBRARIES)
     @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS)
     public void addOnTransportsChangedListener(
             @NonNull @CallbackExecutor Executor executor,
@@ -944,8 +935,6 @@
      *
      * @hide
      */
-    @FlaggedApi(Flags.FLAG_COMPANION_TRANSPORT_APIS)
-    @SystemApi(client = MODULE_LIBRARIES)
     @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS)
     public void removeOnTransportsChangedListener(
             @NonNull OnTransportsChangedListener listener) {
@@ -966,8 +955,6 @@
      *
      * @hide
      */
-    @FlaggedApi(Flags.FLAG_COMPANION_TRANSPORT_APIS)
-    @SystemApi(client = MODULE_LIBRARIES)
     @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS)
     public void sendMessage(int messageType, @NonNull byte[] data, @NonNull int[] associationIds) {
         try {
@@ -984,8 +971,6 @@
      *
      * @hide
      */
-    @FlaggedApi(Flags.FLAG_COMPANION_TRANSPORT_APIS)
-    @SystemApi(client = MODULE_LIBRARIES)
     public interface OnMessageReceivedListener {
         /**
          * Called when a message is received.
@@ -998,8 +983,6 @@
      *
      * @hide
      */
-    @FlaggedApi(Flags.FLAG_COMPANION_TRANSPORT_APIS)
-    @SystemApi(client = MODULE_LIBRARIES)
     @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS)
     public void addOnMessageReceivedListener(
             @NonNull @CallbackExecutor Executor executor, int messageType,
@@ -1018,8 +1001,6 @@
      *
      * @hide
      */
-    @FlaggedApi(Flags.FLAG_COMPANION_TRANSPORT_APIS)
-    @SystemApi(client = MODULE_LIBRARIES)
     @RequiresPermission(android.Manifest.permission.USE_COMPANION_TRANSPORTS)
     public void removeOnMessageReceivedListener(int messageType,
             @NonNull OnMessageReceivedListener listener) {
diff --git a/core/java/android/companion/CompanionDeviceService.java b/core/java/android/companion/CompanionDeviceService.java
index c99a457..4d0267c 100644
--- a/core/java/android/companion/CompanionDeviceService.java
+++ b/core/java/android/companion/CompanionDeviceService.java
@@ -40,7 +40,6 @@
 
 /**
  * A service that receives calls from the system with device events.
- * See {@link #onDeviceEvent(AssociationInfo, int)}.
  *
  * <p>
  * Companion applications must create a service that {@code extends}
@@ -311,10 +310,7 @@
      * Called by system whenever a device associated with this app is connected.
      *
      * @param associationInfo A record for the companion device.
-     *
-     * @deprecated please override {@link #onDeviceEvent(AssociationInfo, int)} instead.
      */
-    @Deprecated
     @MainThread
     public void onDeviceAppeared(@NonNull AssociationInfo associationInfo) {
         if (!associationInfo.isSelfManaged()) {
@@ -326,10 +322,7 @@
      * Called by system whenever a device associated with this app is disconnected.
      *
      * @param associationInfo A record for the companion device.
-     *
-     * @deprecated please override {@link #onDeviceEvent(AssociationInfo, int)} instead.
      */
-    @Deprecated
     @MainThread
     public void onDeviceDisappeared(@NonNull AssociationInfo associationInfo) {
         if (!associationInfo.isSelfManaged()) {
diff --git a/core/java/android/companion/virtual/IVirtualDevice.aidl b/core/java/android/companion/virtual/IVirtualDevice.aidl
index 3520c0b..12229b1 100644
--- a/core/java/android/companion/virtual/IVirtualDevice.aidl
+++ b/core/java/android/companion/virtual/IVirtualDevice.aidl
@@ -219,6 +219,10 @@
     @EnforcePermission("CREATE_VIRTUAL_DEVICE")
     void setShowPointerIcon(boolean showPointerIcon);
 
+    /** Sets an IME policy for the given display. */
+    @EnforcePermission("CREATE_VIRTUAL_DEVICE")
+    void setDisplayImePolicy(int displayId, int policy);
+
     /**
      * Registers an intent interceptor that will intercept an intent attempting to launch
      * when matching the provided IntentFilter and calls the callback with the intercepted
diff --git a/core/java/android/companion/virtual/VirtualDeviceInternal.java b/core/java/android/companion/virtual/VirtualDeviceInternal.java
index 003dffb..2abeeee 100644
--- a/core/java/android/companion/virtual/VirtualDeviceInternal.java
+++ b/core/java/android/companion/virtual/VirtualDeviceInternal.java
@@ -53,6 +53,7 @@
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.util.ArrayMap;
+import android.view.WindowManager;
 
 import com.android.internal.annotations.GuardedBy;
 
@@ -361,6 +362,14 @@
         }
     }
 
+    void setDisplayImePolicy(int displayId, @WindowManager.DisplayImePolicy int policy) {
+        try {
+            mVirtualDevice.setDisplayImePolicy(displayId, policy);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
     void addActivityListener(
             @CallbackExecutor @NonNull Executor executor,
             @NonNull VirtualDeviceManager.ActivityListener listener) {
diff --git a/core/java/android/companion/virtual/VirtualDeviceManager.java b/core/java/android/companion/virtual/VirtualDeviceManager.java
index 41c90b9..eef60f1 100644
--- a/core/java/android/companion/virtual/VirtualDeviceManager.java
+++ b/core/java/android/companion/virtual/VirtualDeviceManager.java
@@ -63,6 +63,7 @@
 import android.os.RemoteException;
 import android.util.Log;
 import android.view.Surface;
+import android.view.WindowManager;
 
 import com.android.internal.annotations.GuardedBy;
 
@@ -914,6 +915,24 @@
         }
 
         /**
+         * Specifies the IME behavior on the given display. By default, all displays created by
+         * virtual devices have {@link WindowManager#DISPLAY_IME_POLICY_LOCAL}.
+         *
+         * @param displayId the ID of the display to change the IME policy for. It must be owned by
+         *                  this virtual device.
+         * @param policy the IME policy to use on that display
+         * @throws SecurityException if the display is not owned by this device or is not
+         *                           {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_TRUSTED trusted}
+         */
+        @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
+        @FlaggedApi(Flags.FLAG_VDM_CUSTOM_IME)
+        public void setDisplayImePolicy(int displayId, @WindowManager.DisplayImePolicy int policy) {
+            if (Flags.vdmCustomIme()) {
+                mVirtualDeviceInternal.setDisplayImePolicy(displayId, policy);
+            }
+        }
+
+        /**
          * Adds an activity listener to listen for events such as top activity change or virtual
          * display task stack became empty.
          *
diff --git a/core/java/android/companion/virtual/VirtualDeviceParams.java b/core/java/android/companion/virtual/VirtualDeviceParams.java
index 0d73e44..0253ddd 100644
--- a/core/java/android/companion/virtual/VirtualDeviceParams.java
+++ b/core/java/android/companion/virtual/VirtualDeviceParams.java
@@ -258,6 +258,7 @@
     // Mapping of @PolicyType to @DevicePolicy
     @NonNull private final SparseIntArray mDevicePolicies;
     @Nullable private final ComponentName mHomeComponent;
+    @Nullable private final ComponentName mInputMethodComponent;
     @NonNull private final List<VirtualSensorConfig> mVirtualSensorConfigs;
     @Nullable private final IVirtualSensorCallback mVirtualSensorCallback;
     private final int mAudioPlaybackSessionId;
@@ -273,6 +274,7 @@
             @Nullable String name,
             @NonNull SparseIntArray devicePolicies,
             @Nullable ComponentName homeComponent,
+            @Nullable ComponentName inputMethodComponent,
             @NonNull List<VirtualSensorConfig> virtualSensorConfigs,
             @Nullable IVirtualSensorCallback virtualSensorCallback,
             int audioPlaybackSessionId,
@@ -289,6 +291,7 @@
         mName = name;
         mDevicePolicies = Objects.requireNonNull(devicePolicies);
         mHomeComponent = homeComponent;
+        mInputMethodComponent = inputMethodComponent;
         mVirtualSensorConfigs = Objects.requireNonNull(virtualSensorConfigs);
         mVirtualSensorCallback = virtualSensorCallback;
         mAudioPlaybackSessionId = audioPlaybackSessionId;
@@ -312,6 +315,7 @@
         mAudioPlaybackSessionId = parcel.readInt();
         mAudioRecordingSessionId = parcel.readInt();
         mHomeComponent = parcel.readTypedObject(ComponentName.CREATOR);
+        mInputMethodComponent = parcel.readTypedObject(ComponentName.CREATOR);
     }
 
     /**
@@ -336,6 +340,18 @@
     }
 
     /**
+     * Returns the custom component used as input method on all displays owned by this virtual
+     * device.
+     *
+     * @see Builder#setInputMethodComponent
+     */
+    @FlaggedApi(Flags.FLAG_VDM_CUSTOM_IME)
+    @Nullable
+    public ComponentName getInputMethodComponent() {
+        return mInputMethodComponent;
+    }
+
+    /**
      * Returns the user handles with matching managed accounts on the remote device to which
      * this virtual device is streaming.
      *
@@ -532,6 +548,7 @@
         dest.writeInt(mAudioPlaybackSessionId);
         dest.writeInt(mAudioRecordingSessionId);
         dest.writeTypedObject(mHomeComponent, flags);
+        dest.writeTypedObject(mInputMethodComponent, flags);
     }
 
     @Override
@@ -563,6 +580,8 @@
                 && Objects.equals(mActivityPolicyExemptions, that.mActivityPolicyExemptions)
                 && mDefaultActivityPolicy == that.mDefaultActivityPolicy
                 && Objects.equals(mName, that.mName)
+                && Objects.equals(mHomeComponent, that.mHomeComponent)
+                && Objects.equals(mInputMethodComponent, that.mInputMethodComponent)
                 && mAudioPlaybackSessionId == that.mAudioPlaybackSessionId
                 && mAudioRecordingSessionId == that.mAudioRecordingSessionId;
     }
@@ -572,7 +591,8 @@
         int hashCode = Objects.hash(
                 mLockState, mUsersWithMatchingAccounts, mCrossTaskNavigationExemptions,
                 mDefaultNavigationPolicy, mActivityPolicyExemptions, mDefaultActivityPolicy, mName,
-                mDevicePolicies, mHomeComponent, mAudioPlaybackSessionId, mAudioRecordingSessionId);
+                mDevicePolicies, mHomeComponent, mInputMethodComponent, mAudioPlaybackSessionId,
+                mAudioRecordingSessionId);
         for (int i = 0; i < mDevicePolicies.size(); i++) {
             hashCode = 31 * hashCode + mDevicePolicies.keyAt(i);
             hashCode = 31 * hashCode + mDevicePolicies.valueAt(i);
@@ -593,6 +613,7 @@
                 + " mName=" + mName
                 + " mDevicePolicies=" + mDevicePolicies
                 + " mHomeComponent=" + mHomeComponent
+                + " mInputMethodComponent=" + mInputMethodComponent
                 + " mAudioPlaybackSessionId=" + mAudioPlaybackSessionId
                 + " mAudioRecordingSessionId=" + mAudioRecordingSessionId
                 + ")";
@@ -612,6 +633,8 @@
         pw.println(prefix + "mActivityPolicyExemptions=" + mActivityPolicyExemptions);
         pw.println(prefix + "mDevicePolicies=" + mDevicePolicies);
         pw.println(prefix + "mVirtualSensorConfigs=" + mVirtualSensorConfigs);
+        pw.println(prefix + "mHomeComponent=" + mHomeComponent);
+        pw.println(prefix + "mInputMethodComponent=" + mInputMethodComponent);
         pw.println(prefix + "mAudioPlaybackSessionId=" + mAudioPlaybackSessionId);
         pw.println(prefix + "mAudioRecordingSessionId=" + mAudioRecordingSessionId);
     }
@@ -644,16 +667,17 @@
         private int mDefaultActivityPolicy = ACTIVITY_POLICY_DEFAULT_ALLOWED;
         private boolean mDefaultActivityPolicyConfigured = false;
         @Nullable private String mName;
-        @NonNull private SparseIntArray mDevicePolicies = new SparseIntArray();
+        @NonNull private final SparseIntArray mDevicePolicies = new SparseIntArray();
         private int mAudioPlaybackSessionId = AUDIO_SESSION_ID_GENERATE;
         private int mAudioRecordingSessionId = AUDIO_SESSION_ID_GENERATE;
 
-        @NonNull private List<VirtualSensorConfig> mVirtualSensorConfigs = new ArrayList<>();
+        @NonNull private final List<VirtualSensorConfig> mVirtualSensorConfigs = new ArrayList<>();
         @Nullable private Executor mVirtualSensorCallbackExecutor;
         @Nullable private VirtualSensorCallback mVirtualSensorCallback;
         @Nullable private Executor mVirtualSensorDirectChannelCallbackExecutor;
         @Nullable private VirtualSensorDirectChannelCallback mVirtualSensorDirectChannelCallback;
         @Nullable private ComponentName mHomeComponent;
+        @Nullable private ComponentName mInputMethodComponent;
 
         private static class VirtualSensorCallbackDelegate extends IVirtualSensorCallback.Stub {
             @NonNull
@@ -749,6 +773,28 @@
         }
 
         /**
+         * Specifies a component to be used as input method on all displays owned by this virtual
+         * device.
+         *
+         * @param inputMethodComponent The component name to be used as input method. Must comply to
+         *   all general input method requirements described in the guide to
+         *   <a href="{@docRoot}guide/topics/text/creating-input-method.html">
+         *   Creating an Input Method</a>. If the given component is not available for any user that
+         *   may interact with the virtual device, then there will effectively be no IME on this
+         *   device's displays for that user.
+         *
+         * @see android.inputmethodservice.InputMethodService
+         * @attr ref android.R.styleable#InputMethod_isVirtualDeviceOnly
+         * @attr ref android.R.styleable#InputMethod_showInInputMethodPicker
+         */
+        @FlaggedApi(Flags.FLAG_VDM_CUSTOM_IME)
+        @NonNull
+        public Builder setInputMethodComponent(@Nullable ComponentName inputMethodComponent) {
+            mInputMethodComponent = inputMethodComponent;
+            return this;
+        }
+
+        /**
          * Sets the user handles with matching managed accounts on the remote device to which
          * this virtual device is streaming. The caller is responsible for verifying the presence
          * and legitimacy of a matching managed account on the remote device.
@@ -1136,6 +1182,7 @@
                     mName,
                     mDevicePolicies,
                     mHomeComponent,
+                    mInputMethodComponent,
                     mVirtualSensorConfigs,
                     virtualSensorCallbackDelegate,
                     mAudioPlaybackSessionId,
diff --git a/core/java/android/companion/virtual/flags.aconfig b/core/java/android/companion/virtual/flags.aconfig
index f0477d4..ce2490b 100644
--- a/core/java/android/companion/virtual/flags.aconfig
+++ b/core/java/android/companion/virtual/flags.aconfig
@@ -39,6 +39,13 @@
 }
 
 flag {
+  name: "vdm_custom_ime"
+  namespace: "virtual_devices"
+  description: "Enable custom IME API"
+  bug: "287269288"
+}
+
+flag {
   name: "vdm_custom_home"
   namespace: "virtual_devices"
   description: "Enable custom home API"
diff --git a/core/java/android/content/AttributionSource.java b/core/java/android/content/AttributionSource.java
index b2074a6..a1357c9 100644
--- a/core/java/android/content/AttributionSource.java
+++ b/core/java/android/content/AttributionSource.java
@@ -173,7 +173,7 @@
 
     /** @hide */
     @TestApi
-    @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS)
+    @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
     public AttributionSource(int uid, int pid, @Nullable String packageName,
             @Nullable String attributionTag, @NonNull IBinder token,
             @Nullable String[] renouncedPermissions,
@@ -539,7 +539,7 @@
      * <p>
      * This device ID is used for permissions checking during attribution source validation.
      */
-    @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS)
+    @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
     public int getDeviceId() {
         return mAttributionSourceState.deviceId;
     }
@@ -727,7 +727,7 @@
          *
          * @return the builder
          */
-        @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS)
+        @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
         public @NonNull Builder setDeviceId(int deviceId) {
             checkNotUsed();
             mBuilderFieldsSet |= 0x12;
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index c86ccfd..c7a75ed 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -117,6 +117,7 @@
  * developer guide.</p>
  * </div>
  */
+@android.ravenwood.annotation.RavenwoodKeepPartialClass
 public abstract class ContentProvider implements ContentInterface, ComponentCallbacks2 {
 
     private static final String TAG = "ContentProvider";
@@ -2781,6 +2782,7 @@
     }
 
     /** @hide */
+    @android.ravenwood.annotation.RavenwoodKeep
     private Uri maybeGetUriWithoutUserId(Uri uri) {
         if (mSingleUser) {
             return uri;
@@ -2789,6 +2791,7 @@
     }
 
     /** @hide */
+    @android.ravenwood.annotation.RavenwoodKeep
     public static int getUserIdFromAuthority(String auth, int defaultUserId) {
         if (auth == null) return defaultUserId;
         int end = auth.lastIndexOf('@');
@@ -2803,17 +2806,20 @@
     }
 
     /** @hide */
+    @android.ravenwood.annotation.RavenwoodKeep
     public static int getUserIdFromAuthority(String auth) {
         return getUserIdFromAuthority(auth, UserHandle.USER_CURRENT);
     }
 
     /** @hide */
+    @android.ravenwood.annotation.RavenwoodKeep
     public static int getUserIdFromUri(Uri uri, int defaultUserId) {
         if (uri == null) return defaultUserId;
         return getUserIdFromAuthority(uri.getAuthority(), defaultUserId);
     }
 
     /** @hide */
+    @android.ravenwood.annotation.RavenwoodKeep
     public static int getUserIdFromUri(Uri uri) {
         return getUserIdFromUri(uri, UserHandle.USER_CURRENT);
     }
@@ -2824,6 +2830,7 @@
      * @hide
      */
     @TestApi
+    @android.ravenwood.annotation.RavenwoodKeep
     public @NonNull static UserHandle getUserHandleFromUri(@NonNull Uri uri) {
         return UserHandle.of(getUserIdFromUri(uri, Process.myUserHandle().getIdentifier()));
     }
@@ -2834,6 +2841,7 @@
      * If there is no userId in the authority, it symply returns the argument
      * @hide
      */
+    @android.ravenwood.annotation.RavenwoodKeep
     public static String getAuthorityWithoutUserId(String auth) {
         if (auth == null) return null;
         int end = auth.lastIndexOf('@');
@@ -2841,6 +2849,7 @@
     }
 
     /** @hide */
+    @android.ravenwood.annotation.RavenwoodKeep
     public static Uri getUriWithoutUserId(Uri uri) {
         if (uri == null) return null;
         Uri.Builder builder = uri.buildUpon();
@@ -2849,6 +2858,7 @@
     }
 
     /** @hide */
+    @android.ravenwood.annotation.RavenwoodKeep
     public static boolean uriHasUserId(Uri uri) {
         if (uri == null) return false;
         return !TextUtils.isEmpty(uri.getUserInfo());
@@ -2872,6 +2882,7 @@
      */
     @NonNull
     @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    @android.ravenwood.annotation.RavenwoodKeep
     public static Uri createContentUriForUser(
             @NonNull Uri contentUri, @NonNull UserHandle userHandle) {
         if (!ContentResolver.SCHEME_CONTENT.equals(contentUri.getScheme())) {
@@ -2898,6 +2909,7 @@
 
     /** @hide */
     @UnsupportedAppUsage
+    @android.ravenwood.annotation.RavenwoodKeep
     public static Uri maybeAddUserId(Uri uri, int userId) {
         if (uri == null) return null;
         if (userId != UserHandle.USER_CURRENT
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 23a5d4d..7af0be3 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2888,7 +2888,7 @@
      * <p class="note">This is a protected intent that can only be sent
      * by the system.
      * <p>
-     * Starting in {@link Build.VERSION_CODES#VANILLA_ICE_CREAM Android V}, an extra timestamp
+     * Starting in Android V, an extra timestamp
      * {@link #EXTRA_TIME} is included with this broadcast to indicate the exact time the package
      * was restarted, in {@link SystemClock#elapsedRealtime() elapsed realtime}.
      * </p>
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 16a80e9..3713380 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -19,6 +19,7 @@
 import static android.os.Build.VERSION_CODES.DONUT;
 
 import android.Manifest;
+import android.annotation.FlaggedApi;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -1065,11 +1066,25 @@
      * PackageManager.GET_SHARED_LIBRARY_FILES} flag was used when retrieving
      * the structure.
      *
+     * NOTE: the list also contains the result of {@link #getOptionalSharedLibraryInfos}.
+     *
      * {@hide}
      */
+    @Nullable
     public List<SharedLibraryInfo> sharedLibraryInfos;
 
     /**
+     * List of all shared libraries this application is optionally linked against.
+     * This field is only set if the {@link PackageManager#GET_SHARED_LIBRARY_FILES
+     * PackageManager.GET_SHARED_LIBRARY_FILES} flag was used when retrieving
+     * the structure.
+     *
+     * @hide
+     */
+    @Nullable
+    public List<SharedLibraryInfo> optionalSharedLibraryInfos;
+
+    /**
      * Full path to the default directory assigned to the package for its
      * persistent data.
      */
@@ -1937,6 +1952,7 @@
         seInfoUser = orig.seInfoUser;
         sharedLibraryFiles = orig.sharedLibraryFiles;
         sharedLibraryInfos = orig.sharedLibraryInfos;
+        optionalSharedLibraryInfos = orig.optionalSharedLibraryInfos;
         dataDir = orig.dataDir;
         deviceProtectedDataDir = orig.deviceProtectedDataDir;
         credentialProtectedDataDir = orig.credentialProtectedDataDir;
@@ -2029,6 +2045,7 @@
         dest.writeString8(seInfoUser);
         dest.writeString8Array(sharedLibraryFiles);
         dest.writeTypedList(sharedLibraryInfos);
+        dest.writeTypedList(optionalSharedLibraryInfos);
         dest.writeString8(dataDir);
         dest.writeString8(deviceProtectedDataDir);
         dest.writeString8(credentialProtectedDataDir);
@@ -2129,6 +2146,7 @@
         seInfoUser = source.readString8();
         sharedLibraryFiles = source.createString8Array();
         sharedLibraryInfos = source.createTypedArrayList(SharedLibraryInfo.CREATOR);
+        optionalSharedLibraryInfos = source.createTypedArrayList(SharedLibraryInfo.CREATOR);
         dataDir = source.readString8();
         deviceProtectedDataDir = source.readString8();
         credentialProtectedDataDir = source.readString8();
@@ -2760,6 +2778,8 @@
      *  list will only be set if the {@link PackageManager#GET_SHARED_LIBRARY_FILES
      *  PackageManager.GET_SHARED_LIBRARY_FILES} flag was used when retrieving the structure.
      *
+     *  NOTE: the list also contains the result of {@link #getOptionalSharedLibraryInfos}.
+     *
      * @hide
      */
     @NonNull
@@ -2772,6 +2792,23 @@
     }
 
     /**
+     *  List of all shared libraries this application is optionally linked against. This
+     *  list will only be set if the {@link PackageManager#GET_SHARED_LIBRARY_FILES
+     *  PackageManager.GET_SHARED_LIBRARY_FILES} flag was used when retrieving the structure.
+     *
+     * @hide
+     */
+    @NonNull
+    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    @FlaggedApi(Flags.FLAG_SDK_LIB_INDEPENDENCE)
+    public List<SharedLibraryInfo> getOptionalSharedLibraryInfos() {
+        if (optionalSharedLibraryInfos == null) {
+            return Collections.EMPTY_LIST;
+        }
+        return optionalSharedLibraryInfos;
+    }
+
+    /**
      * Gets the trusted host certificate digests of apps that are allowed to embed activities of
      * this application. The digests are computed using the SHA-256 digest algorithm.
      * @see android.R.attr#knownActivityEmbeddingCerts
diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl
index e9f419e..a97de63 100644
--- a/core/java/android/content/pm/ILauncherApps.aidl
+++ b/core/java/android/content/pm/ILauncherApps.aidl
@@ -64,6 +64,9 @@
     PendingIntent getActivityLaunchIntent(String callingPackage, in ComponentName component,
             in UserHandle user);
     LauncherUserInfo getLauncherUserInfo(in UserHandle user);
+    List<String> getPreInstalledSystemPackages(in UserHandle user);
+    IntentSender getAppMarketActivityIntent(String callingPackage, String packageName,
+            in UserHandle user);
     void showAppDetailsAsUser(in IApplicationThread caller, String callingPackage,
             String callingFeatureId, in ComponentName component, in Rect sourceBounds,
             in Bundle opts, in UserHandle user);
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 0cd4358..1d2b1af 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -799,6 +799,78 @@
         }
     }
 
+
+    /**
+     * Returns an intent sender which can be used to start the App Market activity (Installer
+     * Activity).
+     * This method is primarily used to get an intent sender which starts App Market activity for
+     * another profile, if the caller is not otherwise allowed to start activity in that profile.
+     *
+     * <p>When packageName is set, intent sender to start the App Market Activity which installed
+     * the package in calling user will be returned, but for the profile passed.
+     *
+     * <p>When packageName is not set, intent sender to launch the default App Market Activity for
+     * the profile will be returned. In case there are multiple App Market Activities available for
+     * the profile, IntentPicker will be started, allowing user to choose the preferred activity.
+     *
+     * <p>The method will fall back to the behaviour of not having the packageName set, in case:
+     * <ul>
+     *     <li>No activity for the packageName is found in calling user-space.</li>
+     *     <li>The App Market Activity which installed the package in calling user-space is not
+     *         present.</li>
+     *     <li>The App Market Activity which installed the package in calling user-space is not
+     *         present in the profile passed.</li>
+     * </ul>
+     * </p>
+     *
+     *
+     *
+     * @param packageName the package for which intent sender to launch App Market Activity is
+     *                    required.
+     * @param user the profile for which intent sender to launch App Market Activity is required.
+     * @return {@link IntentSender} object which launches the App Market Activity, null in case
+     *         there is no such activity.
+     * @hide
+     */
+    @Nullable
+    @FlaggedApi(Flags.FLAG_ALLOW_PRIVATE_PROFILE)
+    public IntentSender getAppMarketActivityIntent(@Nullable String packageName,
+            @NonNull UserHandle user) {
+        if (DEBUG) {
+            Log.i(TAG, "getAppMarketActivityIntent for package: " + packageName
+                    + " user: " + user);
+        }
+        try {
+            return mService.getAppMarketActivityIntent(mContext.getPackageName(),
+                    packageName, user);
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Returns the list of the system packages that are installed at user creation.
+     *
+     * <p>An empty list denotes that all system packages are installed for that user at creation.
+     * This behaviour is inherited from the underlining UserManager API.
+     *
+     * @param userHandle the user for which installed system packages are required.
+     * @return {@link List} of {@link String}, representing the package name of the installed
+     *        package. Can be empty but not null.
+     * @hide
+     */
+    @FlaggedApi(Flags.FLAG_ALLOW_PRIVATE_PROFILE)
+    public List<String> getPreInstalledSystemPackages(@NonNull UserHandle userHandle) {
+        if (DEBUG) {
+            Log.i(TAG, "getPreInstalledSystemPackages for user: " + userHandle);
+        }
+        try {
+            return mService.getPreInstalledSystemPackages(userHandle);
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
     /**
      * Returns the activity info for a given intent and user handle, if it resolves. Otherwise it
      * returns null.
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index 5dee65b..4f61613 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -231,7 +231,7 @@
      * or null if there were none.  This is only filled in if the flag
      * {@link PackageManager#GET_PERMISSIONS} was set.  Each value matches
      * the corresponding entry in {@link #requestedPermissions}, and will have
-     * the flags {@link #REQUESTED_PERMISSION_GRANTED} and
+     * the flags {@link #REQUESTED_PERMISSION_GRANTED}, {@link #REQUESTED_PERMISSION_IMPLICIT}, and
      * {@link #REQUESTED_PERMISSION_NEVER_FOR_LOCATION} set as appropriate.
      */
     @Nullable
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 457fd63..0e131b4 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -379,7 +379,8 @@
 
     /**
      * If true, the requestor of the unarchival has specified that the app should be unarchived
-     * for all users.
+     * for all users. Sent as part of the {@link android.content.Intent#ACTION_UNARCHIVE_PACKAGE}
+     * intent.
      */
     @FlaggedApi(Flags.FLAG_ARCHIVING)
     public static final String EXTRA_UNARCHIVE_ALL_USERS =
@@ -396,6 +397,9 @@
      * with an intent for a corresponding follow-up action (e.g. storage clearing dialog) or a
      * failure dialog.
      *
+     * <p> Used as part of {@link #requestUnarchive} to return the status of the unarchival through
+     * the {@link IntentSender}.
+     *
      * @see #requestUnarchive
      */
     @FlaggedApi(Flags.FLAG_ARCHIVING)
@@ -704,7 +708,8 @@
     /**
      * The installer responsible for the unarchival is disabled.
      *
-     * <p> Should only be used by the system.
+     * <p> The system will return this status if appropriate. Installers do not need to verify for
+     * this error.
      */
     @FlaggedApi(Flags.FLAG_ARCHIVING)
     public static final int UNARCHIVAL_ERROR_INSTALLER_DISABLED = 4;
@@ -712,7 +717,8 @@
     /**
      * The installer responsible for the unarchival has been uninstalled
      *
-     * <p> Should only be used by the system.
+     * <p> The system will return this status if appropriate. Installers do not need to verify for
+     * this error.
      */
     @FlaggedApi(Flags.FLAG_ARCHIVING)
     public static final int UNARCHIVAL_ERROR_INSTALLER_UNINSTALLED = 5;
@@ -1238,7 +1244,7 @@
      *                      {@code statusReceiver} if timeout happens before commit.
      * @throws IllegalArgumentException if the {@code statusReceiver} from an immutable
      *             {@link android.app.PendingIntent} when caller has a target SDK of API
-     *             {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM} or above.
+     *             35 or above.
      */
     public void commitSessionAfterInstallConstraintsAreMet(int sessionId,
             @NonNull IntentSender statusReceiver, @NonNull InstallConstraints constraints,
@@ -1948,7 +1954,7 @@
          *             {@link #openWrite(String, long, long)} are still open.
          * @throws IllegalArgumentException if the {@code statusReceiver} from an immutable
          *             {@link android.app.PendingIntent} when caller has a target SDK of API
-         *             version {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM} or above.
+         *             version 35 or above.
          *
          * @see android.app.admin.DevicePolicyManager
          * @see #requestUserPreapproval
@@ -1979,7 +1985,7 @@
          *                       individual status codes on how to handle them.
          * @throws IllegalArgumentException if the {@code statusReceiver} from an immutable
          *             {@link android.app.PendingIntent} when caller has a target SDK of API
-         *             {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM} or above.
+         *             35 or above.
          *
          * @hide
          */
@@ -4375,6 +4381,17 @@
             return pendingUserActionReason;
         }
 
+        /**
+         * Returns true if the session is an unarchival.
+         *
+         * @see PackageInstaller#requestUnarchive
+         */
+        @FlaggedApi(Flags.FLAG_ARCHIVING)
+        public boolean isUnarchival() {
+            return (installFlags & PackageManager.INSTALL_UNARCHIVE) != 0;
+        }
+
+
         @Override
         public int describeContents() {
             return 0;
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 607e904..82a8c11 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -731,7 +731,7 @@
          * @see VirtualDeviceManager.VirtualDevice#getPersistentDeviceId()
          * @see VirtualDeviceManager#PERSISTENT_DEVICE_ID_DEFAULT
          */
-        @FlaggedApi(android.permission.flags.Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS)
+        @FlaggedApi(android.permission.flags.Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
         default void onPermissionsChanged(int uid, @NonNull String persistentDeviceId) {
             Objects.requireNonNull(persistentDeviceId);
             if (Objects.equals(persistentDeviceId,
@@ -919,6 +919,10 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface InstrumentationInfoFlags {}
 
+    //-------------------------------------------------------------------------
+    // Beginning of GET_ and MATCH_ flags
+    //-------------------------------------------------------------------------
+
     /**
      * {@link PackageInfo} flag: return information about
      * activities in the package in {@link PackageInfo#activities}.
@@ -1216,30 +1220,19 @@
      */
     public static final int MATCH_DIRECT_BOOT_AUTO = 0x10000000;
 
-    /**
-     * {@link ResolveInfo} flag: allow matching components across clone profile
-     * <p>
-     * This flag is used only for query and not resolution, the default behaviour would be to
-     * restrict querying across clone profile. This flag would be honored only if caller have
-     * permission {@link Manifest.permission.QUERY_CLONED_APPS}.
-     *
-     *  @hide
-     * <p>
-     */
-    @SystemApi
-    public static final int MATCH_CLONE_PROFILE = 0x20000000;
-
-    /**
-     * @deprecated Use {@link #GET_ATTRIBUTIONS_LONG} to avoid unintended sign extension.
-     */
-    @Deprecated
-    public static final int GET_ATTRIBUTIONS = 0x80000000;
-
     /** @hide */
     @Deprecated
     public static final int MATCH_DEBUG_TRIAGED_MISSING = MATCH_DIRECT_BOOT_AUTO;
 
     /**
+     * Use {@link #MATCH_CLONE_PROFILE_LONG} instead.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int MATCH_CLONE_PROFILE = 0x20000000;
+
+    /**
      * {@link PackageInfo} flag: include system apps that are in the uninstalled state and have
      * been set to be hidden until installed via {@link #setSystemAppState}.
      * @hide
@@ -1257,6 +1250,12 @@
     public static final int MATCH_APEX = 0x40000000;
 
     /**
+     * @deprecated Use {@link #GET_ATTRIBUTIONS_LONG} to avoid unintended sign extension.
+     */
+    @Deprecated
+    public static final int GET_ATTRIBUTIONS = 0x80000000;
+
+    /**
      * {@link PackageInfo} flag: return all attributions declared in the package manifest
      */
     public static final long GET_ATTRIBUTIONS_LONG = 0x80000000L;
@@ -1282,6 +1281,23 @@
     public static final long MATCH_QUARANTINED_COMPONENTS = 1L << 33;
 
     /**
+     * {@link ResolveInfo} flag: allow matching components across clone profile
+     * <p>
+     * This flag is used only for query and not resolution, the default behaviour would be to
+     * restrict querying across clone profile. This flag would be honored only if caller have
+     * permission {@link Manifest.permission.QUERY_CLONED_APPS}.
+     *
+     * @hide
+     */
+    @FlaggedApi(android.content.pm.Flags.FLAG_FIX_DUPLICATED_FLAGS)
+    @SystemApi
+    public static final long MATCH_CLONE_PROFILE_LONG = 1L << 34;
+
+    //-------------------------------------------------------------------------
+    // End of GET_ and MATCH_ flags
+    //-------------------------------------------------------------------------
+
+    /**
      * Flag for {@link #addCrossProfileIntentFilter}: if this flag is set: when
      * resolving an intent that matches the {@code CrossProfileIntentFilter},
      * the current profile will be skipped. Only activities in the target user
@@ -1501,6 +1517,7 @@
             INSTALL_REQUEST_UPDATE_OWNERSHIP,
             INSTALL_IGNORE_DEXOPT_PROFILE,
             INSTALL_UNARCHIVE_DRAFT,
+            INSTALL_UNARCHIVE,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface InstallFlags {}
@@ -1748,13 +1765,22 @@
      * If set, then the session is a draft session created for an upcoming unarchival by its
      * installer.
      *
-     * @see PackageInstaller#requestUnarchive(String)
+     * @see PackageInstaller#requestUnarchive
      *
      * @hide
      */
     public static final int INSTALL_UNARCHIVE_DRAFT = 1 << 29;
 
     /**
+     * If set, then the {@link PackageInstaller.Session} is an unarchival.
+     *
+     * @see PackageInstaller#requestUnarchive
+     *
+     * @hide
+     */
+    public static final int INSTALL_UNARCHIVE = 1 << 30;
+
+    /**
      * Flag parameter for {@link #installPackage} to force a non-staged update of an APEX. This is
      * a development-only feature and should not be used on end user devices.
      *
@@ -4875,7 +4901,7 @@
      * @hide
      */
     @SystemApi
-    @FlaggedApi(android.permission.flags.Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS)
+    @FlaggedApi(android.permission.flags.Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
     public static final String EXTRA_REQUEST_PERMISSIONS_DEVICE_ID =
             "android.content.pm.extra.REQUEST_PERMISSIONS_DEVICE_ID";
 
@@ -6284,6 +6310,11 @@
     /**
      * Check whether a particular package has been granted a particular
      * permission.
+     * <p>
+     * <strong>Note: </strong>This API returns the underlying permission state
+     * as-is and is mostly intended for permission managing system apps. To
+     * perform an access check for a certain app, please use the
+     * {@link Context#checkPermission} APIs instead.
      *
      * @param permName The name of the permission you are checking for.
      * @param packageName The name of the package you are checking against.
diff --git a/core/java/android/content/pm/SharedLibraryInfo.java b/core/java/android/content/pm/SharedLibraryInfo.java
index fdd2aa1..5acebf5 100644
--- a/core/java/android/content/pm/SharedLibraryInfo.java
+++ b/core/java/android/content/pm/SharedLibraryInfo.java
@@ -16,6 +16,7 @@
 
 package android.content.pm;
 
+import android.annotation.FlaggedApi;
 import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
@@ -23,6 +24,7 @@
 import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.Pair;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -99,20 +101,22 @@
     private final boolean mIsNative;
     private final VersionedPackage mDeclaringPackage;
     private final List<VersionedPackage> mDependentPackages;
+
+    private final List<VersionedPackage> mOptionalDependentPackages;
     private List<SharedLibraryInfo> mDependencies;
 
     /**
      * Creates a new instance.
      *
-     * @param codePaths For a non {@link #TYPE_BUILTIN builtin} library, the locations of jars of
-     *                  this shared library. Null for builtin library.
-     * @param name The lib name.
-     * @param version The lib version if not builtin.
-     * @param type The lib type.
-     * @param declaringPackage The package that declares the library.
+     * @param codePaths         For a non {@link #TYPE_BUILTIN builtin} library, the locations of
+     *                          jars of
+     *                          this shared library. Null for builtin library.
+     * @param name              The lib name.
+     * @param version           The lib version if not builtin.
+     * @param type              The lib type.
+     * @param declaringPackage  The package that declares the library.
      * @param dependentPackages The packages that depend on the library.
-     * @param isNative indicate if this shared lib is a native lib or not (i.e. java)
-     *
+     * @param isNative          indicate if this shared lib is a native lib or not (i.e. java)
      * @hide
      */
     public SharedLibraryInfo(String path, String packageName, List<String> codePaths,
@@ -129,6 +133,58 @@
         mDependentPackages = dependentPackages;
         mDependencies = dependencies;
         mIsNative = isNative;
+        mOptionalDependentPackages = null;
+    }
+
+    /**
+     * Creates a new instance.
+     *
+     * @param codePaths For a non {@link #TYPE_BUILTIN builtin} library, the locations of jars of
+     *                  this shared library. Null for builtin library.
+     * @param name The lib name.
+     * @param version The lib version if not builtin.
+     * @param type The lib type.
+     * @param declaringPackage The package that declares the library.
+     * @param isNative indicate if this shared lib is a native lib or not (i.e. java)
+     * @param allDependentPackages All packages that depend on the library (including the optional
+     *                             sdk libraries).
+     *
+     * @hide
+     */
+    public SharedLibraryInfo(String path, String packageName, List<String> codePaths,
+            String name, long version, int type,
+            VersionedPackage declaringPackage,
+            List<SharedLibraryInfo> dependencies, boolean isNative,
+            Pair<List<VersionedPackage>, List<Boolean>> allDependentPackages) {
+        mPath = path;
+        mPackageName = packageName;
+        mCodePaths = codePaths;
+        mName = name;
+        mVersion = version;
+        mType = type;
+        mDeclaringPackage = declaringPackage;
+        mDependencies = dependencies;
+        mIsNative = isNative;
+
+        var allDependents = allDependentPackages.first;
+        var usesLibOptional = allDependentPackages.second;
+        mDependentPackages = allDependents;
+        List<VersionedPackage> optionalDependents = null;
+        if (mType == SharedLibraryInfo.TYPE_SDK_PACKAGE
+                && Flags.sdkLibIndependence() && allDependents != null
+                && usesLibOptional != null
+                && allDependents.size() == usesLibOptional.size()) {
+            for (int k = 0; k < allDependents.size(); k++) {
+                VersionedPackage versionedPackage = allDependents.get(k);
+                if (usesLibOptional.get(k)) {
+                    if (optionalDependents == null) {
+                        optionalDependents = new ArrayList<>();
+                    }
+                    optionalDependents.add(versionedPackage);
+                }
+            }
+        }
+        mOptionalDependentPackages = optionalDependents;
     }
 
     private SharedLibraryInfo(Parcel parcel) {
@@ -142,10 +198,14 @@
         mName = parcel.readString8();
         mVersion = parcel.readLong();
         mType = parcel.readInt();
-        mDeclaringPackage = parcel.readParcelable(null, android.content.pm.VersionedPackage.class);
-        mDependentPackages = parcel.readArrayList(null, android.content.pm.VersionedPackage.class);
+        mDeclaringPackage =
+                parcel.readParcelable(null, android.content.pm.VersionedPackage.class);
+        mDependentPackages =
+                parcel.readArrayList(null, android.content.pm.VersionedPackage.class);
         mDependencies = parcel.createTypedArrayList(SharedLibraryInfo.CREATOR);
         mIsNative = parcel.readBoolean();
+        mOptionalDependentPackages = parcel.readParcelableList(new ArrayList<>(),
+                VersionedPackage.class.getClassLoader(), VersionedPackage.class);
     }
 
     /**
@@ -322,6 +382,8 @@
     /**
      * Gets the packages that depend on the library.
      *
+     * NOTE: the list also contains the result of {@link #getOptionalDependentPackages}.
+     *
      * @return The dependent packages.
      */
     public @NonNull List<VersionedPackage> getDependentPackages() {
@@ -331,6 +393,19 @@
         return mDependentPackages;
     }
 
+    /**
+     * Gets the packages that optionally depend on the library.
+     *
+     * @return The dependent packages.
+     */
+    @FlaggedApi(Flags.FLAG_SDK_LIB_INDEPENDENCE)
+    public @NonNull List<VersionedPackage> getOptionalDependentPackages() {
+        if (mOptionalDependentPackages == null) {
+            return Collections.emptyList();
+        }
+        return mOptionalDependentPackages;
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -360,6 +435,7 @@
         parcel.writeList(mDependentPackages);
         parcel.writeTypedList(mDependencies);
         parcel.writeBoolean(mIsNative);
+        parcel.writeParcelableList(mOptionalDependentPackages, flags);
     }
 
     private static String typeToString(int type) {
diff --git a/core/java/android/content/pm/UserProperties.java b/core/java/android/content/pm/UserProperties.java
index 56e8291..57749d4 100644
--- a/core/java/android/content/pm/UserProperties.java
+++ b/core/java/android/content/pm/UserProperties.java
@@ -68,6 +68,11 @@
             "authAlwaysRequiredToDisableQuietMode";
     private static final String ATTR_DELETE_APP_WITH_PARENT = "deleteAppWithParent";
     private static final String ATTR_ALWAYS_VISIBLE = "alwaysVisible";
+    private static final String ATTR_ALLOW_STOPPING_USER_WITH_DELAYED_LOCKING =
+            "allowStoppingUserWithDelayedLocking";
+
+    private static final String ATTR_CROSS_PROFILE_CONTENT_SHARING_STRATEGY =
+            "crossProfileContentSharingStrategy";
 
     /** Index values of each property (to indicate whether they are present in this object). */
     @IntDef(prefix = "INDEX_", value = {
@@ -86,6 +91,8 @@
             INDEX_SHOW_IN_QUIET_MODE,
             INDEX_SHOW_IN_SHARING_SURFACES,
             INDEX_AUTH_ALWAYS_REQUIRED_TO_DISABLE_QUIET_MODE,
+            INDEX_CROSS_PROFILE_CONTENT_SHARING_STRATEGY,
+            INDEX_ALLOW_STOPPING_USER_WITH_DELAYED_LOCKING,
     })
     @Retention(RetentionPolicy.SOURCE)
     private @interface PropertyIndex {
@@ -105,6 +112,8 @@
     private static final int INDEX_SHOW_IN_QUIET_MODE = 12;
     private static final int INDEX_AUTH_ALWAYS_REQUIRED_TO_DISABLE_QUIET_MODE = 13;
     private static final int INDEX_SHOW_IN_SHARING_SURFACES = 14;
+    private static final int INDEX_CROSS_PROFILE_CONTENT_SHARING_STRATEGY = 15;
+    private static final int INDEX_ALLOW_STOPPING_USER_WITH_DELAYED_LOCKING = 16;
     /** A bit set, mapping each PropertyIndex to whether it is present (1) or absent (0). */
     private long mPropertiesPresent = 0;
 
@@ -365,6 +374,45 @@
      */
     @SuppressLint("UnflaggedApi") // b/306636213
     public static final int SHOW_IN_SHARING_SURFACES_NO = SHOW_IN_LAUNCHER_NO;
+    /**
+     * Possible values for cross profile content sharing strategy for this profile.
+     *
+     * @hide
+     */
+    @IntDef(prefix = {"CROSS_PROFILE_CONTENT_SHARING_STRATEGY_"}, value = {
+            CROSS_PROFILE_CONTENT_SHARING_NO_DELEGATION,
+            CROSS_PROFILE_CONTENT_SHARING_DELEGATE_FROM_PARENT
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface CrossProfileContentSharingStrategy {
+    }
+
+    /**
+     * Signifies that cross-profile content sharing strategy, both to and from this profile, should
+     * not be delegated to any other user/profile.
+     * For ex:
+     * If this property is set for a profile, content sharing applications (such as Android
+     * Sharesheet), should not delegate the decision to share content between that profile and
+     * another profile to whether content sharing is allowed between any other profile/user related
+     * to those profiles. They should instead decide, based upon whether content sharing is
+     * specifically allowed between the two profiles in question.
+     */
+    @SuppressLint("UnflaggedApi") // b/306636213
+    public static final int CROSS_PROFILE_CONTENT_SHARING_NO_DELEGATION = 0;
+
+    /**
+     * Signifies that cross-profile content sharing strategy, both to and from this profile, should
+     * be based upon the strategy used by the parent user of the profile.
+     * For ex:
+     * If this property is set for a profile A, content sharing applications (such as Android
+     * Sharesheet), should share content between profile A and profile B, based upon whether content
+     * sharing is allowed between the parent of profile A and profile B.
+     * If it's also set for profile B, then decision should, in turn be made by considering content
+     * sharing strategy between the parents of both profiles.
+     */
+    @SuppressLint("UnflaggedApi") // b/306636213
+    public static final int CROSS_PROFILE_CONTENT_SHARING_DELEGATE_FROM_PARENT = 1;
+
 
     /**
      * Creates a UserProperties (intended for the SystemServer) that stores a reference to the given
@@ -406,6 +454,7 @@
             setCrossProfileIntentResolutionStrategy(orig.getCrossProfileIntentResolutionStrategy());
             setDeleteAppWithParent(orig.getDeleteAppWithParent());
             setAlwaysVisible(orig.getAlwaysVisible());
+            setAllowStoppingUserWithDelayedLocking(orig.getAllowStoppingUserWithDelayedLocking());
         }
         if (hasManagePermission) {
             // Add items that require MANAGE_USERS or stronger.
@@ -423,6 +472,7 @@
         setCredentialShareableWithParent(orig.isCredentialShareableWithParent());
         setShowInQuietMode(orig.getShowInQuietMode());
         setShowInSharingSurfaces(orig.getShowInSharingSurfaces());
+        setCrossProfileContentSharingStrategy(orig.getCrossProfileContentSharingStrategy());
     }
 
     /**
@@ -680,6 +730,11 @@
         this.mUpdateCrossProfileIntentFiltersOnOTA = val;
         setPresent(INDEX_UPDATE_CROSS_PROFILE_INTENT_FILTERS_ON_OTA);
     }
+    /**
+     Indicate if {@link com.android.server.pm.CrossProfileIntentFilter}s need to be updated during
+     OTA update between user-parent
+     */
+    private boolean mUpdateCrossProfileIntentFiltersOnOTA;
 
     /**
      * Returns whether a profile shares media with its parent user.
@@ -741,12 +796,38 @@
     }
     private boolean mAuthAlwaysRequiredToDisableQuietMode;
 
-    /*
-     Indicate if {@link com.android.server.pm.CrossProfileIntentFilter}s need to be updated during
-     OTA update between user-parent
+    /**
+     * Returns whether a user (usually a profile) is allowed to leave the CE storage unlocked when
+     * stopped.
+     *
+     * <p> Setting this property to true will enable the user's CE storage to remain unlocked when
+     * the user is stopped using
+     * {@link com.android.server.am.ActivityManagerService#stopUserWithDelayedLocking(int,
+     * boolean, IStopUserCallback)}.
+     *
+     * <p> When this property is false, delayed locking may still be applicable at a global
+     * level for all users via the {@code config_multiuserDelayUserDataLocking}. That is, delayed
+     * locking for a user can happen if either the device configuration is set or if this property
+     * is set. When both, the config and the property value is false, the user storage is always
+     * locked when the user is stopped.
+     * @hide
      */
-    private boolean mUpdateCrossProfileIntentFiltersOnOTA;
-
+    public boolean getAllowStoppingUserWithDelayedLocking() {
+        if (isPresent(INDEX_ALLOW_STOPPING_USER_WITH_DELAYED_LOCKING)) {
+            return mAllowStoppingUserWithDelayedLocking;
+        }
+        if (mDefaultProperties != null) {
+            return mDefaultProperties.mAllowStoppingUserWithDelayedLocking;
+        }
+        throw new SecurityException(
+                "You don't have permission to query allowStoppingUserWithDelayedLocking");
+    }
+    /** @hide */
+    public void setAllowStoppingUserWithDelayedLocking(boolean val) {
+        this.mAllowStoppingUserWithDelayedLocking = val;
+        setPresent(INDEX_ALLOW_STOPPING_USER_WITH_DELAYED_LOCKING);
+    }
+    private boolean mAllowStoppingUserWithDelayedLocking;
 
     /**
      * Returns the user's {@link CrossProfileIntentFilterAccessControlLevel}.
@@ -776,8 +857,7 @@
     private @CrossProfileIntentFilterAccessControlLevel int mCrossProfileIntentFilterAccessControl;
 
     /**
-     * Returns the user's {@link CrossProfileIntentResolutionStrategy}. If not explicitly
-     * configured, default value is {@link #CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_DEFAULT}.
+     * Returns the user's {@link CrossProfileIntentResolutionStrategy}.
      * @return user's {@link CrossProfileIntentResolutionStrategy}.
      *
      * @hide
@@ -792,11 +872,8 @@
         throw new SecurityException("You don't have permission to query "
                 + "crossProfileIntentResolutionStrategy");
     }
-    /**
-     * Sets {@link CrossProfileIntentResolutionStrategy} for the user.
-     * @param val resolution strategy for user
-     * @hide
-     */
+
+    /** @hide */
     public void setCrossProfileIntentResolutionStrategy(
             @CrossProfileIntentResolutionStrategy int val) {
         this.mCrossProfileIntentResolutionStrategy = val;
@@ -804,6 +881,39 @@
     }
     private @CrossProfileIntentResolutionStrategy int mCrossProfileIntentResolutionStrategy;
 
+    /**
+     * Returns the user's {@link CrossProfileContentSharingStrategy}.
+     *
+     * Content sharing applications, such as Android Sharesheet allow sharing of content
+     * (an image, for ex.) between profiles, based upon cross-profile access checks between the
+     * originating and destined profile.
+     * In some cases however, we may want another user (such as profile parent) to serve as the
+     * delegated user to be used for such checks.
+     * To effect the same, clients can fetch this property and accordingly replace the
+     * originating/destined profile by another user for cross-profile access checks.
+     *
+     * @return user's {@link CrossProfileContentSharingStrategy}.
+     */
+    @SuppressLint("UnflaggedApi")  // b/306636213
+    public @CrossProfileContentSharingStrategy int getCrossProfileContentSharingStrategy() {
+        if (isPresent(INDEX_CROSS_PROFILE_CONTENT_SHARING_STRATEGY)) {
+            return mCrossProfileContentSharingStrategy;
+        }
+        if (mDefaultProperties != null) {
+            return mDefaultProperties.mCrossProfileContentSharingStrategy;
+        }
+        throw new SecurityException("You don't have permission to query "
+                + "crossProfileContentSharingStrategy");
+    }
+
+    /** @hide */
+    public void setCrossProfileContentSharingStrategy(
+            @CrossProfileContentSharingStrategy int val) {
+        this.mCrossProfileContentSharingStrategy = val;
+        setPresent(INDEX_CROSS_PROFILE_CONTENT_SHARING_STRATEGY);
+    }
+    private @CrossProfileContentSharingStrategy int mCrossProfileContentSharingStrategy;
+
 
     @Override
     public String toString() {
@@ -825,8 +935,11 @@
                 + ", mCredentialShareableWithParent=" + isCredentialShareableWithParent()
                 + ", mAuthAlwaysRequiredToDisableQuietMode="
                 + isAuthAlwaysRequiredToDisableQuietMode()
+                + ", mAllowStoppingUserWithDelayedLocking="
+                + getAllowStoppingUserWithDelayedLocking()
                 + ", mDeleteAppWithParent=" + getDeleteAppWithParent()
                 + ", mAlwaysVisible=" + getAlwaysVisible()
+                + ", mCrossProfileContentSharingStrategy=" + getCrossProfileContentSharingStrategy()
                 + "}";
     }
 
@@ -854,8 +967,12 @@
                 + isCredentialShareableWithParent());
         pw.println(prefix + "    mAuthAlwaysRequiredToDisableQuietMode="
                 + isAuthAlwaysRequiredToDisableQuietMode());
+        pw.println(prefix + "    mAllowStoppingUserWithDelayedLocking="
+                + getAllowStoppingUserWithDelayedLocking());
         pw.println(prefix + "    mDeleteAppWithParent=" + getDeleteAppWithParent());
         pw.println(prefix + "    mAlwaysVisible=" + getAlwaysVisible());
+        pw.println(prefix + "    mCrossProfileContentSharingStrategy="
+                + getCrossProfileContentSharingStrategy());
     }
 
     /**
@@ -928,12 +1045,17 @@
                 case ATTR_AUTH_ALWAYS_REQUIRED_TO_DISABLE_QUIET_MODE:
                     setAuthAlwaysRequiredToDisableQuietMode(parser.getAttributeBoolean(i));
                     break;
+                case ATTR_ALLOW_STOPPING_USER_WITH_DELAYED_LOCKING:
+                    setAllowStoppingUserWithDelayedLocking(parser.getAttributeBoolean(i));
+                    break;
                 case ATTR_DELETE_APP_WITH_PARENT:
                     setDeleteAppWithParent(parser.getAttributeBoolean(i));
                     break;
                 case ATTR_ALWAYS_VISIBLE:
                     setAlwaysVisible(parser.getAttributeBoolean(i));
                     break;
+                case ATTR_CROSS_PROFILE_CONTENT_SHARING_STRATEGY:
+                    setCrossProfileContentSharingStrategy(parser.getAttributeInt(i));
                 default:
                     Slog.w(LOG_TAG, "Skipping unknown property " + attributeName);
             }
@@ -1000,6 +1122,10 @@
             serializer.attributeBoolean(null, ATTR_AUTH_ALWAYS_REQUIRED_TO_DISABLE_QUIET_MODE,
                     mAuthAlwaysRequiredToDisableQuietMode);
         }
+        if (isPresent(INDEX_ALLOW_STOPPING_USER_WITH_DELAYED_LOCKING)) {
+            serializer.attributeBoolean(null, ATTR_ALLOW_STOPPING_USER_WITH_DELAYED_LOCKING,
+                    mAllowStoppingUserWithDelayedLocking);
+        }
         if (isPresent(INDEX_DELETE_APP_WITH_PARENT)) {
             serializer.attributeBoolean(null, ATTR_DELETE_APP_WITH_PARENT,
                     mDeleteAppWithParent);
@@ -1008,6 +1134,10 @@
             serializer.attributeBoolean(null, ATTR_ALWAYS_VISIBLE,
                     mAlwaysVisible);
         }
+        if (isPresent(INDEX_CROSS_PROFILE_CONTENT_SHARING_STRATEGY)) {
+            serializer.attributeInt(null, ATTR_CROSS_PROFILE_CONTENT_SHARING_STRATEGY,
+                    mCrossProfileContentSharingStrategy);
+        }
     }
 
     // For use only with an object that has already had any permission-lacking fields stripped out.
@@ -1027,8 +1157,10 @@
         dest.writeBoolean(mMediaSharedWithParent);
         dest.writeBoolean(mCredentialShareableWithParent);
         dest.writeBoolean(mAuthAlwaysRequiredToDisableQuietMode);
+        dest.writeBoolean(mAllowStoppingUserWithDelayedLocking);
         dest.writeBoolean(mDeleteAppWithParent);
         dest.writeBoolean(mAlwaysVisible);
+        dest.writeInt(mCrossProfileContentSharingStrategy);
     }
 
     /**
@@ -1052,8 +1184,10 @@
         mMediaSharedWithParent = source.readBoolean();
         mCredentialShareableWithParent = source.readBoolean();
         mAuthAlwaysRequiredToDisableQuietMode = source.readBoolean();
+        mAllowStoppingUserWithDelayedLocking = source.readBoolean();
         mDeleteAppWithParent = source.readBoolean();
         mAlwaysVisible = source.readBoolean();
+        mCrossProfileContentSharingStrategy = source.readInt();
     }
 
     @Override
@@ -1098,8 +1232,11 @@
         private boolean mMediaSharedWithParent = false;
         private boolean mCredentialShareableWithParent = false;
         private boolean mAuthAlwaysRequiredToDisableQuietMode = false;
+        private boolean mAllowStoppingUserWithDelayedLocking = false;
         private boolean mDeleteAppWithParent = false;
         private boolean mAlwaysVisible = false;
+        private @CrossProfileContentSharingStrategy int mCrossProfileContentSharingStrategy =
+                CROSS_PROFILE_CONTENT_SHARING_NO_DELEGATION;
 
         /**
          * @hide
@@ -1215,6 +1352,16 @@
             return this;
         }
 
+        /** Sets the value for {@link #mAllowStoppingUserWithDelayedLocking}
+         * @hide
+         */
+        public Builder setAllowStoppingUserWithDelayedLocking(
+                boolean allowStoppingUserWithDelayedLocking) {
+            mAllowStoppingUserWithDelayedLocking =
+                    allowStoppingUserWithDelayedLocking;
+            return this;
+        }
+
         /** Sets the value for {@link #mDeleteAppWithParent}
          * @hide
          */
@@ -1231,6 +1378,19 @@
             return this;
         }
 
+        /** Sets the value for {@link #mCrossProfileContentSharingStrategy}
+         * @hide
+         */
+
+        @TestApi
+        @SuppressLint("UnflaggedApi") // b/306636213
+        @NonNull
+        public Builder setCrossProfileContentSharingStrategy(@CrossProfileContentSharingStrategy
+                int crossProfileContentSharingStrategy) {
+            mCrossProfileContentSharingStrategy = crossProfileContentSharingStrategy;
+            return this;
+        }
+
         /** Builds a UserProperties object with *all* values populated.
          * @hide
          */
@@ -1252,8 +1412,10 @@
                     mMediaSharedWithParent,
                     mCredentialShareableWithParent,
                     mAuthAlwaysRequiredToDisableQuietMode,
+                    mAllowStoppingUserWithDelayedLocking,
                     mDeleteAppWithParent,
-                    mAlwaysVisible);
+                    mAlwaysVisible,
+                    mCrossProfileContentSharingStrategy);
         }
     } // end Builder
 
@@ -1271,8 +1433,10 @@
             boolean mediaSharedWithParent,
             boolean credentialShareableWithParent,
             boolean authAlwaysRequiredToDisableQuietMode,
+            boolean allowStoppingUserWithDelayedLocking,
             boolean deleteAppWithParent,
-            boolean alwaysVisible) {
+            boolean alwaysVisible,
+            @CrossProfileContentSharingStrategy int crossProfileContentSharingStrategy) {
         mDefaultProperties = null;
         setShowInLauncher(showInLauncher);
         setStartWithParent(startWithParent);
@@ -1288,7 +1452,9 @@
         setCredentialShareableWithParent(credentialShareableWithParent);
         setAuthAlwaysRequiredToDisableQuietMode(
                 authAlwaysRequiredToDisableQuietMode);
+        setAllowStoppingUserWithDelayedLocking(allowStoppingUserWithDelayedLocking);
         setDeleteAppWithParent(deleteAppWithParent);
         setAlwaysVisible(alwaysVisible);
+        setCrossProfileContentSharingStrategy(crossProfileContentSharingStrategy);
     }
 }
diff --git a/core/java/android/content/pm/flags.aconfig b/core/java/android/content/pm/flags.aconfig
index 1b90570..b04b7ba 100644
--- a/core/java/android/content/pm/flags.aconfig
+++ b/core/java/android/content/pm/flags.aconfig
@@ -108,3 +108,10 @@
     description: "Feature flag to reduce app crashes caused by split installs with INSTALL_DONT_KILL"
     bug: "291212866"
 }
+
+flag {
+    name: "fix_duplicated_flags"
+    namespace: "package_manager_service"
+    description: "Feature flag to fix duplicated PackageManager flag values"
+    bug: "314815969"
+}
diff --git a/core/java/android/content/pm/multiuser.aconfig b/core/java/android/content/pm/multiuser.aconfig
index 6c6b33b..57025c2 100644
--- a/core/java/android/content/pm/multiuser.aconfig
+++ b/core/java/android/content/pm/multiuser.aconfig
@@ -49,3 +49,10 @@
     description: "Add support to unlock the private space using biometrics"
     bug: "312184187"
 }
+
+flag {
+    name: "support_autolock_for_private_space"
+    namespace: "profile_experiences"
+    description: "Add support to lock private space automatically after a time period"
+    bug: "303201022"
+}
diff --git a/core/java/android/content/res/Element.java b/core/java/android/content/res/Element.java
index 38dbec5..e511469 100644
--- a/core/java/android/content/res/Element.java
+++ b/core/java/android/content/res/Element.java
@@ -308,7 +308,7 @@
                 initializeCounter(TAG_USES_LIBRARY, 1000);
                 initializeCounter(TAG_ACTIVITY_ALIAS, 4000);
                 initializeCounter(TAG_PROVIDER, 8000);
-                initializeCounter(TAG_ACTIVITY, 40000);
+                initializeCounter(TAG_ACTIVITY, 30000);
                 break;
             case TAG_COMPATIBLE_SCREENS:
                 initializeCounter(TAG_SCREEN, 4000);
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index 48adfb9..bb2d2a0 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -35,8 +35,6 @@
 
 import dalvik.system.VMRuntime;
 
-import org.xmlpull.v1.XmlPullParserException;
-
 import java.util.Arrays;
 
 /**
@@ -309,7 +307,11 @@
         if (type == TypedValue.TYPE_STRING) {
             final int cookie = data[index + STYLE_ASSET_COOKIE];
             if (cookie < 0) {
-                return mXml.getPooledString(data[index + STYLE_DATA]).toString();
+                String value = mXml.getPooledString(data[index + STYLE_DATA]).toString();
+                if (value != null && mXml != null && mXml.mValidator != null) {
+                    mXml.mValidator.validateResStrAttr(mXml, index, value);
+                }
+                return value;
             }
         }
         return null;
@@ -1402,11 +1404,7 @@
             value = mAssets.getPooledStringForCookie(cookie, data[index + STYLE_DATA]);
         }
         if (value != null && mXml != null && mXml.mValidator != null) {
-            try {
-                mXml.mValidator.validateResStrAttr(mXml, index / STYLE_NUM_ENTRIES, value);
-            } catch (XmlPullParserException e) {
-                throw new RuntimeException("Failed to validate resource string: " + e.getMessage());
-            }
+            mXml.mValidator.validateResStrAttr(mXml, index / STYLE_NUM_ENTRIES, value);
         }
         return value;
     }
diff --git a/core/java/android/content/res/Validator.java b/core/java/android/content/res/Validator.java
index 3b68452..f72f3c4 100644
--- a/core/java/android/content/res/Validator.java
+++ b/core/java/android/content/res/Validator.java
@@ -81,7 +81,7 @@
      * Validates the resource string of a manifest tag attribute.
      */
     public void validateResStrAttr(@NonNull XmlPullParser parser, @StyleableRes int index,
-            CharSequence stringValue) throws XmlPullParserException {
+            CharSequence stringValue) {
         if (parser.getDepth() > mElements.size()) {
             return;
         }
diff --git a/core/java/android/credentials/flags.aconfig b/core/java/android/credentials/flags.aconfig
index bab84aa..f876eeb 100644
--- a/core/java/android/credentials/flags.aconfig
+++ b/core/java/android/credentials/flags.aconfig
@@ -26,4 +26,11 @@
     name: "new_settings_intents"
     description: "Enables settings intents to redirect to new settings page"
     bug: "307587989"
+}
+
+flag {
+    namespace: "credential_manager"
+    name: "new_settings_ui"
+    description: "Enables new settings UI for VIC"
+    bug: "315209085"
 }
\ No newline at end of file
diff --git a/core/java/android/database/ContentObserver.java b/core/java/android/database/ContentObserver.java
index 39c9400..4322bed 100644
--- a/core/java/android/database/ContentObserver.java
+++ b/core/java/android/database/ContentObserver.java
@@ -31,6 +31,7 @@
 
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.concurrent.Executor;
 
 /**
  * Receives call backs for changes to content.
@@ -54,6 +55,7 @@
     private Transport mTransport; // guarded by mLock
 
     Handler mHandler;
+    private final Executor mExecutor;
 
     /**
      * Creates a content observer.
@@ -62,6 +64,18 @@
      */
     public ContentObserver(Handler handler) {
         mHandler = handler;
+        mExecutor = null;
+    }
+
+    /**
+     * @hide
+     * Creates a content observer with an executor.
+     *
+     * @param executor The executor to run {@link #onChange} on, or null if none.
+     * @param unused a second argument to avoid source incompatibility.
+     */
+    public ContentObserver(@Nullable Executor executor, int unused) {
+        mExecutor = executor;
     }
 
     /**
@@ -306,12 +320,19 @@
     /** @hide */
     public final void dispatchChange(boolean selfChange, @NonNull Collection<Uri> uris,
             @NotifyFlags int flags, @UserIdInt int userId) {
-        if (mHandler == null) {
-            onChange(selfChange, uris, flags, userId);
-        } else {
+        if (mExecutor != null) {
+            mExecutor.execute(() -> {
+                onChange(selfChange, uris, flags, userId);
+            });
+        } else if (mHandler != null) {
+            // Supporting Handler directly rather than wrapping in a HandlerExecutor
+            //  avoids introducing a RejectedExecutionException for legacy code when
+            //  the post fails.
             mHandler.post(() -> {
                 onChange(selfChange, uris, flags, userId);
             });
+        } else {
+            onChange(selfChange, uris, flags, userId);
         }
     }
 
diff --git a/core/java/android/database/ExecutorContentObserver.java b/core/java/android/database/ExecutorContentObserver.java
new file mode 100644
index 0000000..3ea807d
--- /dev/null
+++ b/core/java/android/database/ExecutorContentObserver.java
@@ -0,0 +1,38 @@
+/*
+ * 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.database;
+
+import android.annotation.Nullable;
+
+import java.util.concurrent.Executor;
+
+/**
+ * @hide
+ *
+ * Receives callbacks for changes to content.
+ * Must be implemented by objects which are added to a {@link ContentObservable}.
+ */
+public abstract class ExecutorContentObserver extends ContentObserver {
+    /**
+     * Creates a content observer that uses an executor for change handling.
+     *
+     * @param executor The executor to run {@link #onChange} on, or null if none.
+     */
+    public ExecutorContentObserver(@Nullable Executor executor) {
+        super(executor, 0);
+    }
+}
diff --git a/core/java/android/hardware/biometrics/AuthenticationStateListener.aidl b/core/java/android/hardware/biometrics/AuthenticationStateListener.aidl
new file mode 100644
index 0000000..73ac333
--- /dev/null
+++ b/core/java/android/hardware/biometrics/AuthenticationStateListener.aidl
@@ -0,0 +1,36 @@
+/*
+ * 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.hardware.biometrics;
+
+/**
+ * Low-level callback interface between <Biometric>Manager and <Auth>Service. Allows core system
+ * services (e.g. SystemUI) to register a listener for updates about the current state of biometric
+ * authentication.
+ * @hide
+ */
+oneway interface AuthenticationStateListener {
+    /**
+     * Defines behavior in response to authentication starting
+     * @param requestReason reason from [BiometricRequestConstants.RequestReason] for requesting
+     * authentication starting
+     */
+    void onAuthenticationStarted(int requestReason);
+
+    /**
+     * Defines behavior in response to authentication stopping
+     */
+    void onAuthenticationStopped();
+}
diff --git a/core/java/android/hardware/biometrics/BiometricManager.java b/core/java/android/hardware/biometrics/BiometricManager.java
index f82f79e..d7d1d1a 100644
--- a/core/java/android/hardware/biometrics/BiometricManager.java
+++ b/core/java/android/hardware/biometrics/BiometricManager.java
@@ -552,6 +552,44 @@
     }
 
     /**
+     * Registers listener for changes to biometric authentication state.
+     * Only sends callbacks for events that occur after the callback has been registered.
+     * @param listener Listener for changes to biometric authentication state
+     * @hide
+     */
+    @RequiresPermission(USE_BIOMETRIC_INTERNAL)
+    public void registerAuthenticationStateListener(AuthenticationStateListener listener) {
+        if (mService != null) {
+            try {
+                mService.registerAuthenticationStateListener(listener);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        } else {
+            Slog.w(TAG, "registerAuthenticationStateListener(): Service not connected");
+        }
+    }
+
+    /**
+     * Unregisters listener for changes to biometric authentication state.
+     * @param listener Listener for changes to biometric authentication state
+     * @hide
+     */
+    @RequiresPermission(USE_BIOMETRIC_INTERNAL)
+    public void unregisterAuthenticationStateListener(AuthenticationStateListener listener) {
+        if (mService != null) {
+            try {
+                mService.unregisterAuthenticationStateListener(listener);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        } else {
+            Slog.w(TAG, "unregisterAuthenticationStateListener(): Service not connected");
+        }
+    }
+
+
+    /**
      * Requests all {@link Authenticators.Types#BIOMETRIC_STRONG} sensors to have their
      * authenticatorId invalidated for the specified user. This happens when enrollments have been
      * added on devices with multiple biometric sensors.
diff --git a/core/java/android/hardware/biometrics/BiometricOverlayConstants.java b/core/java/android/hardware/biometrics/BiometricRequestConstants.java
similarity index 69%
rename from core/java/android/hardware/biometrics/BiometricOverlayConstants.java
rename to core/java/android/hardware/biometrics/BiometricRequestConstants.java
index 065ae64a..b036f30 100644
--- a/core/java/android/hardware/biometrics/BiometricOverlayConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricRequestConstants.java
@@ -22,24 +22,27 @@
 import java.lang.annotation.RetentionPolicy;
 
 /**
- * Common constants for biometric overlays.
+ * Common constants for biometric requests.
  * @hide
  */
-public interface BiometricOverlayConstants {
+public class BiometricRequestConstants {
+
+    private BiometricRequestConstants() {}
+
     /** Unknown usage. */
-    int REASON_UNKNOWN = 0;
+    public static final int REASON_UNKNOWN = 0;
     /** User is about to enroll. */
-    int REASON_ENROLL_FIND_SENSOR = 1;
+    public static final int REASON_ENROLL_FIND_SENSOR = 1;
     /** User is enrolling. */
-    int REASON_ENROLL_ENROLLING = 2;
+    public static final int REASON_ENROLL_ENROLLING = 2;
     /** Usage from BiometricPrompt. */
-    int REASON_AUTH_BP = 3;
-    /** Usage from Keyguard. */
-    int REASON_AUTH_KEYGUARD = 4;
+    public static final int REASON_AUTH_BP = 3;
+    /** Usage from Device Entry. */
+    public static final int REASON_AUTH_KEYGUARD = 4;
     /** Non-specific usage (from FingerprintManager). */
-    int REASON_AUTH_OTHER = 5;
+    public static final int REASON_AUTH_OTHER = 5;
     /** Usage from Settings. */
-    int REASON_AUTH_SETTINGS = 6;
+    public static final int REASON_AUTH_SETTINGS = 6;
 
     @IntDef({REASON_UNKNOWN,
             REASON_ENROLL_FIND_SENSOR,
@@ -49,5 +52,5 @@
             REASON_AUTH_OTHER,
             REASON_AUTH_SETTINGS})
     @Retention(RetentionPolicy.SOURCE)
-    @interface ShowReason {}
+    public @interface RequestReason {}
 }
diff --git a/core/java/android/hardware/biometrics/IAuthService.aidl b/core/java/android/hardware/biometrics/IAuthService.aidl
index 5bdbe2b5..8514f98 100644
--- a/core/java/android/hardware/biometrics/IAuthService.aidl
+++ b/core/java/android/hardware/biometrics/IAuthService.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.biometrics;
 
+import android.hardware.biometrics.AuthenticationStateListener;
 import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
 import android.hardware.biometrics.IBiometricServiceReceiver;
 import android.hardware.biometrics.IInvalidationCallback;
@@ -66,6 +67,12 @@
     // Register callback for when keyguard biometric eligibility changes.
     void registerEnabledOnKeyguardCallback(IBiometricEnabledOnKeyguardCallback callback);
 
+    // Register listener for changes to authentication state.
+    void registerAuthenticationStateListener(AuthenticationStateListener listener);
+
+    // Unregister listener for changes to authentication state.
+    void unregisterAuthenticationStateListener(AuthenticationStateListener listener);
+
     // Requests all BIOMETRIC_STRONG sensors to have their authenticatorId invalidated for the
     // specified user. This happens when enrollments have been added on devices with multiple
     // biometric sensors.
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index bb8924c..3ab889d 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -35,6 +35,7 @@
 import com.android.internal.camera.flags.Flags;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.Set;
@@ -206,6 +207,7 @@
     private List<CameraCharacteristics.Key<?>> mKeysNeedingPermission;
     private List<CaptureRequest.Key<?>> mAvailableRequestKeys;
     private List<CaptureRequest.Key<?>> mAvailableSessionKeys;
+    private List<CameraCharacteristics.Key<?>> mAvailableSessionCharacteristicsKeys;
     private List<CaptureRequest.Key<?>> mAvailablePhysicalRequestKeys;
     private List<CaptureResult.Key<?>> mAvailableResultKeys;
     private ArrayList<RecommendedStreamConfigurationMap> mRecommendedConfigurations;
@@ -546,6 +548,27 @@
     }
 
     /**
+     * <p>Get the keys in Camera Characteristics whose values are capture session specific.
+     * The session specific characteristics can be acquired by calling
+     * CameraDevice.getSessionCharacteristics(). </p>
+     *
+     * <p>Note that getAvailableSessionKeys returns the CaptureRequest keys that are difficult to
+     * apply per-frame, whereas this function returns CameraCharacteristics keys that are dependent
+     * on a particular SessionConfiguration.</p>
+     *
+     * @return List of CameraCharacteristic keys containing characterisitics specific to a session
+     * configuration. For Android 15, this list only contains CONTROL_ZOOM_RATIO_RANGE.
+     */
+    @NonNull
+    @FlaggedApi(Flags.FLAG_FEATURE_COMBINATION_QUERY)
+    public List<CameraCharacteristics.Key<?>> getAvailableSessionCharacteristicsKeys() {
+        if (mAvailableSessionCharacteristicsKeys == null) {
+            mAvailableSessionCharacteristicsKeys = Arrays.asList(CONTROL_ZOOM_RATIO_RANGE);
+        }
+        return mAvailableSessionCharacteristicsKeys;
+    }
+
+    /**
      * <p>Returns a subset of {@link #getAvailableCaptureRequestKeys} keys that can
      * be overridden for physical devices backing a logical multi-camera.</p>
      *
@@ -1332,6 +1355,27 @@
             new Key<Boolean>("android.control.autoframingAvailable", boolean.class);
 
     /**
+     * <p>The operating luminance range of low light boost measured in lux (lx).</p>
+     * <p><b>Range of valid values:</b><br></p>
+     * <p>The lower bound indicates the lowest scene luminance value the AE mode
+     * 'ON_LOW_LIGHT_BOOST_BRIGHTNESS_PRIORITY' can operate within. Scenes of lower luminance
+     * than this may receive less brightening, increased noise, or artifacts.</p>
+     * <p>The upper bound indicates the luminance threshold at the point when the mode is enabled.
+     * For example, 'Range[0.3, 30.0]' defines 0.3 lux being the lowest scene luminance the
+     * mode can reliably support. 30.0 lux represents the threshold when this mode is
+     * activated. Scenes measured at less than or equal to 30 lux will activate low light
+     * boost.</p>
+     * <p>If this key is defined, then the AE mode 'ON_LOW_LIGHT_BOOST_BRIGHTNESS_PRIORITY' will
+     * also be present.</p>
+     * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
+     */
+    @PublicKey
+    @NonNull
+    @FlaggedApi(Flags.FLAG_CAMERA_AE_MODE_LOW_LIGHT_BOOST)
+    public static final Key<android.util.Range<Float>> CONTROL_LOW_LIGHT_BOOST_INFO_LUMINANCE_RANGE =
+            new Key<android.util.Range<Float>>("android.control.lowLightBoostInfoLuminanceRange", new TypeReference<android.util.Range<Float>>() {{ }});
+
+    /**
      * <p>List of edge enhancement modes for {@link CaptureRequest#EDGE_MODE android.edge.mode} that are supported by this camera
      * device.</p>
      * <p>Full-capability camera devices must always support OFF; camera devices that support
@@ -3273,7 +3317,7 @@
      * stream configurations are the same as for applications targeting SDK version older than
      * 31.</p>
      * <p>Refer to {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} and
-     * {@link android.hardware.camera2.CameraDevice#legacy-level-guaranteed-configurations }
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice#legacy-level-guaranteed-configurations">the table</a>
      * for additional mandatory stream configurations on a per-capability basis.</p>
      * <p>*1: For JPEG format, the sizes may be restricted by below conditions:</p>
      * <ul>
@@ -3392,11 +3436,12 @@
      * {@link android.hardware.camera2.CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL }
      * and {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES }.
      * This is an app-readable conversion of the mandatory stream combination
-     * {@link android.hardware.camera2.CameraDevice#legacy-level-guaranteed-configurations tables}.</p>
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice#legacy-level-guaranteed-configurations">tables</a>.</p>
      * <p>The array of
      * {@link android.hardware.camera2.params.MandatoryStreamCombination combinations} is
      * generated according to the documented
-     * {@link android.hardware.camera2.CameraDevice#legacy-level-guaranteed-configurations guideline} based on specific device level and capabilities.
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice#legacy-level-guaranteed-configurations">guideline</a>.
+     * based on specific device level and capabilities.
      * Clients can use the array as a quick reference to find an appropriate camera stream
      * combination.
      * As per documentation, the stream combinations with given PREVIEW, RECORD and
@@ -3425,11 +3470,12 @@
     /**
      * <p>An array of mandatory concurrent stream combinations.
      * This is an app-readable conversion of the concurrent mandatory stream combination
-     * {@link android.hardware.camera2.CameraDevice#concurrent-stream-guaranteed-configurations tables}.</p>
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice#concurrent-stream-guaranteed-configurations">tables</a>.</p>
      * <p>The array of
      * {@link android.hardware.camera2.params.MandatoryStreamCombination combinations} is
      * generated according to the documented
-     * {@link android.hardware.camera2.CameraDevice#concurrent-stream-guaranteed-configurations guideline} for each device which has its Id present in the set returned by
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice#concurrent-stream-guaranteed-configurations">guideline</a>
+     * for each device which has its Id present in the set returned by
      * {@link android.hardware.camera2.CameraManager#getConcurrentCameraIds }.
      * Clients can use the array as a quick reference to find an appropriate camera stream
      * combination.
@@ -3534,7 +3580,7 @@
      * <p>If a camera device supports multi-resolution output streams for a particular format, for
      * each of its mandatory stream combinations, the camera device will support using a
      * MultiResolutionImageReader for the MAXIMUM stream of supported formats. Refer to
-     * {@link android.hardware.camera2.CameraDevice#legacy-level-additional-guaranteed-combinations-with-multiresolutionoutputs }
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice#legacy-level-additional-guaranteed-combinations-with-multiresolutionoutputs">the table</a>
      * for additional details.</p>
      * <p>To use multi-resolution input streams, the supported formats can be queried by {@link android.hardware.camera2.params.MultiResolutionStreamConfigurationMap#getInputFormats }.
      * A reprocessable CameraCaptureSession can then be created using an {@link android.hardware.camera2.params.InputConfiguration InputConfiguration} constructed with
@@ -3543,7 +3589,7 @@
      * {@code YUV} output, or multi-resolution {@code PRIVATE} input and multi-resolution
      * {@code PRIVATE} output, {@code JPEG} and {@code YUV} are guaranteed to be supported
      * multi-resolution output stream formats. Refer to
-     * {@link android.hardware.camera2.CameraDevice#legacy-level-additional-guaranteed-combinations-with-multiresolutionoutputs }}
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice#legacy-level-additional-guaranteed-combinations-with-multiresolutionoutputs">the table</a>
      * for details about the additional mandatory stream combinations in this case.</p>
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
      */
@@ -3656,11 +3702,12 @@
      * {@link android.hardware.camera2.CaptureRequest } has {@link CaptureRequest#SENSOR_PIXEL_MODE android.sensor.pixelMode} set
      * to {@link android.hardware.camera2.CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION }.
      * This is an app-readable conversion of the maximum resolution mandatory stream combination
-     * {@link android.hardware.camera2.CameraDevice#additional-guaranteed-combinations-for-ultra-high-resolution-sensors tables}.</p>
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice#additional-guaranteed-combinations-for-ultra-high-resolution-sensors">tables</a>.</p>
      * <p>The array of
      * {@link android.hardware.camera2.params.MandatoryStreamCombination combinations} is
      * generated according to the documented
-     * {@link android.hardware.camera2.CameraDevice#additional-guaranteed-combinations-for-ultra-high-resolution-sensors guideline} for each device which has the
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice#additional-guaranteed-combinations-for-ultra-high-resolution-sensors">guideline</a>
+     * for each device which has the
      * {@link android.hardware.camera2.CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR }
      * capability.
      * Clients can use the array as a quick reference to find an appropriate camera stream
@@ -3683,11 +3730,12 @@
      * 10-bit output capability
      * {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT }
      * This is an app-readable conversion of the 10 bit output mandatory stream combination
-     * {@link android.hardware.camera2.CameraDevice#10-bit-output-additional-guaranteed-configurations tables}.</p>
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice#10-bit-output-additional-guaranteed-configurations">tables</a>.</p>
      * <p>The array of
      * {@link android.hardware.camera2.params.MandatoryStreamCombination combinations} is
      * generated according to the documented
-     * {@link android.hardware.camera2.CameraDevice#10-bit-output-additional-guaranteed-configurations guideline} for each device which has the
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice#10-bit-output-additional-guaranteed-configurations">guideline</a>
+     * for each device which has the
      * {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT }
      * capability.
      * Clients can use the array as a quick reference to find an appropriate camera stream
@@ -3708,11 +3756,12 @@
      * {@code PREVIEW_STABILIZATION} in {@link CameraCharacteristics#CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES android.control.availableVideoStabilizationModes}.
      * This is an app-readable conversion of the preview stabilization mandatory stream
      * combination
-     * {@link android.hardware.camera2.CameraDevice#preview-stabilization-guaranteed-stream-configurations tables}.</p>
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice#preview-stabilization-guaranteed-stream-configurations">tables</a>.</p>
      * <p>The array of
      * {@link android.hardware.camera2.params.MandatoryStreamCombination combinations} is
      * generated according to the documented
-     * {@link android.hardware.camera2.CameraDevice#preview-stabilization-guaranteed-stream-configurations guideline} for each device which supports {@code PREVIEW_STABILIZATION}
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice#preview-stabilization-guaranteed-stream-configurations">guideline</a>
+     * for each device which supports {@code PREVIEW_STABILIZATION}
      * Clients can use the array as a quick reference to find an appropriate camera stream
      * combination.
      * The mandatory stream combination array will be {@code null} in case the device does not
@@ -3785,8 +3834,8 @@
      * <p>The guaranteed stream combinations related to stream use case for a camera device with
      * {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_STREAM_USE_CASE }
      * capability is documented in the camera device
-     * {@link android.hardware.camera2.CameraDevice#stream-use-case-capability-additional-guaranteed-configurations guideline}. The application is strongly recommended to use one of the guaranteed stream
-     * combinations.
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice#stream-use-case-capability-additional-guaranteed-configurations">guideline</a>.
+     * The application is strongly recommended to use one of the guaranteed stream combinations.
      * If the application creates a session with a stream combination not in the guaranteed
      * list, or with mixed DEFAULT and non-DEFAULT use cases within the same session,
      * the camera device may ignore some stream use cases due to hardware constraints
@@ -3822,11 +3871,13 @@
     /**
      * <p>An array of mandatory stream combinations with stream use cases.
      * This is an app-readable conversion of the mandatory stream combination
-     * {@link android.hardware.camera2.CameraDevice#stream-use-case-capability-additional-guaranteed-configurations tables} with each stream's use case being set.</p>
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice#stream-use-case-capability-additional-guaranteed-configurations">tables</a>
+     * with each stream's use case being set.</p>
      * <p>The array of
      * {@link android.hardware.camera2.params.MandatoryStreamCombination combinations} is
      * generated according to the documented
-     * {@link android.hardware.camera2.CameraDevice#stream-use-case-capability-additional-guaranteed-configurations guideline} for a camera device with
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice#stream-use-case-capability-additional-guaranteed-configurations">guildeline</a>
+     * for a camera device with
      * {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_STREAM_USE_CASE }
      * capability.
      * The mandatory stream combination array will be {@code null} in case the device doesn't
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 58cba41..3835c52 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -16,6 +16,7 @@
 
 package android.hardware.camera2;
 
+import android.annotation.FlaggedApi;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -28,6 +29,8 @@
 import android.os.Handler;
 import android.view.Surface;
 
+import com.android.internal.camera.flags.Flags;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.List;
@@ -1412,7 +1415,35 @@
         throw new UnsupportedOperationException("Subclasses must override this method");
     }
 
-    /**
+  /**
+   * <p>Get camera characteristics for a particular session configuration by the camera device.</p>
+   *
+   * <p>The camera characteristics returned here is typically more limited than the characteristics
+   * returned from {@link CameraManager#getCameraCharacteristics}. The keys that have more limited
+   * values are listed in
+   * {@link CameraCharacteristics#getAvailableSessionCharacteristicsKeys}. </p>
+   *
+   * <p>Other than that, the characteristics returned here can be used in the same way as those
+   * returned from {@link CameraManager#getCameraCharacteristics}.</p>
+   *
+   * @param sessionConfig : The session configuration for which characteristics are fetched.
+   * @return CameraCharacteristics specific to a given session configuration.
+   * @throws UnsupportedOperationException if the query operation is not supported by the camera
+   *                                       device
+   * @throws IllegalArgumentException if the session configuration is invalid
+   * @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
+   * @see android.hardware.camera2.CameraCharacteristics#getAvailableSessionCharacteristicsKeys
+   */
+    @NonNull
+    @FlaggedApi(Flags.FLAG_FEATURE_COMBINATION_QUERY)
+    public CameraCharacteristics getSessionCharacteristics(
+            @NonNull SessionConfiguration sessionConfig) throws CameraAccessException {
+        throw new UnsupportedOperationException("Subclasses must override this method");
+    }
+
+  /**
      * A callback objects for receiving updates about the state of a camera device.
      *
      * <p>A callback instance must be provided to the {@link CameraManager#openCamera} method to
diff --git a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
index d4d1ab3..20b0932 100644
--- a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
@@ -40,7 +40,6 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.SystemProperties;
-import android.util.FeatureFlagUtils;
 import android.util.IntArray;
 import android.util.Log;
 import android.util.Pair;
@@ -722,6 +721,7 @@
                 switch(format) {
                     case ImageFormat.YUV_420_888:
                     case ImageFormat.JPEG:
+                    case ImageFormat.JPEG_R:
                         break;
                     default:
                         throw new IllegalArgumentException("Unsupported format: " + format);
@@ -1058,6 +1058,12 @@
      * <p>The set returned is not modifiable, so any attempts to modify it will throw
      * a {@code UnsupportedOperationException}.</p>
      *
+     * <p>Devices launching on Android {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM}
+     * or newer versions are required to support {@link CaptureRequest#CONTROL_AF_MODE},
+     * {@link CaptureRequest#CONTROL_AF_REGIONS}, {@link CaptureRequest#CONTROL_AF_TRIGGER},
+     * {@link CaptureRequest#CONTROL_ZOOM_RATIO} for
+     * {@link CameraExtensionCharacteristics#EXTENSION_NIGHT}.</p>
+     *
      * @param extension the extension type
      *
      * @return non-modifiable set of capture keys supported by camera extension session initialized
@@ -1139,6 +1145,12 @@
      * and the {@link CameraExtensionSession.ExtensionCaptureCallback#onCaptureResultAvailable}
      * callback will not be fired.</p>
      *
+     * <p>Devices launching on Android {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM}
+     * or newer versions are required to support {@link CaptureResult#CONTROL_AF_MODE},
+     * {@link CaptureResult#CONTROL_AF_REGIONS}, {@link CaptureResult#CONTROL_AF_TRIGGER},
+     * {@link CaptureResult#CONTROL_AF_STATE}, {@link CaptureResult#CONTROL_ZOOM_RATIO} for
+     * {@link CameraExtensionCharacteristics#EXTENSION_NIGHT}.</p>
+     *
      * @param extension the extension type
      *
      * @return non-modifiable set of capture result keys supported by camera extension session
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 002c0b2..bcce4b6 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -1844,7 +1844,7 @@
      * Remaps Camera Ids in the CameraService.
      *
      * @hide
-    */
+     */
     @RequiresPermission(android.Manifest.permission.CAMERA_INJECT_EXTERNAL_CAMERA)
     public void remapCameraIds(@NonNull CameraIdRemapping cameraIdRemapping)
             throws CameraAccessException, SecurityException, IllegalArgumentException {
@@ -1852,6 +1852,29 @@
     }
 
     /**
+     * Injects session params into existing clients in the CameraService.
+     *
+     * @param cameraId       The camera id of client to inject session params into.
+     *                       If no such client exists for cameraId, no injection will
+     *                       take place.
+     * @param sessionParams  A {@link CaptureRequest} object containing the
+     *                       the sessionParams to inject into the existing client.
+     *
+     * @throws CameraAccessException    {@link CameraAccessException#CAMERA_DISCONNECTED} will be
+     *                                  thrown if camera service is not available. Further, if
+     *                                  if no such client exists for cameraId,
+     *                                  {@link CameraAccessException#CAMERA_ERROR} will be thrown.
+     * @throws SecurityException        If the caller does not have permission to inject session
+     *                                  params
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.CAMERA_INJECT_EXTERNAL_CAMERA)
+    public void injectSessionParams(@NonNull String cameraId, @NonNull CaptureRequest sessionParams)
+            throws CameraAccessException, SecurityException {
+        CameraManagerGlobal.get().injectSessionParams(cameraId, sessionParams);
+    }
+
+    /**
      * Reports {@link CameraExtensionSessionStats} to the {@link ICameraService} to be logged for
      * currently active session. Validation is done downstream.
      *
@@ -2110,6 +2133,30 @@
             }
         }
 
+        /** Injects session params into an existing client for cameraid. */
+        public void injectSessionParams(@NonNull String cameraId,
+                @NonNull CaptureRequest sessionParams)
+                throws CameraAccessException, SecurityException {
+            synchronized (mLock) {
+                ICameraService cameraService = getCameraService();
+                if (cameraService == null) {
+                    throw new CameraAccessException(
+                            CameraAccessException.CAMERA_DISCONNECTED,
+                            "Camera service is currently unavailable.");
+                }
+
+                try {
+                    cameraService.injectSessionParams(cameraId, sessionParams.getNativeMetadata());
+                } catch (ServiceSpecificException e) {
+                    throwAsPublicException(e);
+                } catch (RemoteException e) {
+                    throw new CameraAccessException(
+                            CameraAccessException.CAMERA_DISCONNECTED,
+                            "Camera service is currently unavailable.");
+                }
+            }
+        }
+
         private String[] extractCameraIdListLocked() {
             String[] cameraIds = null;
             int idCount = 0;
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 003718e..7cf10d8 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -1216,8 +1216,7 @@
      * <ul>
      * <li>Profile {@link android.hardware.camera2.params.DynamicRangeProfiles#HLG10 }</li>
      * <li>All mandatory stream combinations for this specific capability as per
-     *   documentation
-     *   {@link android.hardware.camera2.CameraDevice#10-bit-output-additional-guaranteed-configurations }</li>
+     *   <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice#10-bit-output-additional-guaranteed-configurations">documentation</a></li>
      * <li>In case the device is not able to capture some combination of supported
      *   standard 8-bit and/or 10-bit dynamic range profiles within the same capture request,
      *   then those constraints must be listed in
@@ -1256,8 +1255,8 @@
      * </ul>
      * <p>{@link android.hardware.camera2.CameraCharacteristics#SCALER_AVAILABLE_STREAM_USE_CASES }
      * lists all of the supported stream use cases.</p>
-     * <p>Refer to
-     * {@link android.hardware.camera2.CameraDevice#stream-use-case-capability-additional-guaranteed-configurations }
+     * <p>Refer to the
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice#stream-use-case-capability-additional-guaranteed-configurations">guideline</a>
      * for the mandatory stream combinations involving stream use cases, which can also be
      * queried via {@link android.hardware.camera2.params.MandatoryStreamCombination }.</p>
      * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
@@ -1756,9 +1755,9 @@
     /**
      * <p>This camera device does not have enough capabilities to qualify as a <code>FULL</code> device or
      * better.</p>
-     * <p>Only the stream configurations listed in the <code>LEGACY</code> and <code>LIMITED</code> tables in the
-     * {@link android.hardware.camera2.CameraDevice#limited-level-additional-guaranteed-configurations }
-     * documentation are guaranteed to be supported.</p>
+     * <p>Only the stream configurations listed in the <code>LEGACY</code> and <code>LIMITED</code>
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice#limited-level-additional-guaranteed-configurations">tables</a>
+     * in the documentation are guaranteed to be supported.</p>
      * <p>All <code>LIMITED</code> devices support the <code>BACKWARDS_COMPATIBLE</code> capability, indicating basic
      * support for color image capture. The only exception is that the device may
      * alternatively support only the <code>DEPTH_OUTPUT</code> capability, if it can only output depth
@@ -1784,9 +1783,9 @@
 
     /**
      * <p>This camera device is capable of supporting advanced imaging applications.</p>
-     * <p>The stream configurations listed in the <code>FULL</code>, <code>LEGACY</code> and <code>LIMITED</code> tables in the
-     * {@link android.hardware.camera2.CameraDevice#full-level-additional-guaranteed-configurations }
-     * documentation are guaranteed to be supported.</p>
+     * <p>The stream configurations listed in the <code>FULL</code>, <code>LEGACY</code> and <code>LIMITED</code>
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice#full-level-additional-guaranteed-configurations">tables</a>
+     * in the documentation are guaranteed to be supported.</p>
      * <p>A <code>FULL</code> device will support below capabilities:</p>
      * <ul>
      * <li><code>BURST_CAPTURE</code> capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains
@@ -1814,9 +1813,9 @@
 
     /**
      * <p>This camera device is running in backward compatibility mode.</p>
-     * <p>Only the stream configurations listed in the <code>LEGACY</code> table in the
-     * {@link android.hardware.camera2.CameraDevice#legacy-level-guaranteed-configurations }
-     * documentation are supported.</p>
+     * <p>Only the stream configurations listed in the <code>LEGACY</code>
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice#legacy-level-guaranteed-configurations">table</a>
+     * in the documentation are supported.</p>
      * <p>A <code>LEGACY</code> device does not support per-frame control, manual sensor control, manual
      * post-processing, arbitrary cropping regions, and has relaxed performance constraints.
      * No additional capabilities beyond <code>BACKWARD_COMPATIBLE</code> will ever be listed by a
@@ -1839,9 +1838,9 @@
      * <p>This camera device is capable of YUV reprocessing and RAW data capture, in addition to
      * FULL-level capabilities.</p>
      * <p>The stream configurations listed in the <code>LEVEL_3</code>, <code>RAW</code>, <code>FULL</code>, <code>LEGACY</code> and
-     * <code>LIMITED</code> tables in the
-     * {@link android.hardware.camera2.CameraDevice#level-3-additional-guaranteed-configurations }
-     * documentation are guaranteed to be supported.</p>
+     * <code>LIMITED</code>
+     * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice#level-3-additional-guaranteed-configurations">tables</a>
+     * in the documentation are guaranteed to be supported.</p>
      * <p>The following additional capabilities are guaranteed to be supported:</p>
      * <ul>
      * <li><code>YUV_REPROCESSING</code> capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains
@@ -2333,6 +2332,46 @@
      */
     public static final int CONTROL_AE_MODE_ON_EXTERNAL_FLASH = 5;
 
+    /**
+     * <p>Like 'ON' but applies additional brightness boost in low light scenes.</p>
+     * <p>When the scene lighting conditions are within the range defined by
+     * {@link CameraCharacteristics#CONTROL_LOW_LIGHT_BOOST_INFO_LUMINANCE_RANGE android.control.lowLightBoostInfoLuminanceRange} this mode will apply additional
+     * brightness boost.</p>
+     * <p>This mode will automatically adjust the intensity of low light boost applied
+     * according to the scene lighting conditions. A darker scene will receive more boost
+     * while a brighter scene will receive less boost.</p>
+     * <p>This mode can ignore the set target frame rate to allow more light to be captured
+     * which can result in choppier motion. The frame rate can extend to lower than the
+     * {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES android.control.aeAvailableTargetFpsRanges} but will not go below 10 FPS. This mode
+     * can also increase the sensor sensitivity gain which can result in increased luma
+     * and chroma noise. The sensor sensitivity gain can extend to higher values beyond
+     * {@link CameraCharacteristics#SENSOR_INFO_SENSITIVITY_RANGE android.sensor.info.sensitivityRange}. This mode may also apply additional
+     * processing to recover details in dark and bright areas of the image,and noise
+     * reduction at high sensitivity gain settings to manage the trade-off between light
+     * sensitivity and capture noise.</p>
+     * <p>This mode is restricted to two output surfaces. One output surface type can either
+     * be SurfaceView or TextureView. Another output surface type can either be MediaCodec
+     * or MediaRecorder. This mode cannot be used with a target FPS range higher than 30
+     * FPS.</p>
+     * <p>If the session configuration is not supported, the AE mode reported in the
+     * CaptureResult will be 'ON' instead of 'ON_LOW_LIGHT_BOOST_BRIGHTNESS_PRIORITY'.</p>
+     * <p>The application can observe the CapturerResult field
+     * {@link CaptureResult#CONTROL_LOW_LIGHT_BOOST_STATE android.control.lowLightBoostState} to determine when low light boost is 'ACTIVE' or
+     * 'INACTIVE'.</p>
+     * <p>The low light boost is 'ACTIVE' once the scene lighting condition is less than the
+     * upper bound lux value defined by {@link CameraCharacteristics#CONTROL_LOW_LIGHT_BOOST_INFO_LUMINANCE_RANGE android.control.lowLightBoostInfoLuminanceRange}.
+     * This mode will be 'INACTIVE' once the scene lighting condition is greater than the
+     * upper bound lux value defined by {@link CameraCharacteristics#CONTROL_LOW_LIGHT_BOOST_INFO_LUMINANCE_RANGE android.control.lowLightBoostInfoLuminanceRange}.</p>
+     *
+     * @see CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES
+     * @see CameraCharacteristics#CONTROL_LOW_LIGHT_BOOST_INFO_LUMINANCE_RANGE
+     * @see CaptureResult#CONTROL_LOW_LIGHT_BOOST_STATE
+     * @see CameraCharacteristics#SENSOR_INFO_SENSITIVITY_RANGE
+     * @see CaptureRequest#CONTROL_AE_MODE
+     */
+    @FlaggedApi(Flags.FLAG_CAMERA_AE_MODE_LOW_LIGHT_BOOST)
+    public static final int CONTROL_AE_MODE_ON_LOW_LIGHT_BOOST_BRIGHTNESS_PRIORITY = 6;
+
     //
     // Enumeration values for CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER
     //
@@ -4074,6 +4113,24 @@
     public static final int CONTROL_AUTOFRAMING_STATE_CONVERGED = 2;
 
     //
+    // Enumeration values for CaptureResult#CONTROL_LOW_LIGHT_BOOST_STATE
+    //
+
+    /**
+     * <p>The AE mode 'ON_LOW_LIGHT_BOOST_BRIGHTNESS_PRIORITY' is enabled but not applied.</p>
+     * @see CaptureResult#CONTROL_LOW_LIGHT_BOOST_STATE
+     */
+    @FlaggedApi(Flags.FLAG_CAMERA_AE_MODE_LOW_LIGHT_BOOST)
+    public static final int CONTROL_LOW_LIGHT_BOOST_STATE_INACTIVE = 0;
+
+    /**
+     * <p>The AE mode 'ON_LOW_LIGHT_BOOST_BRIGHTNESS_PRIORITY' is enabled and applied.</p>
+     * @see CaptureResult#CONTROL_LOW_LIGHT_BOOST_STATE
+     */
+    @FlaggedApi(Flags.FLAG_CAMERA_AE_MODE_LOW_LIGHT_BOOST)
+    public static final int CONTROL_LOW_LIGHT_BOOST_STATE_ACTIVE = 1;
+
+    //
     // Enumeration values for CaptureResult#FLASH_STATE
     //
 
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 06397c9..ded96a2 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -1484,7 +1484,7 @@
      * <p>To start a CaptureSession with a target FPS range different from the
      * capture request template's default value, the application
      * is strongly recommended to call
-     * {@link SessionConfiguration#setSessionParameters }
+     * {@link android.hardware.camera2.params.SessionConfiguration#setSessionParameters }
      * with the target fps range before creating the capture session. The aeTargetFpsRange is
      * typically a session parameter. Specifying it at session creation time helps avoid
      * session reconfiguration delays in cases like 60fps or high speed recording.</p>
@@ -2161,7 +2161,7 @@
      * OFF if the recording output is not stabilized, or if there are no output
      * Surface types that can be stabilized.</p>
      * <p>The application is strongly recommended to call
-     * {@link SessionConfiguration#setSessionParameters }
+     * {@link android.hardware.camera2.params.SessionConfiguration#setSessionParameters }
      * with the desired video stabilization mode before creating the capture session.
      * Video stabilization mode is a session parameter on many devices. Specifying
      * it at session creation time helps avoid reconfiguration delay caused by difference
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 35f295a..1d26d69 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -899,7 +899,7 @@
      * <p>To start a CaptureSession with a target FPS range different from the
      * capture request template's default value, the application
      * is strongly recommended to call
-     * {@link SessionConfiguration#setSessionParameters }
+     * {@link android.hardware.camera2.params.SessionConfiguration#setSessionParameters }
      * with the target fps range before creating the capture session. The aeTargetFpsRange is
      * typically a session parameter. Specifying it at session creation time helps avoid
      * session reconfiguration delays in cases like 60fps or high speed recording.</p>
@@ -2382,7 +2382,7 @@
      * OFF if the recording output is not stabilized, or if there are no output
      * Surface types that can be stabilized.</p>
      * <p>The application is strongly recommended to call
-     * {@link SessionConfiguration#setSessionParameters }
+     * {@link android.hardware.camera2.params.SessionConfiguration#setSessionParameters }
      * with the desired video stabilization mode before creating the capture session.
      * Video stabilization mode is a session parameter on many devices. Specifying
      * it at session creation time helps avoid reconfiguration delay caused by difference
@@ -2814,6 +2814,31 @@
             new Key<Integer>("android.control.autoframingState", int.class);
 
     /**
+     * <p>Current state of the low light boost AE mode.</p>
+     * <p>When low light boost is enabled by setting the AE mode to
+     * 'ON_LOW_LIGHT_BOOST_BRIGHTNESS_PRIORITY', it can dynamically apply a low light
+     * boost when the light level threshold is exceeded.</p>
+     * <p>This state indicates when low light boost is 'ACTIVE' and applied. Similarly, it can
+     * indicate when it is not being applied by returning 'INACTIVE'.</p>
+     * <p>This key will be absent from the CaptureResult if AE mode is not set to
+     * 'ON_LOW_LIGHT_BOOST_BRIGHTNESS_PRIORITY.</p>
+     * <p><b>Possible values:</b></p>
+     * <ul>
+     *   <li>{@link #CONTROL_LOW_LIGHT_BOOST_STATE_INACTIVE INACTIVE}</li>
+     *   <li>{@link #CONTROL_LOW_LIGHT_BOOST_STATE_ACTIVE ACTIVE}</li>
+     * </ul>
+     *
+     * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
+     * @see #CONTROL_LOW_LIGHT_BOOST_STATE_INACTIVE
+     * @see #CONTROL_LOW_LIGHT_BOOST_STATE_ACTIVE
+     */
+    @PublicKey
+    @NonNull
+    @FlaggedApi(Flags.FLAG_CAMERA_AE_MODE_LOW_LIGHT_BOOST)
+    public static final Key<Integer> CONTROL_LOW_LIGHT_BOOST_STATE =
+            new Key<Integer>("android.control.lowLightBoostState", int.class);
+
+    /**
      * <p>Operation mode for edge
      * enhancement.</p>
      * <p>Edge enhancement improves sharpness and details in the captured image. OFF means
diff --git a/core/java/android/hardware/camera2/MultiResolutionImageReader.java b/core/java/android/hardware/camera2/MultiResolutionImageReader.java
index 0dbf29d..8a18a0d 100644
--- a/core/java/android/hardware/camera2/MultiResolutionImageReader.java
+++ b/core/java/android/hardware/camera2/MultiResolutionImageReader.java
@@ -17,6 +17,7 @@
 package android.hardware.camera2;
 
 import android.annotation.CallbackExecutor;
+import android.annotation.FlaggedApi;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -33,6 +34,7 @@
 import android.util.Log;
 import android.view.Surface;
 
+import com.android.internal.camera.flags.Flags;
 
 import java.nio.NioUtils;
 import java.util.ArrayList;
@@ -165,6 +167,104 @@
     }
 
     /**
+     * <p>
+     * Create a new multi-resolution reader based on a group of camera stream properties returned
+     * by a camera device, and the desired format, maximum buffer capacity and consumer usage flag.
+     * </p>
+     * <p>
+     * The valid size and formats depend on the camera characteristics.
+     * {@code MultiResolutionImageReader} for an image format is supported by the camera device if
+     * the format is in the supported multi-resolution output stream formats returned by
+     * {@link android.hardware.camera2.params.MultiResolutionStreamConfigurationMap#getOutputFormats}.
+     * If the image format is supported, the {@code MultiResolutionImageReader} object can be
+     * created with the {@code streams} objects returned by
+     * {@link android.hardware.camera2.params.MultiResolutionStreamConfigurationMap#getOutputInfo}.
+     * </p>
+     * <p>
+     * The {@code maxImages} parameter determines the maximum number of
+     * {@link Image} objects that can be acquired from each of the {@code ImageReader}
+     * within the {@code MultiResolutionImageReader}. However, requesting more buffers will
+     * use up more memory, so it is important to use only the minimum number necessary. The
+     * application is strongly recommended to acquire no more than {@code maxImages} images
+     * from all of the internal ImageReader objects combined. By keeping track of the number of
+     * acquired images for the MultiResolutionImageReader, the application doesn't need to do the
+     * bookkeeping for each internal ImageReader returned from {@link
+     * ImageReader.OnImageAvailableListener#onImageAvailable onImageAvailable} callback.
+     * </p>
+     * <p>
+     * Unlike the normal ImageReader, the MultiResolutionImageReader has a more complex
+     * configuration sequence. Instead of passing the same surface to OutputConfiguration and
+     * CaptureRequest, the
+     * {@link android.hardware.camera2.params.OutputConfiguration#createInstancesForMultiResolutionOutput}
+     * call needs to be used to create the OutputConfigurations for session creation, and then
+     * {@link #getSurface} is used to get {@link CaptureRequest.Builder#addTarget the target for
+     * CaptureRequest}.
+     * </p>
+     * @param streams The group of multi-resolution stream info, which is used to create
+     *            a multi-resolution reader containing a number of ImageReader objects. Each
+     *            ImageReader object represents a multi-resolution stream in the group.
+     * @param format The format of the Image that this multi-resolution reader will produce.
+     *            This must be one of the {@link android.graphics.ImageFormat} or
+     *            {@link android.graphics.PixelFormat} constants. Note that not all formats are
+     *            supported, like ImageFormat.NV21. The supported multi-resolution
+     *            reader format can be queried by {@link
+     *            android.hardware.camera2.params.MultiResolutionStreamConfigurationMap#getOutputFormats}.
+     * @param maxImages The maximum number of images the user will want to
+     *            access simultaneously. This should be as small as possible to
+     *            limit memory use. Once maxImages images are obtained by the
+     *            user from any given internal ImageReader, one of them has to be released before
+     *            a new Image will become available for access through the ImageReader's
+     *            {@link ImageReader#acquireLatestImage()} or
+     *            {@link ImageReader#acquireNextImage()}. Must be greater than 0.
+     * @param usage The intended usage of the images produced by the internal ImageReader. See the usages
+     *              on {@link HardwareBuffer} for a list of valid usage bits. See also
+     *              {@link HardwareBuffer#isSupported(int, int, int, int, long)} for checking
+     *              if a combination is supported. If it's not supported this will throw
+     *              an {@link IllegalArgumentException}.
+     * @see Image
+     * @see
+     * android.hardware.camera2.CameraCharacteristics#SCALER_MULTI_RESOLUTION_STREAM_CONFIGURATION_MAP
+     * @see
+     * android.hardware.camera2.params.MultiResolutionStreamConfigurationMap
+     *
+     * @hide
+     */
+    @FlaggedApi(Flags.FLAG_MULTIRESOLUTION_IMAGEREADER_USAGE_CONFIG)
+    public MultiResolutionImageReader(
+            @NonNull Collection<MultiResolutionStreamInfo> streams,
+            @Format             int format,
+            @IntRange(from = 1) int maxImages,
+            @Usage              long usage) {
+        mFormat = format;
+        mMaxImages = maxImages;
+
+        if (streams == null || streams.size() <= 1) {
+            throw new IllegalArgumentException(
+                "The streams info collection must contain at least 2 entries");
+        }
+        if (mMaxImages < 1) {
+            throw new IllegalArgumentException(
+                "Maximum outstanding image count must be at least 1");
+        }
+
+        if (format == ImageFormat.NV21) {
+            throw new IllegalArgumentException(
+                    "NV21 format is not supported");
+        }
+
+        int numImageReaders = streams.size();
+        mReaders = new ImageReader[numImageReaders];
+        mStreamInfo = new MultiResolutionStreamInfo[numImageReaders];
+        int index = 0;
+        for (MultiResolutionStreamInfo streamInfo : streams) {
+            mReaders[index] = ImageReader.newInstance(streamInfo.getWidth(),
+                    streamInfo.getHeight(), format, maxImages, usage);
+            mStreamInfo[index] = streamInfo;
+            index++;
+        }
+    }
+
+    /**
      * Set onImageAvailableListener callback.
      *
      * <p>This function sets the onImageAvailableListener for all the internal
diff --git a/core/java/android/hardware/camera2/extension/RequestProcessor.java b/core/java/android/hardware/camera2/extension/RequestProcessor.java
index 7c099d6..bf5ea12 100644
--- a/core/java/android/hardware/camera2/extension/RequestProcessor.java
+++ b/core/java/android/hardware/camera2/extension/RequestProcessor.java
@@ -250,7 +250,7 @@
          */
         @FlaggedApi(Flags.FLAG_CONCERT_MODE)
         @NonNull
-        List<Pair<CaptureRequest.Key, Object>> getParameters() {
+        public List<Pair<CaptureRequest.Key, Object>> getParameters() {
             return mParameters;
         }
 
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index 3851e36..ccb24e7 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -786,6 +786,18 @@
         }
     }
 
+    @Override
+    public CameraCharacteristics getSessionCharacteristics(
+            @NonNull SessionConfiguration sessionConfig) throws CameraAccessException,
+            UnsupportedOperationException, IllegalArgumentException {
+        synchronized (mInterfaceLock) {
+            checkIfCameraClosedOrInError();
+            CameraMetadataNative info = mRemoteDevice.getSessionCharacteristics(sessionConfig);
+
+            return new CameraCharacteristics(info);
+        }
+    }
+
     /**
      * For use by backwards-compatibility code only.
      */
diff --git a/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java b/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java
index b6b1968..2129260 100644
--- a/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java
+++ b/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java
@@ -16,19 +16,12 @@
 
 package android.hardware.camera2.impl;
 
-import static android.hardware.camera2.CameraAccessException.CAMERA_DISABLED;
-import static android.hardware.camera2.CameraAccessException.CAMERA_DISCONNECTED;
-import static android.hardware.camera2.CameraAccessException.CAMERA_IN_USE;
-import static android.hardware.camera2.CameraAccessException.CAMERA_ERROR;
-import static android.hardware.camera2.CameraAccessException.MAX_CAMERAS_IN_USE;
-import static android.hardware.camera2.CameraAccessException.CAMERA_DEPRECATED_HAL;
-
 import android.hardware.ICameraService;
-import android.hardware.camera2.CameraManager;
 import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraManager;
 import android.hardware.camera2.CaptureRequest;
-import android.hardware.camera2.ICameraDeviceUser;
 import android.hardware.camera2.ICameraDeviceCallbacks;
+import android.hardware.camera2.ICameraDeviceUser;
 import android.hardware.camera2.ICameraOfflineSession;
 import android.hardware.camera2.impl.CameraMetadataNative;
 import android.hardware.camera2.params.OutputConfiguration;
@@ -205,6 +198,28 @@
         }
     }
 
+    /**
+     * Fetches the CameraCharacteristics for a given session configuration.
+     */
+    public CameraMetadataNative getSessionCharacteristics(SessionConfiguration sessionConfig)
+            throws CameraAccessException {
+        try {
+            return mRemoteDevice.getSessionCharacteristics(sessionConfig);
+        } catch (ServiceSpecificException e) {
+            if (e.errorCode == ICameraService.ERROR_INVALID_OPERATION) {
+                throw new UnsupportedOperationException("Session characteristics query not "
+                    + "supported");
+            } else if (e.errorCode == ICameraService.ERROR_ILLEGAL_ARGUMENT) {
+                throw new IllegalArgumentException("Invalid session configuration");
+            }
+
+            throw e;
+        } catch (Throwable t) {
+            CameraManager.throwAsPublicException(t);
+            throw new UnsupportedOperationException("Unexpected exception", t);
+        }
+    }
+
     public long flush() throws CameraAccessException {
         try {
             return mRemoteDevice.flush();
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 8e49c4c..134a510 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -403,14 +403,13 @@
 
     /**
      * Virtual display flag: Indicates that the display should support system decorations. Virtual
-     * displays without this flag shouldn't show home, IME or any other system decorations.
+     * displays without this flag shouldn't show home, navigation bar or wallpaper.
      * <p>This flag doesn't work without {@link #VIRTUAL_DISPLAY_FLAG_TRUSTED}</p>
      *
      * @see #createVirtualDisplay
      * @see #VIRTUAL_DISPLAY_FLAG_TRUSTED
      * @hide
      */
-    // TODO (b/114338689): Remove the flag and use IWindowManager#setShouldShowSystemDecors
     @TestApi
     public static final int VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS = 1 << 9;
 
diff --git a/core/java/android/hardware/display/VirtualDisplayConfig.java b/core/java/android/hardware/display/VirtualDisplayConfig.java
index 7388b5b..9e09759 100644
--- a/core/java/android/hardware/display/VirtualDisplayConfig.java
+++ b/core/java/android/hardware/display/VirtualDisplayConfig.java
@@ -447,7 +447,8 @@
          * Sets whether this display supports showing home activities and wallpaper.
          *
          * <p>If set to {@code true}, then the home activity relevant to this display will be
-         * automatically launched upon the display creation.</p>
+         * automatically launched upon the display creation. If unset or set to {@code false}, the
+         * display will not host any activities upon creation.</p>
          *
          * <p>Note: setting to {@code true} requires the display to be trusted. If the display is
          * not trusted, this property is ignored.</p>
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 935157a..fe7de83 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -983,6 +983,7 @@
         }
     }
 
+    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
     /**
      * @hide
      */
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index 0100660..f594c00 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -15,6 +15,7 @@
  */
 package android.hardware.fingerprint;
 
+import android.hardware.biometrics.AuthenticationStateListener;
 import android.hardware.biometrics.IBiometricSensorReceiver;
 import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
 import android.hardware.biometrics.IBiometricStateListener;
@@ -203,6 +204,14 @@
     @EnforcePermission("USE_BIOMETRIC_INTERNAL")
     void setSidefpsController(in ISidefpsController controller);
 
+    // Registers AuthenticationStateListener.
+    @EnforcePermission("USE_BIOMETRIC_INTERNAL")
+    void registerAuthenticationStateListener(AuthenticationStateListener listener);
+
+    // Unregisters AuthenticationStateListener.
+    @EnforcePermission("USE_BIOMETRIC_INTERNAL")
+    void unregisterAuthenticationStateListener(AuthenticationStateListener listener);
+
     // Registers BiometricStateListener.
     @EnforcePermission("USE_BIOMETRIC_INTERNAL")
     void registerBiometricStateListener(IBiometricStateListener listener);
diff --git a/core/java/android/hardware/input/InputSettings.java b/core/java/android/hardware/input/InputSettings.java
index 33960c0..cb9c333 100644
--- a/core/java/android/hardware/input/InputSettings.java
+++ b/core/java/android/hardware/input/InputSettings.java
@@ -16,6 +16,9 @@
 
 package android.hardware.input;
 
+import static com.android.hardware.input.Flags.keyboardA11yBounceKeysFlag;
+import static com.android.hardware.input.Flags.keyboardA11yStickyKeysFlag;
+
 import android.Manifest;
 import android.annotation.FloatRange;
 import android.annotation.NonNull;
@@ -58,6 +61,11 @@
      */
     public static final float DEFAULT_MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH = .8f;
 
+    /**
+     * The maximum allowed Accessibility bounce keys threshold.
+     * @hide
+     */
+    public static final int MAX_ACCESSIBILITY_BOUNCE_KEYS_THRESHOLD_MILLIS = 5000;
 
     private InputSettings() {
     }
@@ -328,4 +336,115 @@
                        .getBoolean(com.android.internal.R.bool.config_enableStylusPointerIcon)
                || InputProperties.force_enable_stylus_pointer_icon().orElse(false);
     }
+
+    /**
+     * Whether Accessibility bounce keys is enabled.
+     *
+     * <p>
+     * ‘Bounce keys’ is an accessibility feature to aid users who have physical disabilities,
+     * that allows the user to configure the device to ignore rapid, repeated keypresses of the
+     * same key.
+     * </p>
+     *
+     * @hide
+     */
+    public static boolean isAccessibilityBounceKeysEnabled(@NonNull Context context) {
+        return getAccessibilityBounceKeysThreshold(context) != 0;
+    }
+
+    /**
+     * Get Accessibility bounce keys threshold duration in milliseconds.
+     *
+     * <p>
+     * ‘Bounce keys’ is an accessibility feature to aid users who have physical disabilities,
+     * that allows the user to configure the device to ignore rapid, repeated keypresses of the
+     * same key.
+     * </p>
+     *
+     * @hide
+     */
+    public static int getAccessibilityBounceKeysThreshold(@NonNull Context context) {
+        if (!keyboardA11yBounceKeysFlag()) {
+            return 0;
+        }
+        return Settings.System.getIntForUser(context.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_BOUNCE_KEYS, 0, UserHandle.USER_CURRENT);
+    }
+
+    /**
+     * Set Accessibility bounce keys threshold duration in milliseconds.
+     * @param thresholdTimeMillis time duration for which a key down will be ignored after a
+     *                            previous key up for the same key on the same device between 0 and
+     *                            {@link MAX_ACCESSIBILITY_BOUNCE_KEYS_THRESHOLD_MILLIS}
+     *
+     * <p>
+     * ‘Bounce keys’ is an accessibility feature to aid users who have physical disabilities,
+     * that allows the user to configure the device to ignore rapid, repeated keypresses of the
+     * same key.
+     * </p>
+     *
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
+    public static void setAccessibilityBounceKeysThreshold(@NonNull Context context,
+            int thresholdTimeMillis) {
+        if (!keyboardA11yBounceKeysFlag()) {
+            return;
+        }
+        if (thresholdTimeMillis < 0
+                || thresholdTimeMillis > MAX_ACCESSIBILITY_BOUNCE_KEYS_THRESHOLD_MILLIS) {
+            throw new IllegalArgumentException(
+                    "Provided Bounce keys threshold should be in range [0, "
+                            + MAX_ACCESSIBILITY_BOUNCE_KEYS_THRESHOLD_MILLIS + "]");
+        }
+        Settings.System.putIntForUser(context.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_BOUNCE_KEYS, thresholdTimeMillis,
+                UserHandle.USER_CURRENT);
+    }
+
+    /**
+     * Whether Accessibility sticky keys is enabled.
+     *
+     * <p>
+     * 'Sticky keys' is an accessibility feature that assists users who have physical
+     * disabilities or help users reduce repetitive strain injury. It serializes keystrokes
+     * instead of pressing multiple keys at a time, allowing the user to press and release a
+     * modifier key, such as Shift, Ctrl, Alt, or any other modifier key, and have it remain
+     * active until any other key is pressed.
+     * </p>
+     *
+     * @hide
+     */
+    public static boolean isAccessibilityStickyKeysEnabled(@NonNull Context context) {
+        if (!keyboardA11yStickyKeysFlag()) {
+            return false;
+        }
+        return Settings.System.getIntForUser(context.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_STICKY_KEYS, 0, UserHandle.USER_CURRENT) != 0;
+    }
+
+    /**
+     * Set Accessibility sticky keys feature enabled/disabled.
+     *
+     *  <p>
+     * 'Sticky keys' is an accessibility feature that assists users who have physical
+     * disabilities or help users reduce repetitive strain injury. It serializes keystrokes
+     * instead of pressing multiple keys at a time, allowing the user to press and release a
+     * modifier key, such as Shift, Ctrl, Alt, or any other modifier key, and have it remain
+     * active until any other key is pressed.
+     * </p>
+     *
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
+    public static void setAccessibilityStickyKeysEnabled(@NonNull Context context,
+            boolean enabled) {
+        if (!keyboardA11yStickyKeysFlag()) {
+            return;
+        }
+        Settings.System.putIntForUser(context.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_STICKY_KEYS, enabled ? 1 : 0,
+                UserHandle.USER_CURRENT);
+    }
+
 }
diff --git a/core/java/android/hardware/input/input_framework.aconfig b/core/java/android/hardware/input/input_framework.aconfig
index 97c45a7..362fe78 100644
--- a/core/java/android/hardware/input/input_framework.aconfig
+++ b/core/java/android/hardware/input/input_framework.aconfig
@@ -17,6 +17,12 @@
     bug: "294546335"
 }
 
+flag {
+    namespace: "input_native"
+    name: "keyboard_a11y_bounce_keys_flag"
+    description: "Controls if the bounce keys accessibility feature for physical keyboard is available to the user"
+    bug: "294546335"
+}
 
 flag {
     namespace: "input_native"
diff --git a/core/java/android/net/flags.aconfig b/core/java/android/net/flags.aconfig
new file mode 100644
index 0000000..0ad1804
--- /dev/null
+++ b/core/java/android/net/flags.aconfig
@@ -0,0 +1,50 @@
+package: "com.android.net.flags"
+
+flag {
+  name: "track_multiple_network_activities"
+  namespace: "android_core_networking"
+  description: "NetworkActivityTracker tracks multiple networks including non default networks"
+  bug: "267870186"
+}
+
+flag {
+  name: "forbidden_capability"
+  namespace: "android_core_networking"
+  description: "This flag controls the forbidden capability API"
+  bug: "302997505"
+}
+
+flag {
+  name: "set_data_saver_via_cm"
+  namespace: "android_core_networking"
+  description: "Set data saver through ConnectivityManager API"
+  bug: "297836825"
+}
+
+flag {
+  name: "support_is_uid_networking_blocked"
+  namespace: "android_core_networking"
+  description: "This flag controls whether isUidNetworkingBlocked is supported"
+  bug: "297836825"
+}
+
+flag {
+  name: "basic_background_restrictions_enabled"
+  namespace: "android_core_networking"
+  description: "Block network access for apps in a low importance background state"
+  bug: "304347838"
+}
+
+flag {
+  name: "register_nsd_offload_engine"
+  namespace: "android_core_networking"
+  description: "The flag controls the access for registerOffloadEngine API in NsdManager"
+  bug: "294777050"
+}
+
+flag {
+  name: "ipsec_transform_state"
+  namespace: "android_core_networking_ipsec"
+  description: "The flag controls the access for getIpSecTransformState and IpSecTransformState"
+  bug: "308011229"
+}
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 98a980f..f407fb7 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -284,6 +284,20 @@
     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.
@@ -948,7 +962,7 @@
      */
     @SystemApi
     @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
-    public int getAdapterState() {
+    public @AdapterState int getAdapterState() {
         try {
             return sService.getState();
         } catch (RemoteException e) {
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index e331c95..bd087f9 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -130,7 +130,7 @@
     /**
      * State of the service for CATEGORY_OTHER selection
      */
-    private boolean mOtherServiceEnabled;
+    private boolean mCategoryOtherServiceEnabled;
 
     /**
      * @hide
@@ -183,7 +183,7 @@
         this.mBannerResourceId = bannerResource;
         this.mUid = uid;
         this.mSettingsActivityName = settingsActivityName;
-        this.mOtherServiceEnabled = isEnabled;
+        this.mCategoryOtherServiceEnabled = isEnabled;
 
     }
 
@@ -374,7 +374,7 @@
         // Set uid
         mUid = si.applicationInfo.uid;
 
-        mOtherServiceEnabled = false;    // support other category
+        mCategoryOtherServiceEnabled = false;    // support other category
 
     }
 
@@ -746,7 +746,7 @@
         dest.writeInt(mUid);
         dest.writeString(mSettingsActivityName);
 
-        dest.writeInt(mOtherServiceEnabled ? 1 : 0);
+        dest.writeInt(mCategoryOtherServiceEnabled ? 1 : 0);
     };
 
     @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
@@ -809,7 +809,7 @@
         pw.println("    Static AID groups:");
         for (AidGroup group : mStaticAidGroups.values()) {
             pw.println("        Category: " + group.getCategory()
-                    + "(enabled: " + mOtherServiceEnabled + ")");
+                    + "(enabled: " + mCategoryOtherServiceEnabled + ")");
             for (String aid : group.getAids()) {
                 pw.println("            AID: " + aid);
             }
@@ -817,7 +817,7 @@
         pw.println("    Dynamic AID groups:");
         for (AidGroup group : mDynamicAidGroups.values()) {
             pw.println("        Category: " + group.getCategory()
-                    + "(enabled: " + mOtherServiceEnabled + ")");
+                    + "(enabled: " + mCategoryOtherServiceEnabled + ")");
             for (String aid : group.getAids()) {
                 pw.println("            AID: " + aid);
             }
@@ -834,8 +834,8 @@
      * @param enabled true to indicate if user has enabled this service
      */
     @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
-    public void setOtherServiceEnabled(boolean enabled) {
-        mOtherServiceEnabled = enabled;
+    public void setCategoryOtherServiceEnabled(boolean enabled) {
+        mCategoryOtherServiceEnabled = enabled;
     }
 
 
@@ -845,8 +845,8 @@
      * @return true to indicate if user has enabled this service
      */
     @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
-    public boolean isOtherServiceEnabled() {
-        return mOtherServiceEnabled;
+    public boolean isCategoryOtherServiceEnabled() {
+        return mCategoryOtherServiceEnabled;
     }
 
     /**
diff --git a/core/java/android/os/BatteryConsumer.java b/core/java/android/os/BatteryConsumer.java
index 6a83cee..05a1abea 100644
--- a/core/java/android/os/BatteryConsumer.java
+++ b/core/java/android/os/BatteryConsumer.java
@@ -33,6 +33,7 @@
  *
  * @hide
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public abstract class BatteryConsumer {
 
     private static final String TAG = "BatteryConsumer";
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 16ffaef..1a0ce70 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -56,6 +56,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.BatteryStatsHistoryIterator;
 import com.android.internal.os.CpuScalingPolicies;
+import com.android.internal.os.MonotonicClock;
 import com.android.internal.os.PowerStats;
 
 import com.google.android.collect.Lists;
@@ -1657,6 +1658,7 @@
      */
     public abstract CpuScalingPolicies getCpuScalingPolicies();
 
+    @android.ravenwood.annotation.RavenwoodKeepWholeClass
     public final static class HistoryTag {
         public static final int HISTORY_TAG_POOL_OVERFLOW = -1;
 
@@ -1713,6 +1715,7 @@
      * Optional detailed information that can go into a history step.  This is typically
      * generated each time the battery level changes.
      */
+    @android.ravenwood.annotation.RavenwoodKeepWholeClass
     public final static class HistoryStepDetails {
         // Time (in 1/100 second) spent in user space and the kernel since the last step.
         public int userTime;
@@ -1797,6 +1800,7 @@
     /**
      * An extension to the history item describing a proc state change for a UID.
      */
+    @android.ravenwood.annotation.RavenwoodKeepWholeClass
     public static final class ProcessStateChange {
         public int uid;
         public @BatteryConsumer.ProcessState int processState;
@@ -1850,6 +1854,7 @@
     /**
      * Battery history record.
      */
+    @android.ravenwood.annotation.RavenwoodKeepWholeClass
     public static final class HistoryItem {
         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
         public HistoryItem next;
@@ -7480,7 +7485,8 @@
         long baseTime = -1;
         boolean printed = false;
         HistoryEventTracker tracker = null;
-        try (BatteryStatsHistoryIterator iterator = iterateBatteryStatsHistory(0, 0)) {
+        try (BatteryStatsHistoryIterator iterator =
+                     iterateBatteryStatsHistory(0, MonotonicClock.UNDEFINED)) {
             HistoryItem rec;
             while ((rec = iterator.next()) != null) {
                 try {
@@ -8405,7 +8411,8 @@
         long baseTime = -1;
         boolean printed = false;
         HistoryEventTracker tracker = null;
-        try (BatteryStatsHistoryIterator iterator = iterateBatteryStatsHistory(0, 0)) {
+        try (BatteryStatsHistoryIterator iterator =
+                     iterateBatteryStatsHistory(0, MonotonicClock.UNDEFINED)) {
             HistoryItem rec;
             while ((rec = iterator.next()) != null) {
                 lastTime = rec.time;
diff --git a/core/java/android/os/BatteryUsageStats.java b/core/java/android/os/BatteryUsageStats.java
index eabe13b..511f464 100644
--- a/core/java/android/os/BatteryUsageStats.java
+++ b/core/java/android/os/BatteryUsageStats.java
@@ -26,6 +26,7 @@
 
 import com.android.internal.os.BatteryStatsHistory;
 import com.android.internal.os.BatteryStatsHistoryIterator;
+import com.android.internal.os.MonotonicClock;
 import com.android.modules.utils.TypedXmlPullParser;
 import com.android.modules.utils.TypedXmlSerializer;
 
@@ -323,7 +324,7 @@
             throw new IllegalStateException(
                     "Battery history was not requested in the BatteryUsageStatsQuery");
         }
-        return new BatteryStatsHistoryIterator(mBatteryStatsHistory, 0, 0);
+        return new BatteryStatsHistoryIterator(mBatteryStatsHistory, 0, MonotonicClock.UNDEFINED);
     }
 
     @Override
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 0ccc485..05b7827f 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -339,7 +339,11 @@
      * If the current thread is not currently executing an incoming transaction,
      * then its own PID is returned.
      *
-     * Warning: oneway transactions do not receive PID.
+     * Warning: oneway transactions do not receive PID. Even if you expect
+     * a transaction to be synchronous, a misbehaving client could send it
+     * as a asynchronous call and result in a 0 PID here. Additionally, if
+     * there is a race and the calling process dies, the PID may still be
+     * 0 for a synchronous call.
      */
     @CriticalNative
     @android.ravenwood.annotation.RavenwoodReplace
@@ -396,6 +400,7 @@
      * This is Test API which will be used to override output of isDirectlyHandlingTransactionNative
      * @hide
      */
+    @android.ravenwood.annotation.RavenwoodKeep
     public static void setIsDirectlyHandlingTransactionOverride(boolean isInTransaction) {
         sIsHandlingBinderTransaction = isInTransaction;
     }
@@ -1068,6 +1073,7 @@
      *
      * @hide
      */
+    @android.ravenwood.annotation.RavenwoodKeep
     public @Nullable String getTransactionName(int transactionCode) {
         return null;
     }
@@ -1076,6 +1082,7 @@
      * @hide
      */
     @VisibleForTesting
+    @android.ravenwood.annotation.RavenwoodKeep
     public final @Nullable String getTransactionTraceName(int transactionCode) {
         final boolean isInterfaceUserDefined = getMaxTransactionId() == 0;
         if (mTransactionTraceNames == null) {
@@ -1113,6 +1120,7 @@
         return transactionTraceName;
     }
 
+    @android.ravenwood.annotation.RavenwoodKeep
     private @NonNull String getSimpleDescriptor() {
         String descriptor = mDescriptor;
         if (descriptor == null) {
@@ -1132,6 +1140,7 @@
      * @return The highest user-defined transaction id of all transactions.
      * @hide
      */
+    @android.ravenwood.annotation.RavenwoodKeep
     public int getMaxTransactionId() {
         return 0;
     }
diff --git a/core/java/android/os/Broadcaster.java b/core/java/android/os/Broadcaster.java
index 88760b0..17cf692 100644
--- a/core/java/android/os/Broadcaster.java
+++ b/core/java/android/os/Broadcaster.java
@@ -19,6 +19,7 @@
 import android.compat.annotation.UnsupportedAppUsage;
 
 /** @hide */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class Broadcaster
 {
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
diff --git a/core/java/android/os/BundleMerger.java b/core/java/android/os/BundleMerger.java
index 857aaf5..dc243a5 100644
--- a/core/java/android/os/BundleMerger.java
+++ b/core/java/android/os/BundleMerger.java
@@ -48,6 +48,7 @@
  *
  * @hide
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class BundleMerger implements Parcelable {
     private static final String TAG = "BundleMerger";
 
diff --git a/core/java/android/os/ConditionVariable.java b/core/java/android/os/ConditionVariable.java
index a13eaa6..b5ed53b 100644
--- a/core/java/android/os/ConditionVariable.java
+++ b/core/java/android/os/ConditionVariable.java
@@ -29,6 +29,7 @@
  * This class uses itself as the object to wait on, so if you wait()
  * or notify() on a ConditionVariable, the results are undefined.
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class ConditionVariable
 {
     private volatile boolean mCondition;
diff --git a/core/java/android/os/CoolingDevice.java b/core/java/android/os/CoolingDevice.java
index 4ddcd9d..06ec720 100644
--- a/core/java/android/os/CoolingDevice.java
+++ b/core/java/android/os/CoolingDevice.java
@@ -55,7 +55,11 @@
             TYPE_TPU,
             TYPE_POWER_AMPLIFIER,
             TYPE_DISPLAY,
-            TYPE_SPEAKER
+            TYPE_SPEAKER,
+            TYPE_WIFI,
+            TYPE_CAMERA,
+            TYPE_FLASHLIGHT,
+            TYPE_USB_PORT
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface Type {}
@@ -84,6 +88,14 @@
     public static final int TYPE_DISPLAY = CoolingType.DISPLAY;
     /** Speaker cooling device */
     public static final int TYPE_SPEAKER = CoolingType.SPEAKER;
+    /** WiFi cooling device */
+    public static final int TYPE_WIFI = CoolingType.WIFI;
+    /** Camera cooling device */
+    public static final int TYPE_CAMERA = CoolingType.CAMERA;
+    /** Flashlight cooling device */
+    public static final int TYPE_FLASHLIGHT = CoolingType.FLASHLIGHT;
+    /** USB PORT cooling device */
+    public static final int TYPE_USB_PORT = CoolingType.USB_PORT;
 
     /**
      * Verify a valid cooling device type.
@@ -91,7 +103,7 @@
      * @return true if a cooling device type is valid otherwise false.
      */
     public static boolean isValidType(@Type int type) {
-        return type >= TYPE_FAN && type <= TYPE_SPEAKER;
+        return type >= TYPE_FAN && type <= TYPE_USB_PORT;
     }
 
     public CoolingDevice(long value, @Type int type, @NonNull String name) {
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index c527cb5..04d6f61 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -2702,4 +2702,13 @@
      * @hide
      */
     public static native boolean isVmapStack();
+
+    /**
+     * Log internal statistics about the allocator.
+     * @return true if the statistics were logged properly, false if not.
+     *
+     * @hide
+     */
+    public static native boolean logAllocatorStats();
+
 }
diff --git a/core/java/android/os/DropBoxManager.java b/core/java/android/os/DropBoxManager.java
index a1d2dcc..2aab2b4 100644
--- a/core/java/android/os/DropBoxManager.java
+++ b/core/java/android/os/DropBoxManager.java
@@ -81,10 +81,8 @@
 
     /**
      * Broadcast Action: This is broadcast when a new entry is added in the dropbox.
-     * For apps targeting {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM} and later, you
-     * must hold the {@link android.Manifest.permission#READ_DROPBOX_DATA} permission
-     * in order to receive this broadcast. For apps targeting Android versions lower
-     * than {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM}, you must hold
+     * For apps targeting 35 and later, For apps targeting Android versions lower
+     * than 35, you must hold
      * {@link android.Manifest.permission#READ_LOGS}.
      * This broadcast can be rate limited for low priority entries
      *
@@ -385,11 +383,8 @@
     /**
      * Gets the next entry from the drop box <em>after</em> the specified time.
      * You must always call {@link Entry#close()} on the return value!
-     * {@link android.Manifest.permission#READ_DROPBOX_DATA} permission is
-     * required for apps targeting {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM}
-     * and later. {@link android.Manifest.permission#READ_LOGS} permission is
-     * required for apps targeting Android versions lower than
-     * {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM}.
+     * {@link android.Manifest.permission#READ_LOGS} permission is
+     * required for apps targeting Android versions lower than 35.
      *
      * @param tag of entry to look for, null for all tags
      * @param msec time of the last entry seen
diff --git a/core/java/android/os/IVibratorManagerService.aidl b/core/java/android/os/IVibratorManagerService.aidl
index 0f27569..65e498e 100644
--- a/core/java/android/os/IVibratorManagerService.aidl
+++ b/core/java/android/os/IVibratorManagerService.aidl
@@ -41,5 +41,5 @@
     // There is no order guarantee with respect to the two-way APIs above like
     // vibrate/isVibrating/cancel.
     oneway void performHapticFeedback(int uid, int deviceId, String opPkg, int constant,
-            boolean always, String reason, IBinder token);
+            boolean always, String reason);
 }
diff --git a/core/java/android/os/PackageTagsList.java b/core/java/android/os/PackageTagsList.java
index df99074..cbc4272 100644
--- a/core/java/android/os/PackageTagsList.java
+++ b/core/java/android/os/PackageTagsList.java
@@ -41,6 +41,7 @@
  */
 @TestApi
 @Immutable
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public final class PackageTagsList implements Parcelable {
 
     // an empty set value matches any attribution tag (ie, wildcard)
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index f2930fe..8e860c3 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -465,9 +465,7 @@
     private static native byte[] nativeMarshall(long nativePtr);
     private static native void nativeUnmarshall(
             long nativePtr, byte[] data, int offset, int length);
-    @RavenwoodThrow
     private static native int nativeCompareData(long thisNativePtr, long otherNativePtr);
-    @RavenwoodThrow
     private static native boolean nativeCompareDataInRange(
             long ptrA, int offsetA, long ptrB, int offsetB, int length);
     private static native void nativeAppendFrom(
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 7e07e1f..fc8523e 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -1599,7 +1599,7 @@
      * fully removed, otherwise system resources may leak.
      * @hide
      */
-    public static final native int sendSignalToProcessGroup(int uid, int pid, int signal);
+    public static final native boolean sendSignalToProcessGroup(int uid, int pid, int signal);
 
     /**
       * Freeze the cgroup for the given UID.
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 94f90cc..e32a8f3 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -2435,11 +2435,12 @@
 
     /** @hide */
     public static void onVmPolicyViolation(Violation violation, boolean forceDeath) {
-        final boolean penaltyDropbox = (sVmPolicy.mask & PENALTY_DROPBOX) != 0;
-        final boolean penaltyDeath = ((sVmPolicy.mask & PENALTY_DEATH) != 0) || forceDeath;
-        final boolean penaltyLog = (sVmPolicy.mask & PENALTY_LOG) != 0;
+        final VmPolicy vmPolicy = getVmPolicy();
+        final boolean penaltyDropbox = (vmPolicy.mask & PENALTY_DROPBOX) != 0;
+        final boolean penaltyDeath = ((vmPolicy.mask & PENALTY_DEATH) != 0) || forceDeath;
+        final boolean penaltyLog = (vmPolicy.mask & PENALTY_LOG) != 0;
 
-        final int penaltyMask = (sVmPolicy.mask & PENALTY_ALL);
+        final int penaltyMask = (vmPolicy.mask & PENALTY_ALL);
         final ViolationInfo info = new ViolationInfo(violation, penaltyMask);
 
         // Erase stuff not relevant for process-wide violations
@@ -2492,10 +2493,10 @@
 
         // If penaltyDeath, we can't guarantee this callback finishes before the process dies for
         // all executors. penaltyDeath supersedes penaltyCallback.
-        if (sVmPolicy.mListener != null && sVmPolicy.mCallbackExecutor != null) {
-            final OnVmViolationListener listener = sVmPolicy.mListener;
+        if (vmPolicy.mListener != null && vmPolicy.mCallbackExecutor != null) {
+            final OnVmViolationListener listener = vmPolicy.mListener;
             try {
-                sVmPolicy.mCallbackExecutor.execute(
+                vmPolicy.mCallbackExecutor.execute(
                         () -> {
                             // Lift violated policy to prevent infinite recursion.
                             VmPolicy oldPolicy = allowVmViolations();
diff --git a/core/java/android/os/SystemVibratorManager.java b/core/java/android/os/SystemVibratorManager.java
index bc85412e..8e83923 100644
--- a/core/java/android/os/SystemVibratorManager.java
+++ b/core/java/android/os/SystemVibratorManager.java
@@ -39,6 +39,7 @@
 
     private final IVibratorManagerService mService;
     private final Context mContext;
+    private final int mUid;
     private final Binder mToken = new Binder();
     private final Object mLock = new Object();
     @GuardedBy("mLock")
@@ -56,6 +57,7 @@
     public SystemVibratorManager(Context context) {
         super(context);
         mContext = context;
+        mUid = Process.myUid();
         mService = IVibratorManagerService.Stub.asInterface(
                 ServiceManager.getService(Context.VIBRATOR_MANAGER_SERVICE));
     }
@@ -152,8 +154,7 @@
         }
         try {
             mService.performHapticFeedback(
-                    Process.myUid(), mContext.getDeviceId(), mPackageName, constant, always, reason,
-                    mToken);
+                    mUid, mContext.getDeviceId(), mPackageName, constant, always, reason);
         } catch (RemoteException e) {
             Log.w(TAG, "Failed to perform haptic feedback.", e);
         }
diff --git a/core/java/android/os/Temperature.java b/core/java/android/os/Temperature.java
index a138431..2e12278 100644
--- a/core/java/android/os/Temperature.java
+++ b/core/java/android/os/Temperature.java
@@ -79,7 +79,13 @@
             TYPE_TPU,
             TYPE_DISPLAY,
             TYPE_MODEM,
-            TYPE_SOC
+            TYPE_SOC,
+            TYPE_WIFI,
+            TYPE_CAMERA,
+            TYPE_FLASHLIGHT,
+            TYPE_SPEAKER,
+            TYPE_AMBIENT,
+            TYPE_POGO
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface Type {}
@@ -101,6 +107,12 @@
     public static final int TYPE_DISPLAY = TemperatureType.DISPLAY;
     public static final int TYPE_MODEM = TemperatureType.MODEM;
     public static final int TYPE_SOC = TemperatureType.SOC;
+    public static final int TYPE_WIFI = TemperatureType.WIFI;
+    public static final int TYPE_CAMERA = TemperatureType.CAMERA;
+    public static final int TYPE_FLASHLIGHT = TemperatureType.FLASHLIGHT;
+    public static final int TYPE_SPEAKER = TemperatureType.SPEAKER;
+    public static final int TYPE_AMBIENT = TemperatureType.AMBIENT;
+    public static final int TYPE_POGO = TemperatureType.POGO;
 
     /**
      * Verify a valid Temperature type.
@@ -108,7 +120,7 @@
      * @return true if a Temperature type is valid otherwise false.
      */
     public static boolean isValidType(@Type int type) {
-        return type >= TYPE_UNKNOWN && type <= TYPE_SOC;
+        return type >= TYPE_UNKNOWN && type <= TYPE_POGO;
     }
 
     /**
diff --git a/core/java/android/os/TimestampedValue.java b/core/java/android/os/TimestampedValue.java
index 3d8a550..e514d63 100644
--- a/core/java/android/os/TimestampedValue.java
+++ b/core/java/android/os/TimestampedValue.java
@@ -35,6 +35,7 @@
  * @param <T> the type of the value with an associated timestamp
  * @hide
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public final class TimestampedValue<T> implements Parcelable {
     private final long mReferenceTimeMillis;
     @Nullable
diff --git a/core/java/android/os/WorkSource.java b/core/java/android/os/WorkSource.java
index bc80c8b..6d4e284 100644
--- a/core/java/android/os/WorkSource.java
+++ b/core/java/android/os/WorkSource.java
@@ -23,6 +23,7 @@
  * Currently the public representation of what a work source is not
  * defined; this is an opaque container.
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class WorkSource implements Parcelable {
     static final String TAG = "WorkSource";
     static final boolean DEBUG = false;
@@ -141,11 +142,17 @@
      *
      * @hide
      */
+    @android.ravenwood.annotation.RavenwoodReplace
     public static boolean isChainedBatteryAttributionEnabled(Context context) {
         return Settings.Global.getInt(context.getContentResolver(),
                 Global.CHAINED_BATTERY_ATTRIBUTION_ENABLED, 0) == 1;
     }
 
+    /** @hide */
+    public static boolean isChainedBatteryAttributionEnabled$ravenwood(Context context) {
+        return false;
+    }
+
     /**
      * Returns the number of uids in this work source.
      * @hide
diff --git a/core/java/android/os/flags.aconfig b/core/java/android/os/flags.aconfig
index 980c13c..83d237d 100644
--- a/core/java/android/os/flags.aconfig
+++ b/core/java/android/os/flags.aconfig
@@ -76,3 +76,18 @@
     description: "Guards the ADPF GPU APIs."
     bug: "284324521"
 }
+
+flag {
+    name: "adpf_use_fmq_channel"
+    namespace: "game"
+    description: "Guards use of the FMQ channel for ADPF"
+    bug: "315894228"
+}
+
+flag {
+    name: "battery_service_support_current_adb_command"
+    namespace: "backstage_power"
+    description: "Whether or not BatteryService supports adb commands for Current values."
+    is_fixed_read_only: true
+    bug: "315037695"
+}
diff --git a/core/java/android/os/storage/OWNERS b/core/java/android/os/storage/OWNERS
index bf22dcc..6941857 100644
--- a/core/java/android/os/storage/OWNERS
+++ b/core/java/android/os/storage/OWNERS
@@ -1,6 +1,6 @@
 # Bug component: 95221
 
-# Please assign new bugs to android-storage-triage@, not to individual people
+# PLEASE ASSIGN NEW BUGS TO android-storage-triage@, NOT TO INDIVIDUAL PEOPLE
 
 # Android Storage Team
 alukin@google.com
diff --git a/core/java/android/permission/PermissionControllerService.java b/core/java/android/permission/PermissionControllerService.java
index 9fe2599..5a12760 100644
--- a/core/java/android/permission/PermissionControllerService.java
+++ b/core/java/android/permission/PermissionControllerService.java
@@ -318,7 +318,7 @@
      *                 a virtual device. See {@link Context#DEVICE_ID_DEFAULT}
      */
     @BinderThread
-    @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS)
+    @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
     public void onOneTimePermissionSessionTimeout(@NonNull String packageName,
             int deviceId) {
         onOneTimePermissionSessionTimeout(packageName);
@@ -393,7 +393,7 @@
      * @see android.content.Context#revokeSelfPermissionsOnKill(java.util.Collection)
      */
     @BinderThread
-    @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS)
+    @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
     public void onRevokeSelfPermissionsOnKill(@NonNull String packageName,
             @NonNull List<String> permissions, int deviceId, @NonNull Runnable callback) {
         onRevokeSelfPermissionsOnKill(packageName, permissions, callback);
diff --git a/core/java/android/permission/flags.aconfig b/core/java/android/permission/flags.aconfig
index cbeb821..d09c229 100644
--- a/core/java/android/permission/flags.aconfig
+++ b/core/java/android/permission/flags.aconfig
@@ -1,7 +1,7 @@
 package: "android.permission.flags"
 
 flag {
-  name: "device_aware_permission_apis"
+  name: "device_aware_permission_apis_enabled"
   is_fixed_read_only: true
   namespace: "permissions"
   description: "enable device aware permission APIs"
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 8b5995a..290ae4a 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -608,6 +608,23 @@
 
     /**
      * Activity Action: Show settings to allow configuration of
+     * {@link Manifest.permission#MEDIA_ROUTING_CONTROL} permission.
+     *
+     * Input: Optionally, the Intent's data URI can specify the application package name to
+     * directly invoke the management GUI specific to the package name. For example
+     * "package:com.my.app". However, modifying this permission setting for any package is allowed
+     * only when that package holds an appropriate companion device profile such as
+     * {@link android.companion.AssociationRequest#DEVICE_PROFILE_WATCH}.
+     * <p>
+     * Output: Nothing.
+     */
+    @FlaggedApi("com.android.media.flags.enable_privileged_routing_for_media_routing_control")
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_REQUEST_MEDIA_ROUTING_CONTROL =
+            "android.settings.REQUEST_MEDIA_ROUTING_CONTROL";
+
+    /**
+     * Activity Action: Show settings to allow configuration of
      * {@link Manifest.permission#RUN_USER_INITIATED_JOBS} permission
      *
      * Input: Optionally, the Intent's data URI can specify the application package name to
@@ -7774,6 +7791,25 @@
         public static final String SHOW_IME_WITH_HARD_KEYBOARD = "show_ime_with_hard_keyboard";
 
         /**
+         * Whether to enable bounce keys for Physical Keyboard accessibility.
+         *
+         * If set to non-zero value, any key press on physical keyboard within the provided
+         * threshold duration (in milliseconds) of the same key, will be ignored.
+         *
+         * @hide
+         */
+        public static final String ACCESSIBILITY_BOUNCE_KEYS = "accessibility_bounce_keys";
+
+        /**
+         * Whether to enable sticky keys for Physical Keyboard accessibility.
+         *
+         * This is a boolean value that determines if Sticky keys feature is enabled.
+         *
+         * @hide
+         */
+        public static final String ACCESSIBILITY_STICKY_KEYS = "accessibility_sticky_keys";
+
+        /**
          * Whether stylus button presses are disabled. This is a boolean that
          * determines if stylus buttons are ignored.
          *
@@ -8274,6 +8310,17 @@
         public static final String ACCESSIBILITY_BUTTON_TARGETS = "accessibility_button_targets";
 
         /**
+         * Setting specifying the accessibility services, accessibility shortcut targets,
+         * or features to be toggled via a tile in the quick settings panel.
+         *
+         * <p> This is a colon-separated string list which contains the flattened
+         * {@link ComponentName} and the class name of a system class implementing a supported
+         * accessibility feature.
+         * @hide
+         */
+        public static final String ACCESSIBILITY_QS_TARGETS = "accessibility_qs_targets";
+
+        /**
          * The system class name of magnification controller which is a target to be toggled via
          * accessibility shortcut or accessibility button.
          *
@@ -12109,6 +12156,7 @@
             CLONE_TO_MANAGED_PROFILE.add(LOCATION_CHANGER);
             CLONE_TO_MANAGED_PROFILE.add(LOCATION_MODE);
             CLONE_TO_MANAGED_PROFILE.add(SHOW_IME_WITH_HARD_KEYBOARD);
+            CLONE_TO_MANAGED_PROFILE.add(ACCESSIBILITY_BOUNCE_KEYS);
             CLONE_TO_MANAGED_PROFILE.add(NOTIFICATION_BUBBLES);
         }
 
diff --git a/core/java/android/security/NetworkSecurityPolicy.java b/core/java/android/security/NetworkSecurityPolicy.java
index 0c4eeda..e679d20 100644
--- a/core/java/android/security/NetworkSecurityPolicy.java
+++ b/core/java/android/security/NetworkSecurityPolicy.java
@@ -16,6 +16,8 @@
 
 package android.security;
 
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.security.net.config.ApplicationConfig;
@@ -26,9 +28,6 @@
  *
  * <p>Network stacks/components should honor this policy to make it possible to centrally control
  * the relevant aspects of network security behavior.
- *
- * <p>The policy currently consists of a single flag: whether cleartext network traffic is
- * permitted. See {@link #isCleartextTrafficPermitted()}.
  */
 public class NetworkSecurityPolicy {
 
@@ -94,6 +93,22 @@
     }
 
     /**
+     * Returns {@code true} if Certificate Transparency information is required to be verified by
+     * the client in TLS connections to {@code hostname}.
+     *
+     * <p>See RFC6962 section 3.3 for more details.
+     *
+     * @param hostname hostname to check whether certificate transparency verification is required
+     * @return {@code true} if certificate transparency verification is required and {@code false}
+     *     otherwise
+     */
+    @FlaggedApi(Flags.FLAG_CERTIFICATE_TRANSPARENCY_CONFIGURATION)
+    public boolean isCertificateTransparencyVerificationRequired(@NonNull String hostname) {
+        return libcore.net.NetworkSecurityPolicy.getInstance()
+                .isCertificateTransparencyVerificationRequired(hostname);
+    }
+
+    /**
      * Handle an update to the system or user certificate stores.
      * @hide
      */
diff --git a/core/java/android/security/flags.aconfig b/core/java/android/security/flags.aconfig
index 0dc0413..b56bef3 100644
--- a/core/java/android/security/flags.aconfig
+++ b/core/java/android/security/flags.aconfig
@@ -1,6 +1,13 @@
 package: "android.security"
 
 flag {
+    name: "certificate_transparency_configuration"
+    namespace: "network_security"
+    description: "Enable certificate transparency setting in the network security config"
+    bug: "28746284"
+}
+
+flag {
     name: "fsverity_api"
     namespace: "hardware_backed_security"
     description: "Feature flag for fs-verity API"
@@ -8,6 +15,13 @@
 }
 
 flag {
+    name: "mgf1_digest_setter"
+    namespace: "hardware_backed_security"
+    description: "Feature flag for mgf1 digest setter in key generation and import parameters."
+    bug: "308378912"
+}
+
+flag {
     name: "fix_unlocked_device_required_keys_v2"
     namespace: "hardware_backed_security"
     description: "Fix bugs in behavior of UnlockedDeviceRequired keystore keys"
diff --git a/core/java/android/security/net/config/ApplicationConfig.java b/core/java/android/security/net/config/ApplicationConfig.java
index 801eceb..4cc870b 100644
--- a/core/java/android/security/net/config/ApplicationConfig.java
+++ b/core/java/android/security/net/config/ApplicationConfig.java
@@ -16,10 +16,15 @@
 
 package android.security.net.config;
 
+import static android.security.Flags.certificateTransparencyConfiguration;
+
+import android.annotation.NonNull;
 import android.util.Pair;
+
 import java.util.HashSet;
 import java.util.Locale;
 import java.util.Set;
+
 import javax.net.ssl.X509TrustManager;
 
 /**
@@ -147,6 +152,22 @@
         return getConfigForHostname(hostname).isCleartextTrafficPermitted();
     }
 
+    /**
+     * Returns {@code true} if Certificate Transparency information is required to be verified by
+     * the client in TLS connections to {@code hostname}.
+     *
+     * <p>See RFC6962 section 3.3 for more details.
+     *
+     * @param hostname hostname to check whether certificate transparency verification is required
+     * @return {@code true} if certificate transparency verification is required and {@code false}
+     *     otherwise
+     */
+    public boolean isCertificateTransparencyVerificationRequired(@NonNull String hostname) {
+        return certificateTransparencyConfiguration()
+                ? getConfigForHostname(hostname).isCertificateTransparencyVerificationRequired()
+                : NetworkSecurityConfig.DEFAULT_CERTIFICATE_TRANSPARENCY_VERIFICATION_REQUIRED;
+    }
+
     public void handleTrustStorageUpdate() {
         synchronized(mLock) {
             // If the config is uninitialized then there is no work to be done to handle an update,
diff --git a/core/java/android/security/net/config/ConfigNetworkSecurityPolicy.java b/core/java/android/security/net/config/ConfigNetworkSecurityPolicy.java
index a708f5b..801b32b 100644
--- a/core/java/android/security/net/config/ConfigNetworkSecurityPolicy.java
+++ b/core/java/android/security/net/config/ConfigNetworkSecurityPolicy.java
@@ -40,6 +40,6 @@
 
     @Override
     public boolean isCertificateTransparencyVerificationRequired(String hostname) {
-        return false;
+        return mConfig.isCertificateTransparencyVerificationRequired(hostname);
     }
 }
diff --git a/core/java/android/security/net/config/NetworkSecurityConfig.java b/core/java/android/security/net/config/NetworkSecurityConfig.java
index 00872fb..129ae63 100644
--- a/core/java/android/security/net/config/NetworkSecurityConfig.java
+++ b/core/java/android/security/net/config/NetworkSecurityConfig.java
@@ -38,9 +38,12 @@
     public static final boolean DEFAULT_CLEARTEXT_TRAFFIC_PERMITTED = true;
     /** @hide */
     public static final boolean DEFAULT_HSTS_ENFORCED = false;
+    /** @hide */
+    public static final boolean DEFAULT_CERTIFICATE_TRANSPARENCY_VERIFICATION_REQUIRED = false;
 
     private final boolean mCleartextTrafficPermitted;
     private final boolean mHstsEnforced;
+    private final boolean mCertificateTransparencyVerificationRequired;
     private final PinSet mPins;
     private final List<CertificatesEntryRef> mCertificatesEntryRefs;
     private Set<TrustAnchor> mAnchors;
@@ -48,10 +51,15 @@
     private NetworkSecurityTrustManager mTrustManager;
     private final Object mTrustManagerLock = new Object();
 
-    private NetworkSecurityConfig(boolean cleartextTrafficPermitted, boolean hstsEnforced,
-            PinSet pins, List<CertificatesEntryRef> certificatesEntryRefs) {
+    private NetworkSecurityConfig(
+            boolean cleartextTrafficPermitted,
+            boolean hstsEnforced,
+            boolean certificateTransparencyVerificationRequired,
+            PinSet pins,
+            List<CertificatesEntryRef> certificatesEntryRefs) {
         mCleartextTrafficPermitted = cleartextTrafficPermitted;
         mHstsEnforced = hstsEnforced;
+        mCertificateTransparencyVerificationRequired = certificateTransparencyVerificationRequired;
         mPins = pins;
         mCertificatesEntryRefs = certificatesEntryRefs;
         // Sort the certificates entry refs so that all entries that override pins come before
@@ -104,6 +112,11 @@
         return mHstsEnforced;
     }
 
+    // TODO(b/28746284): add exceptions for user-added certificates and enterprise overrides.
+    public boolean isCertificateTransparencyVerificationRequired() {
+        return mCertificateTransparencyVerificationRequired;
+    }
+
     public PinSet getPins() {
         return mPins;
     }
@@ -208,6 +221,9 @@
         private boolean mHstsEnforced = DEFAULT_HSTS_ENFORCED;
         private boolean mCleartextTrafficPermittedSet = false;
         private boolean mHstsEnforcedSet = false;
+        private boolean mCertificateTransparencyVerificationRequired =
+                DEFAULT_CERTIFICATE_TRANSPARENCY_VERIFICATION_REQUIRED;
+        private boolean mCertificateTransparencyVerificationRequiredSet = false;
         private Builder mParentBuilder;
 
         /**
@@ -313,12 +329,35 @@
             return mCertificatesEntryRefs;
         }
 
+        Builder setCertificateTransparencyVerificationRequired(boolean required) {
+            mCertificateTransparencyVerificationRequired = required;
+            mCertificateTransparencyVerificationRequiredSet = true;
+            return this;
+        }
+
+        private boolean getCertificateTransparencyVerificationRequired() {
+            if (mCertificateTransparencyVerificationRequiredSet) {
+                return mCertificateTransparencyVerificationRequired;
+            }
+            if (mParentBuilder != null) {
+                return mParentBuilder.getCertificateTransparencyVerificationRequired();
+            }
+            return DEFAULT_CERTIFICATE_TRANSPARENCY_VERIFICATION_REQUIRED;
+        }
+
         public NetworkSecurityConfig build() {
             boolean cleartextPermitted = getEffectiveCleartextTrafficPermitted();
             boolean hstsEnforced = getEffectiveHstsEnforced();
+            boolean certificateTransparencyVerificationRequired =
+                    getCertificateTransparencyVerificationRequired();
             PinSet pinSet = getEffectivePinSet();
             List<CertificatesEntryRef> entryRefs = getEffectiveCertificatesEntryRefs();
-            return new NetworkSecurityConfig(cleartextPermitted, hstsEnforced, pinSet, entryRefs);
+            return new NetworkSecurityConfig(
+                    cleartextPermitted,
+                    hstsEnforced,
+                    certificateTransparencyVerificationRequired,
+                    pinSet,
+                    entryRefs);
         }
     }
 }
diff --git a/core/java/android/security/net/config/XmlConfigSource.java b/core/java/android/security/net/config/XmlConfigSource.java
index 311a8d2..b1c1479 100644
--- a/core/java/android/security/net/config/XmlConfigSource.java
+++ b/core/java/android/security/net/config/XmlConfigSource.java
@@ -171,6 +171,11 @@
         return new Domain(domain, includeSubdomains);
     }
 
+    private boolean parseCertificateTransparency(XmlResourceParser parser)
+            throws IOException, XmlPullParserException, ParserException {
+        return parser.getAttributeBooleanValue(null, "enabled", false);
+    }
+
     private CertificatesEntryRef parseCertificatesEntry(XmlResourceParser parser,
             boolean defaultOverridePins)
             throws IOException, XmlPullParserException, ParserException {
@@ -226,7 +231,6 @@
         boolean seenPinSet = false;
         boolean seenTrustAnchors = false;
         boolean defaultOverridePins = configType == CONFIG_DEBUG;
-        String configName = parser.getName();
         int outerDepth = parser.getDepth();
         // Add this builder now so that this builder occurs before any of its children. This
         // makes the final build pass easier.
@@ -279,6 +283,15 @@
                             "Nested domain-config not allowed in " + getConfigString(configType));
                 }
                 builders.addAll(parseConfigEntry(parser, seenDomains, builder, configType));
+            } else if ("certificateTransparency".equals(tagName)) {
+                if (configType != CONFIG_BASE && configType != CONFIG_DOMAIN) {
+                    throw new ParserException(
+                            parser,
+                            "certificateTransparency not allowed in "
+                                    + getConfigString(configType));
+                }
+                builder.setCertificateTransparencyVerificationRequired(
+                        parseCertificateTransparency(parser));
             } else {
                 XmlUtils.skipCurrentTag(parser);
             }
diff --git a/core/java/android/service/dreams/flags.aconfig b/core/java/android/service/dreams/flags.aconfig
new file mode 100644
index 0000000..91a713e
--- /dev/null
+++ b/core/java/android/service/dreams/flags.aconfig
@@ -0,0 +1,9 @@
+package: "android.service.dreams"
+
+flag {
+  name: "dream_overlay_host"
+  namespace: "communal"
+  description: "This flag enables using a host to handle displaying a dream's overlay rather than "
+      "relying on the dream's window"
+  bug: "291990564"
+}
diff --git a/core/java/android/service/notification/Condition.java b/core/java/android/service/notification/Condition.java
index 531626b..6e771f8 100644
--- a/core/java/android/service/notification/Condition.java
+++ b/core/java/android/service/notification/Condition.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2014, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,6 +16,8 @@
 
 package android.service.notification;
 
+import static com.android.internal.util.Preconditions.checkArgument;
+
 import android.annotation.FlaggedApi;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
@@ -117,7 +119,7 @@
 
     /** The source of, or reason for, the state change represented by this Condition. **/
     @FlaggedApi(Flags.FLAG_MODES_API)
-    public final @Source int source;
+    public final @Source int source; // default = SOURCE_UNKNOWN
 
     /**
      * The maximum string length for any string contained in this condition.
@@ -179,7 +181,7 @@
         this.line2 = getTrimmedString(line2);
         this.icon = icon;
         this.state = state;
-        this.source = source;
+        this.source = checkValidSource(source);
         this.flags = flags;
     }
 
@@ -197,10 +199,26 @@
                 source.readInt());
     }
 
+    /** @hide */
+    public void validate() {
+        if (Flags.modesApi()) {
+            checkValidSource(source);
+        }
+    }
+
     private static boolean isValidState(int state) {
         return state >= STATE_FALSE && state <= STATE_ERROR;
     }
 
+    private static int checkValidSource(@Source int source) {
+        if (Flags.modesApi()) {
+            checkArgument(source >= SOURCE_UNKNOWN && source <= SOURCE_CONTEXT,
+                    "Condition source must be one of SOURCE_UNKNOWN, SOURCE_USER_ACTION, "
+                            + "SOURCE_SCHEDULE, or SOURCE_CONTEXT");
+        }
+        return source;
+    }
+
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeParcelable(id, 0);
diff --git a/core/java/android/service/notification/DeviceEffectsApplier.java b/core/java/android/service/notification/DeviceEffectsApplier.java
index 234ff4d..5194cdd 100644
--- a/core/java/android/service/notification/DeviceEffectsApplier.java
+++ b/core/java/android/service/notification/DeviceEffectsApplier.java
@@ -16,6 +16,8 @@
 
 package android.service.notification;
 
+import android.service.notification.ZenModeConfig.ConfigChangeOrigin;
+
 /**
  * Responsible for making any service calls needed to apply the set of {@link ZenDeviceEffects} that
  * make sense for the current platform.
@@ -33,6 +35,13 @@
      *
      * <p>This will be called whenever the set of consolidated effects changes (normally through
      * the activation or deactivation of zen rules).
+     *
+     * @param effects The effects that should be active and inactive.
+     * @param source The origin of the change. Because the application of specific effects can be
+     *               disruptive (e.g. lead to Activity recreation), that operation can in some
+     *               cases be deferred (e.g. until screen off). However, if the effects are
+     *               changing as a result of an explicit user action, then it makes sense to
+     *               apply them immediately regardless.
      */
-    void apply(ZenDeviceEffects effects);
+    void apply(ZenDeviceEffects effects, @ConfigChangeOrigin int source);
 }
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index bb56939..264b53c 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -272,8 +272,10 @@
     /**
      * @param notification Some kind of clone of this.notification.
      * @return A shallow copy of self, with notification in place of this.notification.
+     *
+     * @hide
      */
-    StatusBarNotification cloneShallow(Notification notification) {
+    public StatusBarNotification cloneShallow(Notification notification) {
         StatusBarNotification result = new StatusBarNotification(this.pkg, this.opPkg,
                 this.id, this.tag, this.uid, this.initialPid,
                 notification, this.user, this.overrideGroupKey, this.postTime);
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index f6128ea..fcdc5fe 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -26,6 +26,7 @@
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
 
 import android.annotation.FlaggedApi;
+import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.AlarmManager;
@@ -61,6 +62,8 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Arrays;
 import java.util.Calendar;
 import java.util.Date;
@@ -79,7 +82,66 @@
  * @hide
  */
 public class ZenModeConfig implements Parcelable {
-    private static String TAG = "ZenModeConfig";
+    private static final String TAG = "ZenModeConfig";
+
+    /**
+     * The {@link ZenModeConfig} is being updated because of an unknown reason.
+     */
+    public static final int UPDATE_ORIGIN_UNKNOWN = 0;
+
+    /**
+     * The {@link ZenModeConfig} is being updated because of system initialization (i.e. load from
+     * storage, on device boot).
+     */
+    public static final int UPDATE_ORIGIN_INIT = 1;
+
+    /** The {@link ZenModeConfig} is being updated (replaced) because of a user switch or unlock. */
+    public static final int UPDATE_ORIGIN_INIT_USER = 2;
+
+    /** The {@link ZenModeConfig} is being updated because of a user action, for example:
+     * <ul>
+     *     <li>{@link NotificationManager#setAutomaticZenRuleState} with a
+     *     {@link Condition#source} equal to {@link Condition#SOURCE_USER_ACTION}.</li>
+     *     <li>Adding, updating, or removing a rule from Settings.</li>
+     *     <li>Directly activating or deactivating/snoozing a rule through some UI affordance (e.g.
+     *     Quick Settings).</li>
+     * </ul>
+     */
+    public static final int UPDATE_ORIGIN_USER = 3;
+
+    /**
+     * The {@link ZenModeConfig} is being "independently" updated by an app, and not as a result of
+     * a user's action inside that app (for example, activating an {@link AutomaticZenRule} based on
+     * a previously set schedule).
+     */
+    public static final int UPDATE_ORIGIN_APP = 4;
+
+    /**
+     * The {@link ZenModeConfig} is being updated by the System or SystemUI. Note that this only
+     * includes cases where the call is coming from the System/SystemUI but the change is not due to
+     * a user action (e.g. automatically activating a schedule-based rule). If the change is a
+     * result of a user action (e.g. activating a rule by tapping on its QS tile) then
+     * {@link #UPDATE_ORIGIN_USER} is used instead.
+     */
+    public static final int UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI = 5;
+
+    /**
+     * The {@link ZenModeConfig} is being updated (replaced) because the user's DND configuration
+     * is being restored from a backup.
+     */
+    public static final int UPDATE_ORIGIN_RESTORE_BACKUP = 6;
+
+    @IntDef(prefix = { "UPDATE_ORIGIN_" }, value = {
+            UPDATE_ORIGIN_UNKNOWN,
+            UPDATE_ORIGIN_INIT,
+            UPDATE_ORIGIN_INIT_USER,
+            UPDATE_ORIGIN_USER,
+            UPDATE_ORIGIN_APP,
+            UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI,
+            UPDATE_ORIGIN_RESTORE_BACKUP
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ConfigChangeOrigin {}
 
     public static final int SOURCE_ANYONE = Policy.PRIORITY_SENDERS_ANY;
     public static final int SOURCE_CONTACT = Policy.PRIORITY_SENDERS_CONTACTS;
@@ -1918,6 +1980,7 @@
         @Nullable public ZenDeviceEffects zenDeviceEffects;
         public boolean modified;    // rule has been modified from initial creation
         public String pkg;
+        @AutomaticZenRule.Type
         public int type = AutomaticZenRule.TYPE_UNKNOWN;
         public String triggerDescription;
         public String iconResName;
diff --git a/core/java/android/service/notification/flags.aconfig b/core/java/android/service/notification/flags.aconfig
index 2a05c84..a2ade6a 100644
--- a/core/java/android/service/notification/flags.aconfig
+++ b/core/java/android/service/notification/flags.aconfig
@@ -15,3 +15,9 @@
     bug: "299448097"
 }
 
+flag {
+  name: "redact_sensitive_notifications_from_untrusted_listeners"
+  namespace: "systemui"
+  description: "This flag controls the redacting of sensitive notifications from untrusted NotificationListenerServices"
+  bug: "306271190"
+}
diff --git a/core/java/android/service/persistentdata/OWNERS b/core/java/android/service/persistentdata/OWNERS
new file mode 100644
index 0000000..6dfb888
--- /dev/null
+++ b/core/java/android/service/persistentdata/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pdb/OWNERS
diff --git a/core/java/android/service/voice/HotwordRejectedResult.java b/core/java/android/service/voice/HotwordRejectedResult.java
index 26c1ca4..eb1ac67 100644
--- a/core/java/android/service/voice/HotwordRejectedResult.java
+++ b/core/java/android/service/voice/HotwordRejectedResult.java
@@ -16,9 +16,11 @@
 
 package android.service.voice;
 
+import android.annotation.FlaggedApi;
 import android.annotation.IntDef;
 import android.annotation.SystemApi;
 import android.os.Parcelable;
+import android.service.voice.flags.Flags;
 
 import com.android.internal.util.DataClass;
 
@@ -53,12 +55,17 @@
     /** High confidence in hotword detector result. */
     public static final int CONFIDENCE_LEVEL_HIGH = 3;
 
+    /** Very high confidence in hotword detector result. **/
+    @FlaggedApi(Flags.FLAG_ALLOW_HOTWORD_BUMP_EGRESS)
+    public static final int CONFIDENCE_LEVEL_VERY_HIGH = 4;
+
     /** @hide */
     @IntDef(prefix = {"CONFIDENCE_LEVEL_"}, value = {
             CONFIDENCE_LEVEL_NONE,
             CONFIDENCE_LEVEL_LOW,
             CONFIDENCE_LEVEL_MEDIUM,
-            CONFIDENCE_LEVEL_HIGH
+            CONFIDENCE_LEVEL_HIGH,
+            CONFIDENCE_LEVEL_VERY_HIGH
     })
     @Retention(RetentionPolicy.SOURCE)
     @interface HotwordConfidenceLevelValue {
@@ -91,9 +98,10 @@
         CONFIDENCE_LEVEL_NONE,
         CONFIDENCE_LEVEL_LOW,
         CONFIDENCE_LEVEL_MEDIUM,
-        CONFIDENCE_LEVEL_HIGH
+        CONFIDENCE_LEVEL_HIGH,
+        CONFIDENCE_LEVEL_VERY_HIGH
     })
-    @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE)
+    @Retention(RetentionPolicy.SOURCE)
     @DataClass.Generated.Member
     public @interface ConfidenceLevel {}
 
@@ -109,6 +117,8 @@
                     return "CONFIDENCE_LEVEL_MEDIUM";
             case CONFIDENCE_LEVEL_HIGH:
                     return "CONFIDENCE_LEVEL_HIGH";
+            case CONFIDENCE_LEVEL_VERY_HIGH:
+                    return "CONFIDENCE_LEVEL_VERY_HIGH";
             default: return Integer.toHexString(value);
         }
     }
@@ -259,10 +269,10 @@
     }
 
     @DataClass.Generated(
-            time = 1621961370106L,
+            time = 1701990933632L,
             codegenVersion = "1.0.23",
             sourceFile = "frameworks/base/core/java/android/service/voice/HotwordRejectedResult.java",
-            inputSignatures = "public static final  int CONFIDENCE_LEVEL_NONE\npublic static final  int CONFIDENCE_LEVEL_LOW\npublic static final  int CONFIDENCE_LEVEL_MEDIUM\npublic static final  int CONFIDENCE_LEVEL_HIGH\nprivate final @android.service.voice.HotwordRejectedResult.HotwordConfidenceLevelValue int mConfidenceLevel\nprivate static  int defaultConfidenceLevel()\nclass HotwordRejectedResult extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=true, genEqualsHashCode=true, genHiddenConstDefs=true, genParcelable=true, genToString=true)")
+            inputSignatures = "public static final  int CONFIDENCE_LEVEL_NONE\npublic static final  int CONFIDENCE_LEVEL_LOW\npublic static final  int CONFIDENCE_LEVEL_MEDIUM\npublic static final  int CONFIDENCE_LEVEL_HIGH\npublic static final @android.annotation.FlaggedApi int CONFIDENCE_LEVEL_VERY_HIGH\nprivate final @android.service.voice.HotwordRejectedResult.HotwordConfidenceLevelValue int mConfidenceLevel\nprivate static  int defaultConfidenceLevel()\nclass HotwordRejectedResult extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=true, genEqualsHashCode=true, genHiddenConstDefs=true, genParcelable=true, genToString=true)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/core/java/android/service/voice/VisualQueryDetectionService.java b/core/java/android/service/voice/VisualQueryDetectionService.java
index d184b1e..76b076b 100644
--- a/core/java/android/service/voice/VisualQueryDetectionService.java
+++ b/core/java/android/service/voice/VisualQueryDetectionService.java
@@ -338,16 +338,24 @@
 
     /**
      * Overrides {@link Context#openFileInput} to read files with the given file names under the
-     * internal app storage of the {@link VoiceInteractionService}, i.e., only files stored in
-     * {@link Context#getFilesDir()} can be opened.
+     * internal app storage of the {@link VoiceInteractionService}, i.e., the input file path would
+     * be added with {@link Context#getFilesDir()} as prefix.
+     *
+     * @param filename Relative path of a file under {@link Context#getFilesDir()}.
+     * @throws FileNotFoundException if the file does not exist or cannot be open.
      */
     @Override
-    public @Nullable FileInputStream openFileInput(@NonNull String filename) throws
+    public @NonNull FileInputStream openFileInput(@NonNull String filename) throws
             FileNotFoundException {
         try {
             AndroidFuture<ParcelFileDescriptor> future = new AndroidFuture<>();
+            assert mDetectorSessionStorageService != null;
             mDetectorSessionStorageService.openFile(filename, future);
             ParcelFileDescriptor pfd = future.get();
+            if (pfd == null) {
+                throw new FileNotFoundException(
+                        "File does not exist. Unable to open " + filename + ".");
+            }
             return new FileInputStream(pfd.getFileDescriptor());
         } catch (RemoteException | ExecutionException | InterruptedException e) {
             Log.w(TAG, "Cannot open file due to remote service failure");
diff --git a/core/java/android/service/voice/VisualQueryDetector.java b/core/java/android/service/voice/VisualQueryDetector.java
index 91de894..b7d9705 100644
--- a/core/java/android/service/voice/VisualQueryDetector.java
+++ b/core/java/android/service/voice/VisualQueryDetector.java
@@ -447,12 +447,12 @@
         public void onOpenFile(String filename, AndroidFuture future) throws RemoteException {
             Slog.v(TAG, "BinderCallback#onOpenFile " + filename);
             Binder.withCleanCallingIdentity(() -> mExecutor.execute(() -> {
-                Slog.v(TAG, "onOpenFile: " + filename);
+                Slog.v(TAG, "onOpenFile: " + filename + "under internal app storage.");
                 File f = new File(mContext.getFilesDir(), filename);
                 ParcelFileDescriptor pfd = null;
                 try {
-                    Slog.d(TAG, "opened a file with ParcelFileDescriptor.");
                     pfd = ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY);
+                    Slog.d(TAG, "Successfully opened a file with ParcelFileDescriptor.");
                 } catch (FileNotFoundException e) {
                     Slog.e(TAG, "Cannot open file. No ParcelFileDescriptor returned.");
                 } finally {
diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java
index fba0923..75ab48a 100644
--- a/core/java/android/service/voice/VoiceInteractionService.java
+++ b/core/java/android/service/voice/VoiceInteractionService.java
@@ -1042,13 +1042,13 @@
     @SystemApi
     @FlaggedApi(Flags.FLAG_ALLOW_TRAINING_DATA_EGRESS_FROM_HDS)
     @RequiresPermission(Manifest.permission.MANAGE_HOTWORD_DETECTION)
-    public void setIsReceiveSandboxedTrainingDataAllowed(boolean allowed) {
-        Log.i(TAG, "setIsReceiveSandboxedTrainingDataAllowed to " + allowed);
+    public void setShouldReceiveSandboxedTrainingData(boolean allowed) {
+        Log.i(TAG, "setShouldReceiveSandboxedTrainingData to " + allowed);
         if (mSystemService == null) {
             throw new IllegalStateException("Not available until onReady() is called");
         }
         try {
-            mSystemService.setIsReceiveSandboxedTrainingDataAllowed(allowed);
+            mSystemService.setShouldReceiveSandboxedTrainingData(allowed);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/service/voice/flags/flags.aconfig b/core/java/android/service/voice/flags/flags.aconfig
index c414ef8..b596666 100644
--- a/core/java/android/service/voice/flags/flags.aconfig
+++ b/core/java/android/service/voice/flags/flags.aconfig
@@ -6,3 +6,10 @@
     description: "This flag allows the hotword detection service to egress training data to the default assistant."
     bug: "296074924"
 }
+
+flag {
+    name: "allow_hotword_bump_egress"
+    namespace: "machine_learning"
+    description: "This flag allows hotword detection service to egress reason code for hotword bump."
+    bug: "290951024"
+}
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 89aceb9..c9906cc 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -3906,17 +3906,20 @@
     // Getters of parameters that is used for building Layout instance
     ///////////////////////////////////////////////////////////////////////////////////////////////
 
+    // TODO(316208691): Revive following removed API docs.
+    // @see Layout.Builder
     /**
      * Return the text used for creating this layout.
      *
      * @return the text used for creating this layout.
-     * @see Layout.Builder
      */
     @NonNull
     public final CharSequence getText() {
         return mText;
     }
 
+    // TODO(316208691): Revive following removed API docs.
+    // @see Layout.Builder
     /**
      * Return the paint used for creating this layout.
      *
@@ -3924,29 +3927,30 @@
      * drawing/measuring text.
      *
      * @return the paint used for creating this layout.
-     * @see Layout.Builder
      */
     @NonNull
     public final TextPaint getPaint() {
         return mPaint;
     }
 
+    // TODO(316208691): Revive following removed API docs.
+    // @see Layout.Builder
     /**
      * Return the width used for creating this layout in pixels.
      *
      * @return the width used for creating this layout in pixels.
-     * @see Layout.Builder
      */
     @IntRange(from = 0)
     public final int getWidth() {
         return mWidth;
     }
 
+    // TODO(316208691): Revive following removed API docs.
+    // @see Layout.Builder#setAlignment(Alignment)
     /**
      * Returns the alignment used for creating this layout in pixels.
      *
      * @return the alignment used for creating this layout.
-     * @see Layout.Builder#setAlignment(Alignment)
      * @see StaticLayout.Builder#setAlignment(Alignment)
      */
     @NonNull
@@ -3967,15 +3971,15 @@
         return mTextDir;
     }
 
+    // TODO(316208691): Revive following removed API docs.
+    // This is an alias of {@link #getLineSpacingMultiplier}.
+    // @see Layout.Builder#setLineSpacingMultiplier(float)
+    // @see Layout#getLineSpacingMultiplier()
     /**
      * Returns the multiplier applied to the line height.
      *
-     * This is an alias of {@link #getLineSpacingMultiplier}.
-     *
      * @return the line height multiplier.
-     * @see Layout.Builder#setLineSpacingMultiplier(float)
      * @see StaticLayout.Builder#setLineSpacing(float, float)
-     * @see Layout#getLineSpacingMultiplier()
      */
     public final float getSpacingMultiplier() {
         return getLineSpacingMultiplier();
@@ -3994,15 +3998,15 @@
         return mSpacingMult;
     }
 
+    // TODO(316208691): Revive following removed API docs.
+    // This is an alias of {@link #getLineSpacingAmount()}.
+    // @see Layout.Builder#setLineSpacingAmount(float)
+    // @see Layout#getLineSpacingAmount()
     /**
      * Returns the amount added to the line height.
      *
-     * This is an alias of {@link #getLineSpacingAmount()}.
-     *
      * @return the line height additional amount.
-     * @see Layout.Builder#setLineSpacingAmount(float)
      * @see StaticLayout.Builder#setLineSpacing(float, float)
-     * @see Layout#getLineSpacingAmount()
      */
     public final float getSpacingAdd() {
         return getLineSpacingAmount();
@@ -4033,11 +4037,12 @@
         return mIncludePad;
     }
 
+    // TODO(316208691): Revive following removed API docs.
+    // @see Layout.Builder#setFallbackLineSpacingEnabled(boolean)
     /**
      * Return true if the fallback line space is enabled in this Layout.
      *
      * @return true if the fallback line space is enabled. Otherwise, returns false.
-     * @see Layout.Builder#setFallbackLineSpacingEnabled(boolean)
      * @see StaticLayout.Builder#setUseLineSpacingFromFallbacks(boolean)
      */
     // not being final because of already published API.
@@ -4045,17 +4050,18 @@
         return mFallbackLineSpacing;
     }
 
+    // TODO(316208691): Revive following removed API docs.
+    // @see Layout.Builder#setEllipsizedWidth(int)
+    // @see Layout.Builder#setEllipsize(TextUtils.TruncateAt)
+    // @see Layout#getEllipsize()
     /**
      * Return the width to which this layout is ellipsized.
      *
      * If no ellipsize is applied, the same amount of {@link #getWidth} is returned.
      *
      * @return the amount of ellipsized width in pixels.
-     * @see Layout.Builder#setEllipsizedWidth(int)
      * @see StaticLayout.Builder#setEllipsizedWidth(int)
-     * @see Layout.Builder#setEllipsize(TextUtils.TruncateAt)
      * @see StaticLayout.Builder#setEllipsize(TextUtils.TruncateAt)
-     * @see Layout#getEllipsize()
      */
     @IntRange(from = 0)
     public int getEllipsizedWidth() {  // not being final because of already published API.
diff --git a/core/java/android/util/DayOfMonthCursor.java b/core/java/android/util/DayOfMonthCursor.java
index 393b98e..ac5dc3a 100644
--- a/core/java/android/util/DayOfMonthCursor.java
+++ b/core/java/android/util/DayOfMonthCursor.java
@@ -32,6 +32,7 @@
  *
  * @hide
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class DayOfMonthCursor extends MonthDisplayHelper {
 
     private int mRow;
diff --git a/core/java/android/util/DumpableContainer.java b/core/java/android/util/DumpableContainer.java
index fef5acd..24640c9 100644
--- a/core/java/android/util/DumpableContainer.java
+++ b/core/java/android/util/DumpableContainer.java
@@ -20,6 +20,7 @@
 /**
  * Represents a container that manages {@link Dumpable dumpables}.
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public interface DumpableContainer {
 
     /**
diff --git a/core/java/android/util/KeyValueListParser.java b/core/java/android/util/KeyValueListParser.java
index fbc66e6..783b2d6 100644
--- a/core/java/android/util/KeyValueListParser.java
+++ b/core/java/android/util/KeyValueListParser.java
@@ -28,6 +28,7 @@
  * can be used.
  * @hide
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class KeyValueListParser {
     private final ArrayMap<String, String> mValues = new ArrayMap<>();
     private final TextUtils.StringSplitter mSplitter;
diff --git a/core/java/android/util/LongArrayQueue.java b/core/java/android/util/LongArrayQueue.java
index 354f8df..b9752fe 100644
--- a/core/java/android/util/LongArrayQueue.java
+++ b/core/java/android/util/LongArrayQueue.java
@@ -28,6 +28,7 @@
  *
  * @hide
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class LongArrayQueue {
 
     private long[] mValues;
diff --git a/core/java/android/util/LongSparseLongArray.java b/core/java/android/util/LongSparseLongArray.java
index d4a0126..86268fa 100644
--- a/core/java/android/util/LongSparseLongArray.java
+++ b/core/java/android/util/LongSparseLongArray.java
@@ -46,6 +46,7 @@
  *
  * @hide
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class LongSparseLongArray implements Cloneable {
     @UnsupportedAppUsage(maxTargetSdk = 28) // The type isn't even public.
     private long[] mKeys;
diff --git a/core/java/android/util/MonthDisplayHelper.java b/core/java/android/util/MonthDisplayHelper.java
index c3f13fc..3bd292b 100644
--- a/core/java/android/util/MonthDisplayHelper.java
+++ b/core/java/android/util/MonthDisplayHelper.java
@@ -24,6 +24,7 @@
  *
  * Not thread safe.
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class MonthDisplayHelper {
 
     // display pref
diff --git a/core/java/android/util/RecurrenceRule.java b/core/java/android/util/RecurrenceRule.java
index 39d1f2c..dc470d7 100644
--- a/core/java/android/util/RecurrenceRule.java
+++ b/core/java/android/util/RecurrenceRule.java
@@ -42,6 +42,7 @@
  *
  * @hide
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class RecurrenceRule implements Parcelable {
     private static final String TAG = "RecurrenceRule";
     private static final boolean LOGD = Log.isLoggable(TAG, Log.DEBUG);
diff --git a/core/java/android/util/RotationUtils.java b/core/java/android/util/RotationUtils.java
index f20767b..07ab996 100644
--- a/core/java/android/util/RotationUtils.java
+++ b/core/java/android/util/RotationUtils.java
@@ -36,6 +36,7 @@
  *
  * @hide
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class RotationUtils {
 
     /**
diff --git a/core/java/android/util/SparseDoubleArray.java b/core/java/android/util/SparseDoubleArray.java
index 4b0cbe4..8a0b11e 100644
--- a/core/java/android/util/SparseDoubleArray.java
+++ b/core/java/android/util/SparseDoubleArray.java
@@ -41,6 +41,7 @@
  *
  * @hide
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class SparseDoubleArray implements Cloneable {
     /**
      * The int->double map, but storing the doubles as longs using
diff --git a/core/java/android/util/SparseSetArray.java b/core/java/android/util/SparseSetArray.java
index 61f29a4..80f6a4a08 100644
--- a/core/java/android/util/SparseSetArray.java
+++ b/core/java/android/util/SparseSetArray.java
@@ -22,6 +22,7 @@
  *
  * @hide
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class SparseSetArray<T> {
     private final SparseArray<ArraySet<T>> mData;
 
diff --git a/core/java/android/util/StateSet.java b/core/java/android/util/StateSet.java
index 4bbc0f8..16d6082 100644
--- a/core/java/android/util/StateSet.java
+++ b/core/java/android/util/StateSet.java
@@ -34,7 +34,6 @@
  * and not have static methods here but there is some concern about
  * performance since these methods are called during view drawing.
  */
-
 public class StateSet {
     /**
      * The order here is very important to
diff --git a/core/java/android/util/Xml.java b/core/java/android/util/Xml.java
index 2a33caa..ec6e90b 100644
--- a/core/java/android/util/Xml.java
+++ b/core/java/android/util/Xml.java
@@ -334,6 +334,7 @@
      *
      * @hide
      */
+    @android.ravenwood.annotation.RavenwoodKeep
     public static void copy(@NonNull XmlPullParser in, @NonNull XmlSerializer out)
             throws XmlPullParserException, IOException {
         // Some parsers may have already consumed the event that starts the
@@ -393,6 +394,7 @@
      * unsupported, which can confuse serializers. This method normalizes empty
      * strings to be {@code null}.
      */
+    @android.ravenwood.annotation.RavenwoodKeep
     private static @Nullable String normalizeNamespace(@Nullable String namespace) {
         if (namespace == null || namespace.isEmpty()) {
             return null;
diff --git a/core/java/android/view/AttachedSurfaceControl.java b/core/java/android/view/AttachedSurfaceControl.java
index fd5517d..f28574e 100644
--- a/core/java/android/view/AttachedSurfaceControl.java
+++ b/core/java/android/view/AttachedSurfaceControl.java
@@ -27,9 +27,6 @@
 
 import com.android.window.flags.Flags;
 
-import java.util.concurrent.Executor;
-import java.util.function.Consumer;
-
 /**
  * Provides an interface to the root-Surface of a View Hierarchy or Window. This
  * is used in combination with the {@link android.view.SurfaceControl} API to enable
@@ -197,42 +194,6 @@
     }
 
     /**
-     * Add a trusted presentation listener on the SurfaceControl associated with this window.
-     *
-     * @param t          Transaction that the trusted presentation listener is added on. This should
-     *                   be applied by the caller.
-     * @param thresholds The {@link SurfaceControl.TrustedPresentationThresholds} that will specify
-     *                   when the to invoke the callback.
-     * @param executor   The {@link Executor} where the callback will be invoked on.
-     * @param listener   The {@link Consumer} that will receive the callbacks when entered or
-     *                   exited the threshold.
-     *
-     * @see SurfaceControl.Transaction#setTrustedPresentationCallback(SurfaceControl,
-     * SurfaceControl.TrustedPresentationThresholds, Executor, Consumer)
-     *
-     * @hide b/287076178 un-hide with API bump
-     */
-    default void addTrustedPresentationCallback(@NonNull SurfaceControl.Transaction t,
-            @NonNull SurfaceControl.TrustedPresentationThresholds thresholds,
-            @NonNull Executor executor, @NonNull Consumer<Boolean> listener) {
-    }
-
-    /**
-     * Remove a trusted presentation listener on the SurfaceControl associated with this window.
-     *
-     * @param t          Transaction that the trusted presentation listener removed on. This should
-     *                   be applied by the caller.
-     * @param listener   The {@link Consumer} that was previously registered with
-     *                   addTrustedPresentationCallback that should be removed.
-     *
-     * @see SurfaceControl.Transaction#clearTrustedPresentationCallback(SurfaceControl)
-     * @hide b/287076178 un-hide with API bump
-     */
-    default void removeTrustedPresentationCallback(@NonNull SurfaceControl.Transaction t,
-            @NonNull Consumer<Boolean> listener) {
-    }
-
-    /**
      * Transfer the currently in progress touch gesture from the host to the requested
      * {@link SurfaceControlViewHost.SurfacePackage}. This requires that the
      * SurfaceControlViewHost was created with the current host's inputToken.
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 07dd882..1908c64c 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -276,15 +276,14 @@
     /**
      * Display flag: Indicates that the display should show system decorations.
      * <p>
-     * This flag identifies secondary displays that should show system decorations, such as status
-     * bar, navigation bar, home activity or IME.
+     * This flag identifies secondary displays that should show system decorations, such as
+     * navigation bar, home activity or wallpaper.
      * </p>
      * <p>Note that this flag doesn't work without {@link #FLAG_TRUSTED}</p>
      *
      * @see #getFlags()
      * @hide
      */
-    // TODO (b/114338689): Remove the flag and use IWindowManager#setShouldShowSystemDecors
     public static final int FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS = 1 << 6;
 
     /**
diff --git a/core/java/android/view/ISurfaceControlViewHostParent.aidl b/core/java/android/view/ISurfaceControlViewHostParent.aidl
index f42e001..559c20e 100644
--- a/core/java/android/view/ISurfaceControlViewHostParent.aidl
+++ b/core/java/android/view/ISurfaceControlViewHostParent.aidl
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.view.KeyEvent;
 import android.view.WindowManager;
 
 /**
@@ -24,4 +25,6 @@
  */
 oneway interface ISurfaceControlViewHostParent {
     void updateParams(in WindowManager.LayoutParams[] childAttrs);
+    // To forward the back key event from embedded to host app.
+    void forwardBackKeyToParent(in KeyEvent keyEvent);
 }
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 17bbee6d0..36b74e3 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -73,6 +73,8 @@
 import android.window.ITaskFpsCallback;
 import android.window.ScreenCapture;
 import android.window.WindowContextInfo;
+import android.window.ITrustedPresentationListener;
+import android.window.TrustedPresentationThresholds;
 
 /**
  * System private interface to the window manager.
@@ -1075,4 +1077,10 @@
     @JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
             + ".permission.MONITOR_INPUT)")
     void unregisterDecorViewGestureListener(IDecorViewGestureListener listener, int displayId);
+
+    void registerTrustedPresentationListener(in IBinder window, in ITrustedPresentationListener listener,
+            in TrustedPresentationThresholds thresholds, int id);
+
+
+    void unregisterTrustedPresentationListener(in ITrustedPresentationListener listener, int id);
 }
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index dbacca5..9bf43a3 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -162,6 +162,8 @@
      * @param flags See {@code View#startDragAndDrop}
      * @param surface Surface containing drag shadow image
      * @param touchSource See {@code InputDevice#getSource()}
+     * @param touchDeviceId device ID of last touch event
+     * @param pointerId pointer ID of last touch event
      * @param touchX X coordinate of last touch point
      * @param touchY Y coordinate of last touch point
      * @param thumbCenterX X coordinate for the position within the shadow image that should be
@@ -171,9 +173,9 @@
      * @param data Data transferred by drag and drop
      * @return Token of drag operation which will be passed to cancelDragAndDrop.
      */
-    @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
     IBinder performDrag(IWindow window, int flags, in SurfaceControl surface, int touchSource,
-            float touchX, float touchY, float thumbCenterX, float thumbCenterY, in ClipData data);
+            int touchDeviceId, int touchPointerId, float touchX, float touchY, float thumbCenterX,
+            float thumbCenterY, in ClipData data);
 
     /**
      * Drops the content of the current drag operation for accessibility
diff --git a/core/java/android/view/SurfaceControlViewHost.java b/core/java/android/view/SurfaceControlViewHost.java
index 4056531..4840f00 100644
--- a/core/java/android/view/SurfaceControlViewHost.java
+++ b/core/java/android/view/SurfaceControlViewHost.java
@@ -447,6 +447,7 @@
         addWindowToken(attrs);
         view.setLayoutParams(attrs);
         mViewRoot.setView(view, attrs, null);
+        mViewRoot.setBackKeyCallbackForWindowlessWindow(mWm::forwardBackKeyToParent);
     }
 
     /**
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index a44a95a..108de28 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -37,6 +37,7 @@
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.graphics.RenderNode;
+import android.hardware.input.InputManager;
 import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
@@ -159,6 +160,8 @@
     private static final boolean DEBUG = false;
     private static final boolean DEBUG_POSITION = false;
 
+    private static final long FORWARD_BACK_KEY_TOLERANCE_MS = 100;
+
     @UnsupportedAppUsage(
             maxTargetSdk = Build.VERSION_CODES.TIRAMISU,
             publicAlternatives = "Track {@link SurfaceHolder#addCallback} instead")
@@ -326,6 +329,41 @@
                 });
             }
         }
+
+        @Override
+        public void forwardBackKeyToParent(@NonNull KeyEvent keyEvent) {
+                runOnUiThread(() -> {
+                    if (!isAttachedToWindow() || keyEvent.getKeyCode() != KeyEvent.KEYCODE_BACK) {
+                        return;
+                    }
+                    final ViewRootImpl vri = getViewRootImpl();
+                    if (vri == null) {
+                        return;
+                    }
+                    final InputManager inputManager = mContext.getSystemService(InputManager.class);
+                    if (inputManager == null) {
+                        return;
+                    }
+                    // Check that the event was created recently.
+                    final long timeDiff = SystemClock.uptimeMillis() - keyEvent.getEventTime();
+                    if (timeDiff > FORWARD_BACK_KEY_TOLERANCE_MS) {
+                        Log.e(TAG, "Ignore the input event that exceed the tolerance time, "
+                                + "exceed " + timeDiff + "ms");
+                        return;
+                    }
+                    if (inputManager.verifyInputEvent(keyEvent) == null) {
+                        Log.e(TAG, "Received invalid input event");
+                        return;
+                    }
+                    try {
+                        vri.processingBackKey(true);
+                        vri.enqueueInputEvent(keyEvent, null /* receiver */, 0 /* flags */,
+                                true /* processImmediately */);
+                    } finally {
+                        vri.processingBackKey(false);
+                    }
+                });
+        }
     };
 
     private final boolean mRtDrivenClipping = Flags.clipSurfaceviews();
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 75f8eba..cbafd1c 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -28340,6 +28340,8 @@
                 IBinder token = mAttachInfo.mSession.performDrag(
                         mAttachInfo.mWindow, flags, null,
                         mAttachInfo.mViewRootImpl.getLastTouchSource(),
+                        mAttachInfo.mViewRootImpl.getLastTouchDeviceId(),
+                        mAttachInfo.mViewRootImpl.getLastTouchPointerId(),
                         0f, 0f, 0f, 0f, data);
                 if (ViewDebug.DEBUG_DRAG) {
                     Log.d(VIEW_LOG_TAG, "startDragAndDrop via a11y action returned " + token);
@@ -28414,7 +28416,8 @@
             }
 
             token = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, flags, surfaceControl,
-                    root.getLastTouchSource(), lastTouchPoint.x, lastTouchPoint.y,
+                    root.getLastTouchSource(), root.getLastTouchDeviceId(),
+                    root.getLastTouchPointerId(), lastTouchPoint.x, lastTouchPoint.y,
                     shadowTouchPoint.x, shadowTouchPoint.y, data);
             if (ViewDebug.DEBUG_DRAG) {
                 Log.d(VIEW_LOG_TAG, "performDrag returned " + token);
@@ -32685,6 +32688,8 @@
                 == PFLAG4_IMPORTANT_FOR_CREDENTIAL_MANAGER);
     }
 
+    // TODO(316208691): Revive following removed API docs.
+    // @see EditorInfo#setStylusHandwritingEnabled(boolean)
     /**
      * Set whether this view enables automatic handwriting initiation.
      *
@@ -32706,7 +32711,6 @@
      * @see android.view.inputmethod.InputMethodManager#startStylusHandwriting(View)
      * @param enabled whether auto handwriting initiation is enabled for this view.
      * @attr ref android.R.styleable#View_autoHandwritingEnabled
-     * @see EditorInfo#setStylusHandwritingEnabled(boolean)
      */
     public void setAutoHandwritingEnabled(boolean enabled) {
         if (enabled) {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 1530aa7..e83488e 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -76,13 +76,8 @@
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_OPTIMIZE_MEASURE;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
-import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
-import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
-import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL;
 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
@@ -96,6 +91,7 @@
 import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.IME_FOCUS_CONTROLLER;
 import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.INSETS_CONTROLLER;
 import static android.view.flags.Flags.toolkitSetFrameRateReadOnly;
+import static android.view.flags.Flags.toolkitMetricsForFrameRateDecision;
 
 import static com.android.input.flags.Flags.enablePointerChoreographer;
 
@@ -255,7 +251,7 @@
 import java.util.Queue;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executor;
-import java.util.function.Consumer;
+import java.util.function.Predicate;
 
 /**
  * The top of a view hierarchy, implementing the needed protocol between View
@@ -375,6 +371,8 @@
      */
     private static final int KEEP_CLEAR_AREA_REPORT_RATE_MILLIS = 100;
 
+    private static final long NANOS_PER_SEC = 1000000000;
+
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     static final ThreadLocal<HandlerActionQueue> sRunQueues = new ThreadLocal<HandlerActionQueue>();
 
@@ -620,6 +618,13 @@
     boolean mUpcomingWindowFocus;
     @GuardedBy("this")
     boolean mUpcomingInTouchMode;
+    // While set, allow this VRI to handle back key without drop it.
+    private boolean mProcessingBackKey;
+    /**
+     * Compatibility {@link OnBackInvokedCallback} for windowless window, to forward the back
+     * key event host app.
+     */
+    private Predicate<KeyEvent> mWindowlessBackKeyCallback;
 
     public boolean mTraversalScheduled;
     int mTraversalBarrier;
@@ -808,6 +813,8 @@
     final PointF mDragPoint = new PointF();
     final PointF mLastTouchPoint = new PointF();
     int mLastTouchSource;
+    int mLastTouchDeviceId = KeyCharacterMap.VIRTUAL_KEYBOARD;
+    int mLastTouchPointerId;
     /** Tracks last {@link MotionEvent#getToolType(int)} with {@link MotionEvent#ACTION_UP}. **/
     private int mLastClickToolType;
 
@@ -822,15 +829,25 @@
 
     private boolean mInsetsAnimationRunning;
 
+    private long mPreviousFrameDrawnTime = -1;
+
     /**
      * The resolved pointer icon type requested by this window.
      * A null value indicates the resolved pointer icon has not yet been calculated.
      */
+    // TODO(b/293587049): Remove pointer icon tracking by type when refactor is complete.
     @Nullable
     private Integer mPointerIconType = null;
     private PointerIcon mCustomPointerIcon = null;
 
     /**
+     * The resolved pointer icon requested by this window.
+     * A null value indicates the resolved pointer icon has not yet been calculated.
+     */
+    @Nullable
+    private PointerIcon mResolvedPointerIcon = null;
+
+    /**
      * see {@link #playSoundEffect(int)}
      */
     AudioManager mAudioManager;
@@ -1051,11 +1068,14 @@
     private boolean mChildBoundingInsetsChanged = false;
 
     private String mTag = TAG;
+    private String mFpsTraceName;
 
     private static boolean sToolkitSetFrameRateReadOnlyFlagValue;
+    private static boolean sToolkitMetricsForFrameRateDecisionFlagValue;
 
     static {
         sToolkitSetFrameRateReadOnlyFlagValue = toolkitSetFrameRateReadOnly();
+        sToolkitMetricsForFrameRateDecisionFlagValue = toolkitMetricsForFrameRateDecision();
     }
 
     // The latest input event from the gesture that was used to resolve the pointer icon.
@@ -1299,6 +1319,7 @@
 
                 attrs = mWindowAttributes;
                 setTag();
+                mFpsTraceName = "FPS of " + getTitle();
 
                 if (DEBUG_KEEP_SCREEN_ON && (mClientWindowLayoutFlags
                         & WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) != 0
@@ -3186,7 +3207,11 @@
             host.dispatchAttachedToWindow(mAttachInfo, 0);
             mAttachInfo.mTreeObserver.dispatchOnWindowAttachedChange(true);
             dispatchApplyInsets(host);
-            if (!mOnBackInvokedDispatcher.isOnBackInvokedCallbackEnabled()) {
+            if (!mOnBackInvokedDispatcher.isOnBackInvokedCallbackEnabled()
+                    // Don't register compat OnBackInvokedCallback for windowless window.
+                    // The onBackInvoked event by default should forward to host app, so the
+                    // host app can decide the behavior.
+                    && mWindowlessBackKeyCallback == null) {
                 // For apps requesting legacy back behavior, we add a compat callback that
                 // dispatches {@link KeyEvent#KEYCODE_BACK} to their root views.
                 // This way from system point of view, these apps are providing custom
@@ -3216,6 +3241,12 @@
                 endDragResizing();
                 destroyHardwareResources();
             }
+
+            if (sToolkitSetFrameRateReadOnlyFlagValue && viewVisibility == View.VISIBLE) {
+                // Boost frame rate when the viewVisibility becomes true.
+                // This is mainly for lanuchers that lanuch new windows.
+                boostFrameRate(FRAME_RATE_TOUCH_BOOST_TIME);
+            }
         }
 
         // Non-visible windows can't hold accessibility focus.
@@ -3925,6 +3956,11 @@
                     focused.restoreDefaultFocus();
                 }
             }
+
+            if (sToolkitSetFrameRateReadOnlyFlagValue) {
+                // Boost the frame rate when the ViewRootImpl first becomes available.
+                boostFrameRate(FRAME_RATE_TOUCH_BOOST_TIME);
+            }
         }
 
         final boolean changedVisibility = (viewVisibilityChanged || mFirst) && isViewVisible;
@@ -4707,6 +4743,31 @@
         }
     }
 
+    /**
+     * Called from draw() to collect metrics for frame rate decision.
+     */
+    private void collectFrameRateDecisionMetrics() {
+        if (!Trace.isEnabled()) {
+            if (mPreviousFrameDrawnTime > 0) mPreviousFrameDrawnTime = -1;
+            return;
+        }
+
+        if (mPreviousFrameDrawnTime < 0) {
+            mPreviousFrameDrawnTime = mChoreographer.getExpectedPresentationTimeNanos();
+            return;
+        }
+
+        long expectedDrawnTime = mChoreographer.getExpectedPresentationTimeNanos();
+        long timeDiff = expectedDrawnTime - mPreviousFrameDrawnTime;
+        if (timeDiff <= 0) {
+            return;
+        }
+
+        long fps = NANOS_PER_SEC / timeDiff;
+        Trace.setCounter(mFpsTraceName, fps);
+        mPreviousFrameDrawnTime = expectedDrawnTime;
+    }
+
     private void reportDrawFinished(@Nullable Transaction t, int seqId) {
         if (DEBUG_BLAST) {
             Log.d(mTag, "reportDrawFinished");
@@ -5025,6 +5086,9 @@
         if (DEBUG_FPS) {
             trackFPS();
         }
+        if (sToolkitMetricsForFrameRateDecisionFlagValue) {
+            collectFrameRateDecisionMetrics();
+        }
 
         if (!sFirstDrawComplete) {
             synchronized (sFirstDrawHandlers) {
@@ -6641,7 +6705,8 @@
 
             // Find a reason for dropping or canceling the event.
             final String reason;
-            if (!mAttachInfo.mHasWindowFocus
+            // The embedded window is focused, allow this VRI to handle back key.
+            if (!mAttachInfo.mHasWindowFocus && !(mProcessingBackKey && isBack(q.mEvent))
                     && !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)
                     && !isAutofillUiShowing()) {
                 // This is a non-pointer event and the window doesn't currently have input focus
@@ -6864,10 +6929,20 @@
 
                 // If the new back dispatch is enabled, intercept KEYCODE_BACK before it reaches the
                 // view tree or IME, and invoke the appropriate {@link OnBackInvokedCallback}.
-                if (isBack(keyEvent)
-                        && mContext != null
-                        && mOnBackInvokedDispatcher.isOnBackInvokedCallbackEnabled()) {
-                    return doOnBackKeyEvent(keyEvent);
+                if (isBack(keyEvent)) {
+                    if (mWindowlessBackKeyCallback != null) {
+                        if (mWindowlessBackKeyCallback.test(keyEvent)) {
+                            return keyEvent.getAction() == KeyEvent.ACTION_UP
+                                    && !keyEvent.isCanceled()
+                                    ? FINISH_HANDLED : FINISH_NOT_HANDLED;
+                        } else {
+                            // Unable to forward the back key to host, forward to next stage.
+                            return FORWARD;
+                        }
+                    } else if (mContext != null
+                            && mOnBackInvokedDispatcher.isOnBackInvokedCallbackEnabled()) {
+                        return doOnBackKeyEvent(keyEvent);
+                    }
                 }
 
                 if (mInputQueue != null) {
@@ -7090,6 +7165,8 @@
                 mLastTouchPoint.x = event.getRawX();
                 mLastTouchPoint.y = event.getRawY();
                 mLastTouchSource = event.getSource();
+                mLastTouchDeviceId = event.getDeviceId();
+                mLastTouchPointerId = event.getPointerId(0);
 
                 // Register last ACTION_UP. This will be propagated to IME.
                 if (event.getActionMasked() == MotionEvent.ACTION_UP) {
@@ -7399,12 +7476,14 @@
                 // Other apps or the window manager may change the icon type outside of
                 // this app, therefore the icon type has to be reset on enter/exit event.
                 mPointerIconType = null;
+                mResolvedPointerIcon = null;
             }
 
             if (action != MotionEvent.ACTION_HOVER_EXIT) {
                 // Resolve the pointer icon
                 if (!updatePointerIcon(event) && action == MotionEvent.ACTION_HOVER_MOVE) {
                     mPointerIconType = null;
+                    mResolvedPointerIcon = null;
                 }
             }
 
@@ -7459,6 +7538,7 @@
 
     private void resetPointerIcon(MotionEvent event) {
         mPointerIconType = null;
+        mResolvedPointerIcon = null;
         updatePointerIcon(event);
     }
 
@@ -7496,6 +7576,21 @@
             pointerIcon = mView.onResolvePointerIcon(event, pointerIndex);
         }
 
+        if (enablePointerChoreographer()) {
+            if (pointerIcon == null) {
+                pointerIcon = PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_NOT_SPECIFIED);
+            }
+            if (Objects.equals(mResolvedPointerIcon, pointerIcon)) {
+                return true;
+            }
+            mResolvedPointerIcon = pointerIcon;
+
+            InputManagerGlobal.getInstance()
+                    .setPointerIcon(pointerIcon, event.getDisplayId(),
+                            event.getDeviceId(), event.getPointerId(0), getInputToken());
+            return true;
+        }
+
         final int pointerType = (pointerIcon != null) ?
                 pointerIcon.getType() : PointerIcon.TYPE_NOT_SPECIFIED;
 
@@ -7503,34 +7598,18 @@
             mPointerIconType = pointerType;
             mCustomPointerIcon = null;
             if (mPointerIconType != PointerIcon.TYPE_CUSTOM) {
-                if (enablePointerChoreographer()) {
-                    InputManagerGlobal
-                            .getInstance()
-                            .setPointerIcon(PointerIcon.getSystemIcon(mContext, pointerType),
-                                    event.getDisplayId(), event.getDeviceId(),
-                                    event.getPointerId(pointerIndex), getInputToken());
-                } else {
-                    InputManagerGlobal
-                            .getInstance()
-                            .setPointerIconType(pointerType);
-                }
+                InputManagerGlobal
+                        .getInstance()
+                        .setPointerIconType(pointerType);
                 return true;
             }
         }
         if (mPointerIconType == PointerIcon.TYPE_CUSTOM &&
                 !pointerIcon.equals(mCustomPointerIcon)) {
             mCustomPointerIcon = pointerIcon;
-            if (enablePointerChoreographer()) {
-                InputManagerGlobal
-                        .getInstance()
-                        .setPointerIcon(mCustomPointerIcon,
-                                event.getDisplayId(), event.getDeviceId(),
-                                event.getPointerId(pointerIndex), getInputToken());
-            } else {
-                InputManagerGlobal
-                        .getInstance()
-                        .setCustomPointerIcon(mCustomPointerIcon);
-            }
+            InputManagerGlobal
+                    .getInstance()
+                    .setCustomPointerIcon(mCustomPointerIcon);
         }
         return true;
     }
@@ -8499,6 +8578,14 @@
         return mLastTouchSource;
     }
 
+    public int getLastTouchDeviceId() {
+        return mLastTouchDeviceId;
+    }
+
+    public int getLastTouchPointerId() {
+        return mLastTouchPointerId;
+    }
+
     /**
      * Used by InputMethodManager.
      * @hide
@@ -10508,6 +10595,11 @@
         mHandler.obtainMessage(MSG_REQUEST_SCROLL_CAPTURE, listener).sendToTarget();
     }
 
+    // Make this VRI able to process back key without drop it.
+    void processingBackKey(boolean processing) {
+        mProcessingBackKey = processing;
+    }
+
     /**
      * Collect and include any ScrollCaptureCallback instances registered with the window.
      *
@@ -11732,13 +11824,18 @@
                 KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /* scancode */,
                 KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,
                 InputDevice.SOURCE_KEYBOARD);
-        enqueueInputEvent(ev);
+        enqueueInputEvent(ev, null /* receiver */, 0 /* flags */, true /* processImmediately */);
     }
 
     private void registerCompatOnBackInvokedCallback() {
         mCompatOnBackInvokedCallback = () -> {
-            sendBackKeyEvent(KeyEvent.ACTION_DOWN);
-            sendBackKeyEvent(KeyEvent.ACTION_UP);
+            try {
+                processingBackKey(true);
+                sendBackKeyEvent(KeyEvent.ACTION_DOWN);
+                sendBackKeyEvent(KeyEvent.ACTION_UP);
+            } finally {
+                processingBackKey(false);
+            }
         };
         if (mOnBackInvokedDispatcher.hasImeOnBackInvokedDispatcher()) {
             Log.d(TAG, "Skip registering CompatOnBackInvokedCallback on IME dispatcher");
@@ -12005,18 +12102,6 @@
         scheduleTraversals();
     }
 
-    @Override
-    public void addTrustedPresentationCallback(@NonNull SurfaceControl.Transaction t,
-            @NonNull SurfaceControl.TrustedPresentationThresholds thresholds,
-            @NonNull Executor executor, @NonNull Consumer<Boolean> listener) {
-        t.setTrustedPresentationCallback(getSurfaceControl(), thresholds, executor, listener);
-    }
-
-    @Override
-    public void removeTrustedPresentationCallback(@NonNull SurfaceControl.Transaction t,
-            @NonNull Consumer<Boolean> listener) {
-        t.clearTrustedPresentationCallback(getSurfaceControl());
-    }
 
     private void logAndTrace(String msg) {
         if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
@@ -12036,7 +12121,7 @@
         try {
             if (mLastPreferredFrameRateCategory != frameRateCategory) {
                 mFrameRateTransaction.setFrameRateCategory(mSurfaceControl,
-                    frameRateCategory, false).applyAsyncUnsafe();
+                        frameRateCategory, false).applyAsyncUnsafe();
                 mLastPreferredFrameRateCategory = frameRateCategory;
             }
         } catch (Exception e) {
@@ -12088,11 +12173,9 @@
         boolean desiredAction = motionEventAction == MotionEvent.ACTION_DOWN
                 || motionEventAction == MotionEvent.ACTION_MOVE
                 || motionEventAction == MotionEvent.ACTION_UP;
-        boolean desiredType = windowType == TYPE_BASE_APPLICATION || windowType == TYPE_APPLICATION
-                || windowType == TYPE_APPLICATION_STARTING || windowType == TYPE_DRAWN_APPLICATION
-                || windowType == TYPE_NOTIFICATION_SHADE || windowType == TYPE_STATUS_BAR;
+        boolean undesiredType = windowType == TYPE_INPUT_METHOD;
         // use toolkitSetFrameRate flag to gate the change
-        return desiredAction && desiredType && sToolkitSetFrameRateReadOnlyFlagValue;
+        return desiredAction && !undesiredType && sToolkitSetFrameRateReadOnlyFlagValue;
     }
 
     /**
@@ -12159,6 +12242,22 @@
         return mPreferredFrameRate;
     }
 
+    /**
+     * Get the value of mIsFrameRateBoosting
+     */
+    @VisibleForTesting
+    public boolean getIsFrameRateBoosting() {
+        return mIsFrameRateBoosting;
+    }
+
+    private void boostFrameRate(int boostTimeOut) {
+        mIsFrameRateBoosting = true;
+        setPreferredFrameRateCategory(mPreferredFrameRateCategory);
+        mHandler.removeMessages(MSG_TOUCH_BOOST_TIMEOUT);
+        mHandler.sendEmptyMessageDelayed(MSG_TOUCH_BOOST_TIMEOUT,
+                boostTimeOut);
+    }
+
     @Override
     public boolean transferHostTouchGestureToEmbedded(
             @NonNull SurfaceControlViewHost.SurfacePackage surfacePackage) {
@@ -12171,4 +12270,13 @@
         }
         return false;
     }
+
+    /**
+     * Set the default back key callback for windowless window, to forward the back key event
+     * to host app.
+     * MUST NOT call this method for normal window.
+     */
+    void setBackKeyCallbackForWindowlessWindow(@NonNull Predicate<KeyEvent> callback) {
+        mWindowlessBackKeyCallback = callback;
+    }
 }
diff --git a/core/java/android/view/ViewTreeObserver.java b/core/java/android/view/ViewTreeObserver.java
index c9526fd..3b444c4 100644
--- a/core/java/android/view/ViewTreeObserver.java
+++ b/core/java/android/view/ViewTreeObserver.java
@@ -75,7 +75,7 @@
     private boolean mWindowShown;
 
     // The reason that the last call to dispatchOnPreDraw() returned true to cancel and redraw
-    private String mLastDispatchOnPreDrawCanceledReason;
+    private StringBuilder mLastDispatchOnPreDrawCanceledReason;
 
     private boolean mAlive = true;
 
@@ -1173,9 +1173,15 @@
                 int count = access.size();
                 for (int i = 0; i < count; i++) {
                     final OnPreDrawListener preDrawListener = access.get(i);
-                    cancelDraw |= !(preDrawListener.onPreDraw());
-                    if (cancelDraw) {
-                        mLastDispatchOnPreDrawCanceledReason = preDrawListener.getClass().getName();
+                    final boolean listenerCanceledDraw = !(preDrawListener.onPreDraw());
+                    cancelDraw |= listenerCanceledDraw;
+                    if (listenerCanceledDraw) {
+                        final String className = preDrawListener.getClass().getName();
+                        if (mLastDispatchOnPreDrawCanceledReason == null) {
+                            mLastDispatchOnPreDrawCanceledReason = new StringBuilder(className);
+                        } else {
+                            mLastDispatchOnPreDrawCanceledReason.append("|").append(className);
+                        }
                     }
                 }
             } finally {
@@ -1191,7 +1197,10 @@
      * @hide
      */
     final String getLastDispatchOnPreDrawCanceledReason() {
-        return mLastDispatchOnPreDrawCanceledReason;
+        if (mLastDispatchOnPreDrawCanceledReason != null) {
+            return mLastDispatchOnPreDrawCanceledReason.toString();
+        }
+        return null;
     }
 
     /**
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 046ea77..e3d9c60 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -122,7 +122,11 @@
 import android.view.WindowInsets.Type;
 import android.view.WindowInsets.Type.InsetsType;
 import android.view.accessibility.AccessibilityNodeInfo;
+import android.window.ITrustedPresentationListener;
 import android.window.TaskFpsCallback;
+import android.window.TrustedPresentationThresholds;
+
+import com.android.window.flags.Flags;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -588,6 +592,13 @@
     int TRANSIT_FLAG_KEYGUARD_UNOCCLUDING = (1 << 13); // 0x2000
 
     /**
+     * Transition flag: Indicates that there is a physical display switch
+     * TODO(b/316112906) remove after defer_display_updates flag roll out
+     * @hide
+     */
+    int TRANSIT_FLAG_PHYSICAL_DISPLAY_SWITCH = (1 << 14); // 0x4000
+
+    /**
      * @hide
      */
     @IntDef(flag = true, prefix = { "TRANSIT_FLAG_" }, value = {
@@ -604,7 +615,8 @@
             TRANSIT_FLAG_INVISIBLE,
             TRANSIT_FLAG_KEYGUARD_APPEARING,
             TRANSIT_FLAG_KEYGUARD_OCCLUDING,
-            TRANSIT_FLAG_KEYGUARD_UNOCCLUDING
+            TRANSIT_FLAG_KEYGUARD_UNOCCLUDING,
+            TRANSIT_FLAG_PHYSICAL_DISPLAY_SWITCH,
     })
     @Retention(RetentionPolicy.SOURCE)
     @interface TransitionFlags {}
@@ -656,26 +668,35 @@
 
     /**
      * Display IME Policy: The IME should appear on the local display.
+     *
      * @hide
      */
-    @TestApi
+    @SuppressLint("UnflaggedApi")  // promoting from @TestApi.
+    @SystemApi
     int DISPLAY_IME_POLICY_LOCAL = 0;
 
     /**
-     * Display IME Policy: The IME should appear on the fallback display.
+     * Display IME Policy: The IME should appear on a fallback display.
+     *
+     * <p>The fallback display is always {@link Display#DEFAULT_DISPLAY}.</p>
+     *
      * @hide
      */
-    @TestApi
+    @SuppressLint("UnflaggedApi")  // promoting from @TestApi.
+    @SystemApi
     int DISPLAY_IME_POLICY_FALLBACK_DISPLAY = 1;
 
     /**
      * Display IME Policy: The IME should be hidden.
      *
-     * Setting this policy will prevent the IME from making a connection. This
-     * will prevent any IME from receiving metadata about input.
+     * <p>Setting this policy will prevent the IME from making a connection. This
+     * will prevent any IME from receiving metadata about input and this display will effectively
+     * have no IME.</p>
+     *
      * @hide
      */
-    @TestApi
+    @SuppressLint("UnflaggedApi")  // promoting from @TestApi.
+    @SystemApi
     int DISPLAY_IME_POLICY_HIDE = 2;
 
     /**
@@ -3251,6 +3272,13 @@
         public static final int PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC = 1 << 24;
 
         /**
+         * Flag to indicate that the window consumes the insets of {@link Type#ime()}. This makes
+         * windows below this window unable to receive visible IME insets.
+         * @hide
+         */
+        public static final int PRIVATE_FLAG_CONSUME_IME_INSETS = 1 << 25;
+
+        /**
          * Flag to indicate that the window is controlling the appearance of system bars. So we
          * don't need to adjust it by reading its system UI flags for compatibility.
          * @hide
@@ -3334,6 +3362,7 @@
                 PRIVATE_FLAG_EXCLUDE_FROM_SCREEN_MAGNIFICATION,
                 PRIVATE_FLAG_NOT_MAGNIFIABLE,
                 PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC,
+                PRIVATE_FLAG_CONSUME_IME_INSETS,
                 PRIVATE_FLAG_APPEARANCE_CONTROLLED,
                 PRIVATE_FLAG_BEHAVIOR_CONTROLLED,
                 PRIVATE_FLAG_FIT_INSETS_CONTROLLED,
@@ -3432,6 +3461,10 @@
                         equals = PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC,
                         name = "COLOR_SPACE_AGNOSTIC"),
                 @ViewDebug.FlagToString(
+                        mask = PRIVATE_FLAG_CONSUME_IME_INSETS,
+                        equals = PRIVATE_FLAG_CONSUME_IME_INSETS,
+                        name = "CONSUME_IME_INSETS"),
+                @ViewDebug.FlagToString(
                         mask = PRIVATE_FLAG_APPEARANCE_CONTROLLED,
                         equals = PRIVATE_FLAG_APPEARANCE_CONTROLLED,
                         name = "APPEARANCE_CONTROLLED"),
@@ -3458,7 +3491,7 @@
                 @ViewDebug.FlagToString(
                         mask = PRIVATE_FLAG_SYSTEM_APPLICATION_OVERLAY,
                         equals = PRIVATE_FLAG_SYSTEM_APPLICATION_OVERLAY,
-                        name = "PRIVATE_FLAG_SYSTEM_APPLICATION_OVERLAY")
+                        name = "SYSTEM_APPLICATION_OVERLAY")
         })
         @PrivateFlags
         @TestApi
@@ -5884,4 +5917,34 @@
     default boolean replaceContentOnDisplayWithSc(int displayId, @NonNull SurfaceControl sc) {
         throw new UnsupportedOperationException();
     }
+
+    /**
+     * Add a trusted presentation listener associated with a window.
+     *
+     * <p> If this listener is already registered then the window and thresholds will be updated.
+     *
+     * @param window     The Window to add the trusted presentation listener for
+     * @param thresholds The {@link TrustedPresentationThresholds} that will specify
+     *                   when the to invoke the callback.
+     * @param executor   The {@link Executor} where the callback will be invoked on.
+     * @param listener   The {@link Consumer} that will receive the callbacks
+     *                  when entered or exited trusted presentation per the thresholds.
+     */
+    @FlaggedApi(Flags.FLAG_TRUSTED_PRESENTATION_LISTENER_FOR_WINDOW)
+    default void registerTrustedPresentationListener(@NonNull IBinder window,
+            @NonNull TrustedPresentationThresholds thresholds,  @NonNull Executor executor,
+            @NonNull Consumer<Boolean> listener) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Removes a presentation listener associated with a window. If the listener was not previously
+     * registered, the call will be a noop.
+     *
+     * @see WindowManager#registerTrustedPresentationListener(IBinder, TrustedPresentationThresholds, Executor, Consumer)
+     */
+    @FlaggedApi(Flags.FLAG_TRUSTED_PRESENTATION_LISTENER_FOR_WINDOW)
+    default void unregisterTrustedPresentationListener(@NonNull Consumer<Boolean> listener) {
+        throw new UnsupportedOperationException();
+    }
 }
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 214f1ec..f1e4061 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -30,9 +30,13 @@
 import android.os.ServiceManager;
 import android.os.SystemProperties;
 import android.util.AndroidRuntimeException;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Log;
+import android.util.Pair;
 import android.view.inputmethod.InputMethodManager;
+import android.window.ITrustedPresentationListener;
+import android.window.TrustedPresentationThresholds;
 
 import com.android.internal.util.FastPrintWriter;
 
@@ -43,6 +47,7 @@
 import java.util.ArrayList;
 import java.util.WeakHashMap;
 import java.util.concurrent.Executor;
+import java.util.function.Consumer;
 import java.util.function.IntConsumer;
 
 /**
@@ -143,6 +148,9 @@
 
     private Runnable mSystemPropertyUpdater;
 
+    private final TrustedPresentationListener mTrustedPresentationListener =
+            new TrustedPresentationListener();
+
     private WindowManagerGlobal() {
     }
 
@@ -324,7 +332,7 @@
             final Context context = view.getContext();
             if (context != null
                     && (context.getApplicationInfo().flags
-                            & ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
+                    & ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
                 wparams.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
             }
         }
@@ -482,7 +490,7 @@
                     if (who != null) {
                         WindowLeaked leak = new WindowLeaked(
                                 what + " " + who + " has leaked window "
-                                + root.getView() + " that was originally added here");
+                                        + root.getView() + " that was originally added here");
                         leak.setStackTrace(root.getLocation().getStackTrace());
                         Log.e(TAG, "", leak);
                     }
@@ -790,6 +798,87 @@
         }
     }
 
+    public void registerTrustedPresentationListener(@NonNull IBinder window,
+            @NonNull TrustedPresentationThresholds thresholds, Executor executor,
+            @NonNull Consumer<Boolean> listener) {
+        mTrustedPresentationListener.addListener(window, thresholds, listener, executor);
+    }
+
+    public void unregisterTrustedPresentationListener(@NonNull Consumer<Boolean> listener) {
+        mTrustedPresentationListener.removeListener(listener);
+    }
+
+    private final class TrustedPresentationListener extends
+            ITrustedPresentationListener.Stub {
+        private static int sId = 0;
+        private final ArrayMap<Consumer<Boolean>, Pair<Integer, Executor>> mListeners =
+                new ArrayMap<>();
+
+        private final Object mTplLock = new Object();
+
+        private void addListener(IBinder window, TrustedPresentationThresholds thresholds,
+                Consumer<Boolean> listener, Executor executor) {
+            synchronized (mTplLock) {
+                if (mListeners.containsKey(listener)) {
+                    Log.i(TAG, "Updating listener " + listener + " thresholds to " + thresholds);
+                    removeListener(listener);
+                }
+                int id = sId++;
+                mListeners.put(listener, new Pair<>(id, executor));
+                try {
+                    WindowManagerGlobal.getWindowManagerService()
+                            .registerTrustedPresentationListener(window, this, thresholds, id);
+                } catch (RemoteException e) {
+                    e.rethrowAsRuntimeException();
+                }
+            }
+        }
+
+        private void removeListener(Consumer<Boolean> listener) {
+            synchronized (mTplLock) {
+                var removedListener = mListeners.remove(listener);
+                if (removedListener == null) {
+                    Log.i(TAG, "listener " + listener + " does not exist.");
+                    return;
+                }
+
+                try {
+                    WindowManagerGlobal.getWindowManagerService()
+                            .unregisterTrustedPresentationListener(this, removedListener.first);
+                } catch (RemoteException e) {
+                    e.rethrowAsRuntimeException();
+                }
+            }
+        }
+
+        @Override
+        public void onTrustedPresentationChanged(int[] inTrustedStateListenerIds,
+                int[] outOfTrustedStateListenerIds) {
+            ArrayList<Runnable> firedListeners = new ArrayList<>();
+            synchronized (mTplLock) {
+                mListeners.forEach((listener, idExecutorPair) -> {
+                    final var listenerId =  idExecutorPair.first;
+                    final var executor = idExecutorPair.second;
+                    for (int id : inTrustedStateListenerIds) {
+                        if (listenerId == id) {
+                            firedListeners.add(() -> executor.execute(
+                                    () -> listener.accept(/*presentationState*/true)));
+                        }
+                    }
+                    for (int id : outOfTrustedStateListenerIds) {
+                        if (listenerId == id) {
+                            firedListeners.add(() -> executor.execute(
+                                    () -> listener.accept(/*presentationState*/false)));
+                        }
+                    }
+                });
+            }
+            for (int i = 0; i < firedListeners.size(); i++) {
+                firedListeners.get(i).run();
+            }
+        }
+    }
+
     /** @hide */
     public void addWindowlessRoot(ViewRootImpl impl) {
         synchronized (mLock) {
@@ -801,7 +890,7 @@
     public void removeWindowlessRoot(ViewRootImpl impl) {
         synchronized (mLock) {
             mWindowlessRoots.remove(impl);
-	}
+        }
     }
 
     public void setRecentsAppBehindSystemBars(boolean behindSystemBars) {
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index d7b74b3..b4b1fde 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -37,6 +37,7 @@
 import android.util.Log;
 import android.window.ITaskFpsCallback;
 import android.window.TaskFpsCallback;
+import android.window.TrustedPresentationThresholds;
 import android.window.WindowContext;
 import android.window.WindowMetricsController;
 import android.window.WindowProvider;
@@ -508,4 +509,17 @@
         }
         return false;
     }
+
+    @Override
+    public void registerTrustedPresentationListener(@NonNull IBinder window,
+            @NonNull TrustedPresentationThresholds thresholds, @NonNull Executor executor,
+            @NonNull Consumer<Boolean> listener) {
+        mGlobal.registerTrustedPresentationListener(window, thresholds, executor, listener);
+    }
+
+    @Override
+    public void unregisterTrustedPresentationListener(@NonNull Consumer<Boolean> listener) {
+        mGlobal.unregisterTrustedPresentationListener(listener);
+
+    }
 }
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index d817e6f..d6ac562 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.WindowConfiguration;
 import android.content.res.Configuration;
@@ -488,8 +489,9 @@
 
     @Override
     public android.os.IBinder performDrag(android.view.IWindow window, int flags,
-            android.view.SurfaceControl surface, int touchSource, float touchX, float touchY,
-            float thumbCenterX, float thumbCenterY, android.content.ClipData data) {
+            android.view.SurfaceControl surface, int touchSource, int touchDeviceId,
+            int touchPointerId, float touchX, float touchY, float thumbCenterX, float thumbCenterY,
+            android.content.ClipData data) {
         return null;
     }
 
@@ -703,4 +705,17 @@
             }
         }
     }
+
+    boolean forwardBackKeyToParent(@NonNull KeyEvent keyEvent) {
+        if (mParentInterface == null) {
+            return false;
+        }
+        try {
+            mParentInterface.forwardBackKeyToParent(keyEvent);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to forward back key To Parent: ", e);
+            return false;
+        }
+        return true;
+    }
 }
diff --git a/core/java/android/view/accessibility/IMagnificationConnection.aidl b/core/java/android/view/accessibility/IMagnificationConnection.aidl
index a5e8aaf..aae51ab 100644
--- a/core/java/android/view/accessibility/IMagnificationConnection.aidl
+++ b/core/java/android/view/accessibility/IMagnificationConnection.aidl
@@ -18,7 +18,7 @@
 
 import android.graphics.PointF;
 import android.graphics.Rect;
-import android.view.accessibility.IWindowMagnificationConnectionCallback;
+import android.view.accessibility.IMagnificationConnectionCallback;
 import android.view.accessibility.IRemoteMagnificationAnimationCallback;
 
 /**
@@ -110,11 +110,11 @@
     void removeMagnificationSettingsPanel(int displayId);
 
     /**
-     * Sets {@link IWindowMagnificationConnectionCallback} to receive the request or the callback.
+     * Sets {@link IMagnificationConnectionCallback} to receive the request or the callback.
      *
      * @param callback the interface to be called.
      */
-    void setConnectionCallback(in IWindowMagnificationConnectionCallback callback);
+    void setConnectionCallback(in IMagnificationConnectionCallback callback);
 
     /**
      * Notify System UI the magnification scale on the specified display for userId is changed.
diff --git a/core/java/android/view/accessibility/IWindowMagnificationConnectionCallback.aidl b/core/java/android/view/accessibility/IMagnificationConnectionCallback.aidl
similarity index 97%
rename from core/java/android/view/accessibility/IWindowMagnificationConnectionCallback.aidl
rename to core/java/android/view/accessibility/IMagnificationConnectionCallback.aidl
index 21b4334..0ba61b1 100644
--- a/core/java/android/view/accessibility/IWindowMagnificationConnectionCallback.aidl
+++ b/core/java/android/view/accessibility/IMagnificationConnectionCallback.aidl
@@ -24,7 +24,7 @@
  *
  * @hide
  */
- oneway interface IWindowMagnificationConnectionCallback {
+ oneway interface IMagnificationConnectionCallback {
 
     /**
      * Called when the bounds of the mirrow window is changed.
diff --git a/core/java/android/view/accessibility/flags/accessibility_flags.aconfig b/core/java/android/view/accessibility/flags/accessibility_flags.aconfig
index 75ea08e..0cc19fb 100644
--- a/core/java/android/view/accessibility/flags/accessibility_flags.aconfig
+++ b/core/java/android/view/accessibility/flags/accessibility_flags.aconfig
@@ -10,6 +10,13 @@
 }
 
 flag {
+    name: "a11y_qs_shortcut"
+    namespace: "accessibility"
+    description: "Add Quick Setting as one of the a11y shortcut options"
+    bug: "297554934"
+}
+
+flag {
     namespace: "accessibility"
     name: "allow_shortcut_chooser_on_lockscreen"
     description: "Allows the a11y shortcut disambig dialog to appear on the lockscreen"
@@ -32,6 +39,13 @@
 
 flag {
     namespace: "accessibility"
+    name: "copy_events_for_gesture_detection"
+    description: "Creates copies of MotionEvents and GestureEvents in GestureMatcher"
+    bug: "280130713"
+}
+
+flag {
+    namespace: "accessibility"
     name: "flash_notification_system_api"
     description: "Makes flash notification APIs as system APIs for calling from mainline module"
     bug: "303131332"
@@ -45,6 +59,13 @@
 }
 
 flag {
+    name: "motion_event_observing"
+    namespace: "accessibility"
+    description: "Allows accessibility services to intercept but not consume motion events from specified sources."
+    bug: "297595990"
+}
+
+flag {
     namespace: "accessibility"
     name: "granular_scrolling"
     description: "Allow the use of granular scrolling. This allows scrollable nodes to scroll by increments other than a full screen"
@@ -70,4 +91,4 @@
     namespace: "accessibility"
     description: "Feature flag for system pinch zoom gesture detector and related opt-out apis"
     bug: "283323770"
-}
\ No newline at end of file
+}
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 6bc2a13..bb49679 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -38,6 +38,7 @@
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
+import android.app.ActivityOptions;
 import android.app.assist.AssistStructure.ViewNode;
 import android.app.assist.AssistStructure.ViewNodeBuilder;
 import android.app.assist.AssistStructure.ViewNodeParcelable;
@@ -4370,7 +4371,11 @@
             if (afm != null) {
                 afm.post(() -> {
                     try {
-                        afm.mContext.startIntentSender(intentSender, intent, 0, 0, 0);
+                        Bundle options = ActivityOptions.makeBasic()
+                                .setPendingIntentBackgroundActivityStartMode(
+                                        ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED)
+                                .toBundle();
+                        afm.mContext.startIntentSender(intentSender, intent, 0, 0, 0, options);
                     } catch (IntentSender.SendIntentException e) {
                         Log.e(TAG, "startIntentSender() failed for intent:" + intentSender, e);
                     }
diff --git a/core/java/android/view/contentprotection/flags/content_protection_flags.aconfig b/core/java/android/view/contentprotection/flags/content_protection_flags.aconfig
index f3dc33c..2a3008a 100644
--- a/core/java/android/view/contentprotection/flags/content_protection_flags.aconfig
+++ b/core/java/android/view/contentprotection/flags/content_protection_flags.aconfig
@@ -27,3 +27,10 @@
     description: "If true, an appop is logged on creation of accessibility overlays."
     bug: "289081465"
 }
+
+flag {
+    name: "rapid_clear_notifications_by_listener_app_op_enabled"
+    namespace: "content_protection"
+    description: "If true, an appop is logged when a notification is rapidly cleared by a notification listener."
+    bug: "289080543"
+}
diff --git a/core/java/android/view/flags/refresh_rate_flags.aconfig b/core/java/android/view/flags/refresh_rate_flags.aconfig
index a467afe..0aa516e 100644
--- a/core/java/android/view/flags/refresh_rate_flags.aconfig
+++ b/core/java/android/view/flags/refresh_rate_flags.aconfig
@@ -42,4 +42,12 @@
   namespace: "core_graphics"
   description: "Enable the `setFrameRate` callback"
   bug: "299946220"
+}
+
+flag {
+    name: "toolkit_metrics_for_frame_rate_decision"
+    namespace: "toolkit"
+    description: "Feature flag for toolkit metrics collecting for frame rate decision"
+    bug: "301343249"
+    is_fixed_read_only: true
 }
\ No newline at end of file
diff --git a/core/java/android/view/inputmethod/ImeTracker.java b/core/java/android/view/inputmethod/ImeTracker.java
index fab8c77..1b7d57b 100644
--- a/core/java/android/view/inputmethod/ImeTracker.java
+++ b/core/java/android/view/inputmethod/ImeTracker.java
@@ -20,8 +20,8 @@
 import static android.view.InsetsController.ANIMATION_TYPE_SHOW;
 
 import static com.android.internal.inputmethod.InputMethodDebug.softInputDisplayReasonToString;
-import static com.android.internal.jank.InteractionJankMonitor.CUJ_IME_INSETS_HIDE_ANIMATION;
-import static com.android.internal.jank.InteractionJankMonitor.CUJ_IME_INSETS_SHOW_ANIMATION;
+import static com.android.internal.jank.Cuj.CUJ_IME_INSETS_HIDE_ANIMATION;
+import static com.android.internal.jank.Cuj.CUJ_IME_INSETS_SHOW_ANIMATION;
 import static com.android.internal.util.LatencyTracker.ACTION_REQUEST_IME_HIDDEN;
 import static com.android.internal.util.LatencyTracker.ACTION_REQUEST_IME_SHOWN;
 
@@ -758,7 +758,7 @@
          * A helper method to translate animation type to CUJ type for IME animations.
          *
          * @param animType the animation type.
-         * @return the integer in {@link com.android.internal.jank.InteractionJankMonitor.CujType},
+         * @return the integer in {@link com.android.internal.jank.Cuj.CujType},
          * or {@code -1} if the animation type is not supported for tracking yet.
          */
         private static int getImeInsetsCujFromAnimation(@AnimationType int animType) {
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index 8b55494..d38a95e 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -16,9 +16,11 @@
 
 package android.view.inputmethod;
 
+import android.annotation.FlaggedApi;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
@@ -113,6 +115,11 @@
     final boolean mIsVrOnly;
 
     /**
+     * IME only supports virtual devices.
+     */
+    final boolean mIsVirtualDeviceOnly;
+
+    /**
      * The unique string Id to identify the input method.  This is generated
      * from the input method component.
      */
@@ -239,6 +246,7 @@
         String settingsActivityComponent = null;
         String stylusHandwritingSettingsActivity = null;
         boolean isVrOnly;
+        boolean isVirtualDeviceOnly;
         int isDefaultResId = 0;
 
         XmlResourceParser parser = null;
@@ -277,6 +285,8 @@
             }
 
             isVrOnly = sa.getBoolean(com.android.internal.R.styleable.InputMethod_isVrOnly, false);
+            isVirtualDeviceOnly = sa.getBoolean(
+                    com.android.internal.R.styleable.InputMethod_isVirtualDeviceOnly, false);
             isDefaultResId = sa.getResourceId(
                     com.android.internal.R.styleable.InputMethod_isDefault, 0);
             supportsSwitchingToNextInputMethod = sa.getBoolean(
@@ -382,6 +392,7 @@
         mSuppressesSpellChecker = suppressesSpellChecker;
         mShowInInputMethodPicker = showInInputMethodPicker;
         mIsVrOnly = isVrOnly;
+        mIsVirtualDeviceOnly = isVirtualDeviceOnly;
     }
 
     /**
@@ -399,6 +410,7 @@
         mSuppressesSpellChecker = source.mSuppressesSpellChecker;
         mShowInInputMethodPicker = source.mShowInInputMethodPicker;
         mIsVrOnly = source.mIsVrOnly;
+        mIsVirtualDeviceOnly = source.mIsVirtualDeviceOnly;
         mService = source.mService;
         mSubtypes = source.mSubtypes;
         mHandledConfigChanges = source.mHandledConfigChanges;
@@ -418,6 +430,7 @@
         mSuppressesSpellChecker = source.readBoolean();
         mShowInInputMethodPicker = source.readBoolean();
         mIsVrOnly = source.readBoolean();
+        mIsVirtualDeviceOnly = source.readBoolean();
         mService = ResolveInfo.CREATOR.createFromParcel(source);
         mSubtypes = new InputMethodSubtypeArray(source);
         mHandledConfigChanges = source.readInt();
@@ -435,7 +448,8 @@
                 settingsActivity, null /* subtypes */, 0 /* isDefaultResId */,
                 false /* forceDefault */, true /* supportsSwitchingToNextInputMethod */,
                 false /* inlineSuggestionsEnabled */, false /* isVrOnly */,
-                0 /* handledConfigChanges */, false /* supportsStylusHandwriting */,
+                false /* isVirtualDeviceOnly */, 0 /* handledConfigChanges */,
+                false /* supportsStylusHandwriting */,
                 null /* stylusHandwritingSettingsActivityAttr */,
                 false /* inlineSuggestionsEnabled */);
     }
@@ -453,8 +467,9 @@
                 settingsActivity, null /* subtypes */, 0 /* isDefaultResId */,
                 false /* forceDefault */, true /* supportsSwitchingToNextInputMethod */,
                 false /* inlineSuggestionsEnabled */, false /* isVrOnly */,
-                0 /* handledConfigChanges */, supportStylusHandwriting,
-                stylusHandwritingSettingsActivityAttr, false /* inlineSuggestionsEnabled */);
+                false /* isVirtualDeviceOnly */, 0 /* handledConfigChanges */,
+                supportStylusHandwriting, stylusHandwritingSettingsActivityAttr,
+                false /* inlineSuggestionsEnabled */);
     }
 
     /**
@@ -468,7 +483,8 @@
         this(buildFakeResolveInfo(packageName, className, label), false /* isAuxIme */,
                 settingsActivity, null /* subtypes */, 0 /* isDefaultResId */,
                 false /* forceDefault */, true /* supportsSwitchingToNextInputMethod */,
-                false /* inlineSuggestionsEnabled */, false /* isVrOnly */, handledConfigChanges,
+                false /* inlineSuggestionsEnabled */, false /* isVrOnly */,
+                false /* isVirtualDeviceOnly */, handledConfigChanges,
                 false /* supportsStylusHandwriting */,
                 null /* stylusHandwritingSettingsActivityAttr */,
                 false /* inlineSuggestionsEnabled */);
@@ -483,7 +499,7 @@
             boolean forceDefault) {
         this(ri, isAuxIme, settingsActivity, subtypes, isDefaultResId, forceDefault,
                 true /* supportsSwitchingToNextInputMethod */, false /* inlineSuggestionsEnabled */,
-                false /* isVrOnly */, 0 /* handledconfigChanges */,
+                false /* isVrOnly */, false /* isVirtualDeviceOnly */, 0 /* handledconfigChanges */,
                 false /* supportsStylusHandwriting */,
                 null /* stylusHandwritingSettingsActivityAttr */,
                 false /* inlineSuggestionsEnabled */);
@@ -498,6 +514,7 @@
             boolean supportsSwitchingToNextInputMethod, boolean isVrOnly) {
         this(ri, isAuxIme, settingsActivity, subtypes, isDefaultResId, forceDefault,
                 supportsSwitchingToNextInputMethod, false /* inlineSuggestionsEnabled */, isVrOnly,
+                false /* isVirtualDeviceOnly */,
                 0 /* handledConfigChanges */, false /* supportsStylusHandwriting */,
                 null /* stylusHandwritingSettingsActivityAttr */,
                 false /* inlineSuggestionsEnabled */);
@@ -510,8 +527,8 @@
     public InputMethodInfo(ResolveInfo ri, boolean isAuxIme, String settingsActivity,
             List<InputMethodSubtype> subtypes, int isDefaultResId, boolean forceDefault,
             boolean supportsSwitchingToNextInputMethod, boolean inlineSuggestionsEnabled,
-            boolean isVrOnly, int handledConfigChanges, boolean supportsStylusHandwriting,
-            String stylusHandwritingSettingsActivityAttr,
+            boolean isVrOnly, boolean isVirtualDeviceOnly, int handledConfigChanges,
+            boolean supportsStylusHandwriting, String stylusHandwritingSettingsActivityAttr,
             boolean supportsInlineSuggestionsWithTouchExploration) {
         final ServiceInfo si = ri.serviceInfo;
         mService = ri;
@@ -528,6 +545,7 @@
         mSuppressesSpellChecker = false;
         mShowInInputMethodPicker = true;
         mIsVrOnly = isVrOnly;
+        mIsVirtualDeviceOnly = isVirtualDeviceOnly;
         mHandledConfigChanges = handledConfigChanges;
         mSupportsStylusHandwriting = supportsStylusHandwriting;
         mStylusHandwritingSettingsActivityAttr = stylusHandwritingSettingsActivityAttr;
@@ -635,6 +653,16 @@
     }
 
     /**
+     * Returns true if IME supports only virtual devices.
+     * @hide
+     */
+    @FlaggedApi(android.companion.virtual.flags.Flags.FLAG_VDM_CUSTOM_IME)
+    @SystemApi
+    public boolean isVirtualDeviceOnly() {
+        return mIsVirtualDeviceOnly;
+    }
+
+    /**
      * Return the count of the subtypes of Input Method.
      */
     public int getSubtypeCount() {
@@ -732,6 +760,7 @@
         pw.println(prefix + "mId=" + mId
                 + " mSettingsActivityName=" + mSettingsActivityName
                 + " mIsVrOnly=" + mIsVrOnly
+                + " mIsVirtualDeviceOnly=" + mIsVirtualDeviceOnly
                 + " mSupportsSwitchingToNextInputMethod=" + mSupportsSwitchingToNextInputMethod
                 + " mInlineSuggestionsEnabled=" + mInlineSuggestionsEnabled
                 + " mSupportsInlineSuggestionsWithTouchExploration="
@@ -851,6 +880,7 @@
         dest.writeBoolean(mSuppressesSpellChecker);
         dest.writeBoolean(mShowInInputMethodPicker);
         dest.writeBoolean(mIsVrOnly);
+        dest.writeBoolean(mIsVirtualDeviceOnly);
         mService.writeToParcel(dest, flags);
         mSubtypes.writeToParcel(dest);
         dest.writeInt(mHandledConfigChanges);
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index da31348..8ad10af 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import static android.appwidget.flags.Flags.remoteAdapterConversion;
 import static android.view.inputmethod.Flags.FLAG_HOME_SCREEN_HANDWRITING_DELEGATOR;
 
 import android.annotation.AttrRes;
@@ -36,7 +37,6 @@
 import android.app.Activity;
 import android.app.ActivityOptions;
 import android.app.ActivityThread;
-import android.app.AppGlobals;
 import android.app.Application;
 import android.app.LoadedApk;
 import android.app.PendingIntent;
@@ -108,7 +108,6 @@
 import android.widget.CompoundButton.OnCheckedChangeListener;
 
 import com.android.internal.R;
-import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
 import com.android.internal.util.Preconditions;
 import com.android.internal.widget.IRemoteViewsFactory;
 
@@ -4950,21 +4949,11 @@
      */
     @Deprecated
     public void setRemoteAdapter(@IdRes int viewId, Intent intent) {
-        if (isAdapterConversionEnabled()) {
+        if (remoteAdapterConversion()) {
             addAction(new SetRemoteCollectionItemListAdapterAction(viewId, intent));
-            return;
+        } else {
+            addAction(new SetRemoteViewsAdapterIntent(viewId, intent));
         }
-        addAction(new SetRemoteViewsAdapterIntent(viewId, intent));
-    }
-
-    /**
-     * @hide
-     * @return True if the remote adapter conversion is enabled
-     */
-    public static boolean isAdapterConversionEnabled() {
-        return AppGlobals.getIntCoreSetting(
-                SystemUiDeviceConfigFlags.REMOTEVIEWS_ADAPTER_CONVERSION,
-                SystemUiDeviceConfigFlags.REMOTEVIEWS_ADAPTER_CONVERSION_DEFAULT ? 1 : 0) != 0;
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsLottieViewWrapper.kt b/core/java/android/window/ITrustedPresentationListener.aidl
similarity index 66%
copy from packages/SystemUI/src/com/android/systemui/biometrics/SideFpsLottieViewWrapper.kt
copy to core/java/android/window/ITrustedPresentationListener.aidl
index e98f6db..b33128a 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsLottieViewWrapper.kt
+++ b/core/java/android/window/ITrustedPresentationListener.aidl
@@ -13,12 +13,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.systemui.biometrics
 
-import android.content.Context
-import android.util.AttributeSet
-import com.android.systemui.util.wrapper.LottieViewWrapper
+package android.window;
 
-class SideFpsLottieViewWrapper
-@JvmOverloads
-constructor(context: Context, attrs: AttributeSet? = null) : LottieViewWrapper(context, attrs)
+/**
+ * @hide
+ */
+oneway interface ITrustedPresentationListener {
+    void onTrustedPresentationChanged(in int[] enteredTrustedStateIds, in int[] exitedTrustedStateIds);
+}
\ No newline at end of file
diff --git a/packages/overlays/NavigationBarModeGesturalOverlay/res/values-sw600dp/config.xml b/core/java/android/window/TrustedPresentationListener.java
similarity index 60%
rename from packages/overlays/NavigationBarModeGesturalOverlay/res/values-sw600dp/config.xml
rename to core/java/android/window/TrustedPresentationListener.java
index be1f081..02fd6d9 100644
--- a/packages/overlays/NavigationBarModeGesturalOverlay/res/values-sw600dp/config.xml
+++ b/core/java/android/window/TrustedPresentationListener.java
@@ -1,13 +1,11 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * Copyright (c) 2023, The Android Open Source Project
+/*
+ * 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
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -15,8 +13,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
--->
-<resources>
-    <!-- If true, attach the navigation bar to the app during app transition -->
-    <bool name="config_attachNavBarToAppDuringTransition">false</bool>
-</resources>
+
+package android.window;
+
+/**
+ * @hide
+ */
+public interface TrustedPresentationListener {
+
+    void onTrustedPresentationChanged(boolean inTrustedPresentationState);
+
+}
diff --git a/core/java/android/window/TrustedPresentationThresholds.aidl b/core/java/android/window/TrustedPresentationThresholds.aidl
new file mode 100644
index 0000000..d7088bf
--- /dev/null
+++ b/core/java/android/window/TrustedPresentationThresholds.aidl
@@ -0,0 +1,3 @@
+package android.window;
+
+parcelable TrustedPresentationThresholds;
diff --git a/core/java/android/window/TrustedPresentationThresholds.java b/core/java/android/window/TrustedPresentationThresholds.java
new file mode 100644
index 0000000..90f8834
--- /dev/null
+++ b/core/java/android/window/TrustedPresentationThresholds.java
@@ -0,0 +1,144 @@
+/*
+ * 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.window;
+
+import android.annotation.FlaggedApi;
+import android.annotation.FloatRange;
+import android.annotation.IntRange;
+import android.annotation.SuppressLint;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.view.SurfaceControl;
+
+import androidx.annotation.NonNull;
+
+import com.android.window.flags.Flags;
+
+/**
+ * Threshold values that are sent with
+ * {@link android.view.WindowManager#registerTrustedPresentationListener(IBinder,
+ * TrustedPresentationThresholds, Executor, Consumer)}
+ */
+@FlaggedApi(Flags.FLAG_TRUSTED_PRESENTATION_LISTENER_FOR_WINDOW)
+public final class TrustedPresentationThresholds implements Parcelable {
+    /**
+     * The min alpha the {@link SurfaceControl} is required to have to be considered inside the
+     * threshold.
+     */
+    @FloatRange(from = 0f, fromInclusive = false, to = 1f)
+    @FlaggedApi(Flags.FLAG_TRUSTED_PRESENTATION_LISTENER_FOR_WINDOW)
+    @SuppressLint("InternalField") // simple data class
+    public final float minAlpha;
+
+    /**
+     * The min fraction of the SurfaceControl that was presented to the user to be considered
+     * inside the threshold.
+     */
+    @FloatRange(from = 0f, fromInclusive = false, to = 1f)
+    @FlaggedApi(Flags.FLAG_TRUSTED_PRESENTATION_LISTENER_FOR_WINDOW)
+    @SuppressLint("InternalField") // simple data class
+    public final float minFractionRendered;
+
+    /**
+     * The time in milliseconds required for the {@link SurfaceControl} to be in the threshold.
+     */
+    @IntRange(from = 1)
+    @FlaggedApi(Flags.FLAG_TRUSTED_PRESENTATION_LISTENER_FOR_WINDOW)
+    @SuppressLint("InternalField") // simple data class
+    public final int stabilityRequirementMs;
+
+    private void checkValid() {
+        if (minAlpha <= 0 || minFractionRendered <= 0 || stabilityRequirementMs < 1) {
+            throw new IllegalArgumentException(
+                    "TrustedPresentationThresholds values are invalid");
+        }
+    }
+
+    /**
+     * Creates a new TrustedPresentationThresholds.
+     *
+     * @param minAlpha               The min alpha the {@link SurfaceControl} is required to
+     *                               have to be considered inside the
+     *                               threshold.
+     * @param minFractionRendered    The min fraction of the SurfaceControl that was presented
+     *                               to the user to be considered
+     *                               inside the threshold.
+     * @param stabilityRequirementMs The time in milliseconds required for the
+     *                               {@link SurfaceControl} to be in the threshold.
+     */
+    @FlaggedApi(Flags.FLAG_TRUSTED_PRESENTATION_LISTENER_FOR_WINDOW)
+    public TrustedPresentationThresholds(
+            @FloatRange(from = 0f, fromInclusive = false, to = 1f) float minAlpha,
+            @FloatRange(from = 0f, fromInclusive = false, to = 1f) float minFractionRendered,
+            @IntRange(from = 1) int stabilityRequirementMs) {
+        this.minAlpha = minAlpha;
+        this.minFractionRendered = minFractionRendered;
+        this.stabilityRequirementMs = stabilityRequirementMs;
+        checkValid();
+    }
+
+    @Override
+    @FlaggedApi(Flags.FLAG_TRUSTED_PRESENTATION_LISTENER_FOR_WINDOW)
+    public String toString() {
+        return "TrustedPresentationThresholds { "
+                + "minAlpha = " + minAlpha + ", "
+                + "minFractionRendered = " + minFractionRendered + ", "
+                + "stabilityRequirementMs = " + stabilityRequirementMs
+                + " }";
+    }
+
+    @Override
+    @FlaggedApi(Flags.FLAG_TRUSTED_PRESENTATION_LISTENER_FOR_WINDOW)
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeFloat(minAlpha);
+        dest.writeFloat(minFractionRendered);
+        dest.writeInt(stabilityRequirementMs);
+    }
+
+    @Override
+    @FlaggedApi(Flags.FLAG_TRUSTED_PRESENTATION_LISTENER_FOR_WINDOW)
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * @hide
+     */
+    TrustedPresentationThresholds(@NonNull Parcel in) {
+        minAlpha = in.readFloat();
+        minFractionRendered = in.readFloat();
+        stabilityRequirementMs = in.readInt();
+
+        checkValid();
+    }
+
+    @FlaggedApi(Flags.FLAG_TRUSTED_PRESENTATION_LISTENER_FOR_WINDOW)
+    public static final @NonNull Creator<TrustedPresentationThresholds> CREATOR =
+            new Creator<TrustedPresentationThresholds>() {
+                @Override
+                @FlaggedApi(Flags.FLAG_TRUSTED_PRESENTATION_LISTENER_FOR_WINDOW)
+                public TrustedPresentationThresholds[] newArray(int size) {
+                    return new TrustedPresentationThresholds[size];
+                }
+
+                @Override
+                @FlaggedApi(Flags.FLAG_TRUSTED_PRESENTATION_LISTENER_FOR_WINDOW)
+                public TrustedPresentationThresholds createFromParcel(@NonNull Parcel in) {
+                    return new TrustedPresentationThresholds(in);
+                }
+            };
+}
diff --git a/core/java/android/window/WindowOnBackInvokedDispatcher.java b/core/java/android/window/WindowOnBackInvokedDispatcher.java
index 3d4bc2f..6a8ca33 100644
--- a/core/java/android/window/WindowOnBackInvokedDispatcher.java
+++ b/core/java/android/window/WindowOnBackInvokedDispatcher.java
@@ -41,6 +41,7 @@
 import java.util.HashMap;
 import java.util.Objects;
 import java.util.TreeMap;
+import java.util.function.Supplier;
 
 /**
  * Provides window based implementation of {@link OnBackInvokedDispatcher}.
@@ -271,7 +272,7 @@
      * Returns false if the legacy back behavior should be used.
      */
     public boolean isOnBackInvokedCallbackEnabled() {
-        return Checker.isOnBackInvokedCallbackEnabled(mChecker.getContext());
+        return isOnBackInvokedCallbackEnabled(mChecker.getContext());
     }
 
     /**
@@ -394,7 +395,18 @@
      * {@link OnBackInvokedCallback}.
      */
     public static boolean isOnBackInvokedCallbackEnabled(@NonNull Context context) {
-        return Checker.isOnBackInvokedCallbackEnabled(context);
+        final Context originalContext = context;
+        while ((context instanceof ContextWrapper) && !(context instanceof Activity)) {
+            context = ((ContextWrapper) context).getBaseContext();
+        }
+        final ActivityInfo activityInfo = (context instanceof Activity)
+                ? ((Activity) context).getActivityInfo() : null;
+        final ApplicationInfo applicationInfo = context.getApplicationInfo();
+
+        return WindowOnBackInvokedDispatcher
+                .isOnBackInvokedCallbackEnabled(activityInfo, applicationInfo,
+                        () -> originalContext.obtainStyledAttributes(
+                                new int[] {android.R.attr.windowSwipeToDismiss}), true);
     }
 
     @Override
@@ -426,7 +438,7 @@
          */
         public boolean checkApplicationCallbackRegistration(int priority,
                 OnBackInvokedCallback callback) {
-            if (!isOnBackInvokedCallbackEnabled(getContext())
+            if (!WindowOnBackInvokedDispatcher.isOnBackInvokedCallbackEnabled(getContext())
                     && !(callback instanceof CompatOnBackInvokedCallback)) {
                 Log.w(TAG,
                         "OnBackInvokedCallback is not enabled for the application."
@@ -445,97 +457,76 @@
         private Context getContext() {
             return mContext.get();
         }
+    }
 
-        private static boolean isOnBackInvokedCallbackEnabled(@Nullable Context context) {
-            // new back is enabled if the feature flag is enabled AND the app does not explicitly
-            // request legacy back.
-            boolean featureFlagEnabled = ENABLE_PREDICTIVE_BACK;
-            if (!featureFlagEnabled) {
-                return false;
+    /**
+     * @hide
+     */
+    public static boolean isOnBackInvokedCallbackEnabled(@Nullable ActivityInfo activityInfo,
+            @NonNull ApplicationInfo applicationInfo,
+            @NonNull Supplier<TypedArray> windowAttrSupplier, boolean recycleTypedArray) {
+        // new back is enabled if the feature flag is enabled AND the app does not explicitly
+        // request legacy back.
+        if (!ENABLE_PREDICTIVE_BACK) {
+            return false;
+        }
+
+        if (ALWAYS_ENFORCE_PREDICTIVE_BACK) {
+            return true;
+        }
+
+        boolean requestsPredictiveBack;
+        // Activity
+        if (activityInfo != null && activityInfo.hasOnBackInvokedCallbackEnabled()) {
+            requestsPredictiveBack = activityInfo.isOnBackInvokedCallbackEnabled();
+            if (DEBUG) {
+                Log.d(TAG, TextUtils.formatSimple(
+                        "Activity: %s isPredictiveBackEnabled=%s",
+                        activityInfo.getComponentName(),
+                        requestsPredictiveBack));
             }
-
-            if (ALWAYS_ENFORCE_PREDICTIVE_BACK) {
-                return true;
-            }
-
-            // If the context is null, return false to use legacy back.
-            if (context == null) {
-                Log.w(TAG, "OnBackInvokedCallback is not enabled because context is null.");
-                return false;
-            }
-
-            boolean requestsPredictiveBack = false;
-
-            // Check if the context is from an activity.
-            Context originalContext = context;
-            while ((context instanceof ContextWrapper) && !(context instanceof Activity)) {
-                context = ((ContextWrapper) context).getBaseContext();
-            }
-
-            boolean shouldCheckActivity = false;
-
-            if (context instanceof Activity) {
-                final Activity activity = (Activity) context;
-
-                final ActivityInfo activityInfo = activity.getActivityInfo();
-                if (activityInfo != null) {
-                    if (activityInfo.hasOnBackInvokedCallbackEnabled()) {
-                        shouldCheckActivity = true;
-                        requestsPredictiveBack = activityInfo.isOnBackInvokedCallbackEnabled();
-
-                        if (DEBUG) {
-                            Log.d(TAG, TextUtils.formatSimple(
-                                    "Activity: %s isPredictiveBackEnabled=%s",
-                                    activity.getComponentName(),
-                                    requestsPredictiveBack));
-                        }
-                    }
-                } else {
-                    Log.w(TAG, "The ActivityInfo is null, so we cannot verify if this Activity"
-                            + " has the 'android:enableOnBackInvokedCallback' attribute."
-                            + " The application attribute will be used as a fallback.");
-                }
-            }
-
-            if (!shouldCheckActivity) {
-                final ApplicationInfo applicationInfo = context.getApplicationInfo();
-                requestsPredictiveBack = applicationInfo.isOnBackInvokedCallbackEnabled();
-
-                if (DEBUG) {
-                    Log.d(TAG, TextUtils.formatSimple("App: %s requestsPredictiveBack=%s",
-                            applicationInfo.packageName,
-                            requestsPredictiveBack));
-                }
-
-                if (PREDICTIVE_BACK_FALLBACK_WINDOW_ATTRIBUTE && !requestsPredictiveBack) {
-                    // Compatibility check for legacy window style flag used by Wear OS.
-                    // Note on compatibility behavior:
-                    // 1. windowSwipeToDismiss should be respected for all apps not opted in.
-                    // 2. windowSwipeToDismiss should be true for all apps not opted in, which
-                    //    enables the PB animation for them.
-                    // 3. windowSwipeToDismiss=false should be respected for apps not opted in,
-                    //    which disables PB & onBackPressed caused by BackAnimController's
-                    //    setTrigger(true)
-                    // Use the original context to resolve the styled attribute so that they stay
-                    // true to the window.
-                    TypedArray windowAttr =
-                            originalContext.obtainStyledAttributes(
-                                    new int[] {android.R.attr.windowSwipeToDismiss});
-                    boolean windowSwipeToDismiss = true;
-                    if (windowAttr.getIndexCount() > 0) {
-                        windowSwipeToDismiss = windowAttr.getBoolean(0, true);
-                    }
-                    windowAttr.recycle();
-
-                    if (DEBUG) {
-                        Log.i(TAG, "falling back to windowSwipeToDismiss: " + windowSwipeToDismiss);
-                    }
-
-                    requestsPredictiveBack = windowSwipeToDismiss;
-                }
-            }
-
             return requestsPredictiveBack;
         }
+
+        // Application
+        requestsPredictiveBack = applicationInfo.isOnBackInvokedCallbackEnabled();
+        if (DEBUG) {
+            Log.d(TAG, TextUtils.formatSimple("App: %s requestsPredictiveBack=%s",
+                    applicationInfo.packageName,
+                    requestsPredictiveBack));
+        }
+        if (requestsPredictiveBack) {
+            return true;
+        }
+
+        if (PREDICTIVE_BACK_FALLBACK_WINDOW_ATTRIBUTE) {
+            // Compatibility check for legacy window style flag used by Wear OS.
+            // Note on compatibility behavior:
+            // 1. windowSwipeToDismiss should be respected for all apps not opted in.
+            // 2. windowSwipeToDismiss should be true for all apps not opted in, which
+            //    enables the PB animation for them.
+            // 3. windowSwipeToDismiss=false should be respected for apps not opted in,
+            //    which disables PB & onBackPressed caused by BackAnimController's
+            //    setTrigger(true)
+            // Use the original context to resolve the styled attribute so that they stay
+            // true to the window.
+            TypedArray windowAttr = windowAttrSupplier.get();
+            boolean windowSwipeToDismiss = true;
+            if (windowAttr != null) {
+                if (windowAttr.getIndexCount() > 0) {
+                    windowSwipeToDismiss = windowAttr.getBoolean(0, true);
+                }
+                if (recycleTypedArray) {
+                    windowAttr.recycle();
+                }
+            }
+
+            if (DEBUG) {
+                Log.i(TAG, "falling back to windowSwipeToDismiss: " + windowSwipeToDismiss);
+            }
+
+            requestsPredictiveBack = windowSwipeToDismiss;
+        }
+        return requestsPredictiveBack;
     }
 }
diff --git a/core/java/android/window/flags/accessibility.aconfig b/core/java/android/window/flags/accessibility.aconfig
new file mode 100644
index 0000000..d467be6
--- /dev/null
+++ b/core/java/android/window/flags/accessibility.aconfig
@@ -0,0 +1,8 @@
+package: "com.android.window.flags"
+
+flag {
+  name: "do_not_check_intersection_when_non_magnifiable_window_transitions"
+  namespace: "accessibility"
+  description: "The flag controls whether the intersection check for non-magnifiable windows is needed when onWindowTransition,"
+  bug: "312624253"
+}
\ No newline at end of file
diff --git a/core/java/android/window/flags/responsible_apis.aconfig b/core/java/android/window/flags/responsible_apis.aconfig
index f828cff..ad0e9a4 100644
--- a/core/java/android/window/flags/responsible_apis.aconfig
+++ b/core/java/android/window/flags/responsible_apis.aconfig
@@ -41,3 +41,10 @@
     description: "Prevent a task to restart based on a visible window during task switch."
     bug: "171459802"
 }
+
+flag {
+    name: "bal_respect_app_switch_state_when_check_bound_by_foreground_uid"
+    namespace: "responsible_apis"
+    description: "Prevent BAL based on it is bound by foreground Uid but the app switch is stopped."
+    bug: "171459802"
+}
diff --git a/core/java/android/window/flags/window_surfaces.aconfig b/core/java/android/window/flags/window_surfaces.aconfig
index 29932f3..56df493 100644
--- a/core/java/android/window/flags/window_surfaces.aconfig
+++ b/core/java/android/window/flags/window_surfaces.aconfig
@@ -56,3 +56,11 @@
     is_fixed_read_only: true
     bug: "308662081"
 }
+
+flag {
+    namespace: "window_surfaces"
+    name: "trusted_presentation_listener_for_window"
+    description: "Enable trustedPresentationListener on windows public API"
+    is_fixed_read_only: true
+    bug: "278027319"
+}
\ 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 31a3ebd..07beb11 100644
--- a/core/java/android/window/flags/windowing_frontend.aconfig
+++ b/core/java/android/window/flags/windowing_frontend.aconfig
@@ -16,7 +16,7 @@
 
 flag {
     name: "defer_display_updates"
-    namespace: "window_manager"
+    namespace: "windowing_frontend"
     description: "Feature flag for deferring DisplayManager updates to WindowManager if Shell transition is running"
     bug: "259220649"
     is_fixed_read_only: true
@@ -44,11 +44,18 @@
   bug: "294925498"
 }
 
-
 flag {
     name: "wallpaper_offset_async"
     namespace: "windowing_frontend"
     description: "Do not synchronise the wallpaper offset"
     bug: "293248754"
     is_fixed_read_only: true
+}
+
+flag {
+    name: "predictive_back_system_animations"
+    namespace: "systemui"
+    description: "Predictive back for system animations"
+    bug: "309545085"
+    is_fixed_read_only: true
 }
\ No newline at end of file
diff --git a/core/java/com/android/internal/accessibility/dialog/AccessibilityShortcutChooserActivity.java b/core/java/com/android/internal/accessibility/dialog/AccessibilityShortcutChooserActivity.java
index 7d06e3f..2e80b7e 100644
--- a/core/java/com/android/internal/accessibility/dialog/AccessibilityShortcutChooserActivity.java
+++ b/core/java/com/android/internal/accessibility/dialog/AccessibilityShortcutChooserActivity.java
@@ -262,6 +262,11 @@
         return mMenuDialog;
     }
 
+    @VisibleForTesting
+    public Dialog getPermissionDialog() {
+        return mPermissionDialog;
+    }
+
     private AlertDialog createMenuDialog() {
         final String dialogTitle =
                 getString(R.string.accessibility_select_shortcut_menu_title);
diff --git a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
index 82ee8fc..e92c6a6 100644
--- a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
+++ b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
@@ -397,5 +397,5 @@
       * sandboxed detection (from trusted process).
       */
       @EnforcePermission("MANAGE_HOTWORD_DETECTION")
-      void setIsReceiveSandboxedTrainingDataAllowed(boolean allowed);
+      void setShouldReceiveSandboxedTrainingData(boolean allowed);
 }
diff --git a/core/java/com/android/internal/app/SuspendedAppActivity.java b/core/java/com/android/internal/app/SuspendedAppActivity.java
index 1e0b2a0..efc1455 100644
--- a/core/java/com/android/internal/app/SuspendedAppActivity.java
+++ b/core/java/com/android/internal/app/SuspendedAppActivity.java
@@ -80,7 +80,8 @@
                 // Suspension conditions were modified, dismiss any related visible dialogs.
                 final String[] modified = intent.getStringArrayExtra(
                         Intent.EXTRA_CHANGED_PACKAGE_LIST);
-                if (ArrayUtils.contains(modified, mSuspendedPackage)) {
+                if (ArrayUtils.contains(modified, mSuspendedPackage)
+                        && !isPackageSuspended(mSuspendedPackage)) {
                     if (!isFinishing()) {
                         Slog.w(TAG, "Package " + mSuspendedPackage + " has modified"
                                 + " suspension conditions while dialog was visible. Finishing.");
@@ -92,6 +93,15 @@
         }
     };
 
+    private boolean isPackageSuspended(String packageName) {
+        try {
+            return mPm.isPackageSuspended(packageName);
+        } catch (PackageManager.NameNotFoundException ne) {
+            Slog.e(TAG, "Package " + packageName + " not found", ne);
+        }
+        return false;
+    }
+
     private CharSequence getAppLabel(String packageName) {
         try {
             return mPm.getApplicationInfoAsUser(packageName, 0, mUserId).loadLabel(mPm);
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index e494346..bd806bf 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -519,24 +519,6 @@
     public static final String TASK_MANAGER_SHOW_FOOTER_DOT = "task_manager_show_footer_dot";
 
     /**
-     * (boolean) Whether to enable the adapter conversion in RemoteViews
-     */
-    public static final String REMOTEVIEWS_ADAPTER_CONVERSION =
-            "CursorControlFeature__remoteviews_adapter_conversion";
-
-    /**
-     * The key name used in app core settings for {@link #REMOTEVIEWS_ADAPTER_CONVERSION}
-     */
-    public static final String KEY_REMOTEVIEWS_ADAPTER_CONVERSION =
-            "systemui__remoteviews_adapter_conversion";
-
-    /**
-     * Default value for whether the adapter conversion is enabled or not. This is set for
-     * RemoteViews and should not be a common practice.
-     */
-    public static final boolean REMOTEVIEWS_ADAPTER_CONVERSION_DEFAULT = false;
-
-    /**
      * (boolean) Whether the task manager should show a stop button if the app is allowlisted
      * by the user.
      */
diff --git a/core/java/com/android/internal/content/PackageMonitor.java b/core/java/com/android/internal/content/PackageMonitor.java
index d85227f..c89cfc4 100644
--- a/core/java/com/android/internal/content/PackageMonitor.java
+++ b/core/java/com/android/internal/content/PackageMonitor.java
@@ -199,6 +199,11 @@
     public void onPackageChangedWithExtras(String packageName, Bundle extras) {
     }
 
+    public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit,
+            Bundle extras) {
+        return onHandleForceStop(intent, packages, uid, doit);
+    }
+
     public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
         return false;
     }
@@ -254,6 +259,15 @@
     public void onPackageModified(@NonNull String packageName) {
     }
 
+    /**
+     * Called when a package in the stopped state is started for some reason.
+     *
+     * @param packageName Name of the package that was unstopped
+     * @param uid UID of the package that was unstopped
+     */
+    public void onPackageUnstopped(String packageName, int uid, Bundle extras) {
+    }
+
     public boolean didSomePackagesChange() {
         return mSomePackagesChanged;
     }
@@ -444,13 +458,13 @@
             mChangeType = PACKAGE_TEMPORARY_CHANGE;
             boolean canRestart = onHandleForceStop(intent,
                     mDisappearingPackages,
-                    intent.getIntExtra(Intent.EXTRA_UID, 0), false);
+                    intent.getIntExtra(Intent.EXTRA_UID, 0), false, intent.getExtras());
             if (canRestart) setResultCode(Activity.RESULT_OK);
         } else if (Intent.ACTION_PACKAGE_RESTARTED.equals(action)) {
             mDisappearingPackages = new String[] {getPackageName(intent)};
             mChangeType = PACKAGE_TEMPORARY_CHANGE;
             onHandleForceStop(intent, mDisappearingPackages,
-                    intent.getIntExtra(Intent.EXTRA_UID, 0), true);
+                    intent.getIntExtra(Intent.EXTRA_UID, 0), true, intent.getExtras());
         } else if (Intent.ACTION_UID_REMOVED.equals(action)) {
             onUidRemoved(intent.getIntExtra(Intent.EXTRA_UID, 0));
         } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
@@ -485,6 +499,12 @@
             String[] pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
             mSomePackagesChanged = true;
             onPackagesUnsuspended(pkgList);
+        } else if (Intent.ACTION_PACKAGE_UNSTOPPED.equals(action)) {
+            final String pkgName = getPackageName(intent);
+            mAppearingPackages = new String[] {pkgName};
+            mChangeType = PACKAGE_TEMPORARY_CHANGE;
+            onPackageUnstopped(pkgName, intent.getIntExtra(Intent.EXTRA_UID, 0),
+                    intent.getExtras());
         }
 
         if (mSomePackagesChanged) {
diff --git a/core/java/com/android/internal/jank/Cuj.java b/core/java/com/android/internal/jank/Cuj.java
new file mode 100644
index 0000000..96740c5
--- /dev/null
+++ b/core/java/com/android/internal/jank/Cuj.java
@@ -0,0 +1,510 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.jank;
+
+import android.annotation.IntDef;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.FrameworkStatsLog;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+
+/** @hide */
+public class Cuj {
+    @VisibleForTesting
+    public static final int MAX_LENGTH_OF_CUJ_NAME = 80;
+
+    // Every value must have a corresponding entry in CUJ_STATSD_INTERACTION_TYPE.
+    public static final int CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE = 0;
+    public static final int CUJ_NOTIFICATION_SHADE_SCROLL_FLING = 2;
+    public static final int CUJ_NOTIFICATION_SHADE_ROW_EXPAND = 3;
+    public static final int CUJ_NOTIFICATION_SHADE_ROW_SWIPE = 4;
+    public static final int CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE = 5;
+    public static final int CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE = 6;
+    public static final int CUJ_LAUNCHER_APP_LAUNCH_FROM_RECENTS = 7;
+    public static final int CUJ_LAUNCHER_APP_LAUNCH_FROM_ICON = 8;
+    public static final int CUJ_LAUNCHER_APP_CLOSE_TO_HOME = 9;
+    public static final int CUJ_LAUNCHER_APP_CLOSE_TO_PIP = 10;
+    public static final int CUJ_LAUNCHER_QUICK_SWITCH = 11;
+    public static final int CUJ_NOTIFICATION_HEADS_UP_APPEAR = 12;
+    public static final int CUJ_NOTIFICATION_HEADS_UP_DISAPPEAR = 13;
+    public static final int CUJ_NOTIFICATION_ADD = 14;
+    public static final int CUJ_NOTIFICATION_REMOVE = 15;
+    public static final int CUJ_NOTIFICATION_APP_START = 16;
+    public static final int CUJ_LOCKSCREEN_PASSWORD_APPEAR = 17;
+    public static final int CUJ_LOCKSCREEN_PATTERN_APPEAR = 18;
+    public static final int CUJ_LOCKSCREEN_PIN_APPEAR = 19;
+    public static final int CUJ_LOCKSCREEN_PASSWORD_DISAPPEAR = 20;
+    public static final int CUJ_LOCKSCREEN_PATTERN_DISAPPEAR = 21;
+    public static final int CUJ_LOCKSCREEN_PIN_DISAPPEAR = 22;
+    public static final int CUJ_LOCKSCREEN_TRANSITION_FROM_AOD = 23;
+    public static final int CUJ_LOCKSCREEN_TRANSITION_TO_AOD = 24;
+    public static final int CUJ_LAUNCHER_OPEN_ALL_APPS = 25;
+    public static final int CUJ_LAUNCHER_ALL_APPS_SCROLL = 26;
+    public static final int CUJ_LAUNCHER_APP_LAUNCH_FROM_WIDGET = 27;
+    public static final int CUJ_SETTINGS_PAGE_SCROLL = 28;
+    public static final int CUJ_LOCKSCREEN_UNLOCK_ANIMATION = 29;
+    public static final int CUJ_SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON = 30;
+    public static final int CUJ_SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER = 31;
+    public static final int CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE = 32;
+    public static final int CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON = 33;
+    public static final int CUJ_STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP = 34;
+    public static final int CUJ_PIP_TRANSITION = 35;
+    public static final int CUJ_WALLPAPER_TRANSITION = 36;
+    public static final int CUJ_USER_SWITCH = 37;
+    public static final int CUJ_SPLASHSCREEN_AVD = 38;
+    public static final int CUJ_SPLASHSCREEN_EXIT_ANIM = 39;
+    public static final int CUJ_SCREEN_OFF = 40;
+    public static final int CUJ_SCREEN_OFF_SHOW_AOD = 41;
+    public static final int CUJ_ONE_HANDED_ENTER_TRANSITION = 42;
+    public static final int CUJ_ONE_HANDED_EXIT_TRANSITION = 43;
+    public static final int CUJ_UNFOLD_ANIM = 44;
+    public static final int CUJ_SUW_LOADING_TO_SHOW_INFO_WITH_ACTIONS = 45;
+    public static final int CUJ_SUW_SHOW_FUNCTION_SCREEN_WITH_ACTIONS = 46;
+    public static final int CUJ_SUW_LOADING_TO_NEXT_FLOW = 47;
+    public static final int CUJ_SUW_LOADING_SCREEN_FOR_STATUS = 48;
+    public static final int CUJ_SPLIT_SCREEN_ENTER = 49;
+    public static final int CUJ_SPLIT_SCREEN_EXIT = 50;
+    public static final int CUJ_LOCKSCREEN_LAUNCH_CAMERA = 51; // reserved.
+    public static final int CUJ_SPLIT_SCREEN_RESIZE = 52;
+    public static final int CUJ_SETTINGS_SLIDER = 53;
+    public static final int CUJ_TAKE_SCREENSHOT = 54;
+    public static final int CUJ_VOLUME_CONTROL = 55;
+    public static final int CUJ_BIOMETRIC_PROMPT_TRANSITION = 56;
+    public static final int CUJ_SETTINGS_TOGGLE = 57;
+    public static final int CUJ_SHADE_DIALOG_OPEN = 58;
+    public static final int CUJ_USER_DIALOG_OPEN = 59;
+    public static final int CUJ_TASKBAR_EXPAND = 60;
+    public static final int CUJ_TASKBAR_COLLAPSE = 61;
+    public static final int CUJ_SHADE_CLEAR_ALL = 62;
+    public static final int CUJ_LAUNCHER_UNLOCK_ENTRANCE_ANIMATION = 63;
+    public static final int CUJ_LOCKSCREEN_OCCLUSION = 64;
+    public static final int CUJ_RECENTS_SCROLLING = 65;
+    public static final int CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS = 66;
+    public static final int CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE = 67;
+    public static final int CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME = 68;
+    public static final int CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION = 70;
+    public static final int CUJ_LAUNCHER_OPEN_SEARCH_RESULT = 71;
+    // 72 - 77 are reserved for b/281564325.
+
+    /**
+     * In some cases when we do not have any end-target, we play a simple slide-down animation.
+     * eg: Open an app from Overview/Task switcher such that there is no home-screen icon.
+     * eg: Exit the app using back gesture.
+     */
+    public static final int CUJ_LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK = 78;
+    // 79 is reserved.
+    public static final int CUJ_IME_INSETS_SHOW_ANIMATION = 80;
+    public static final int CUJ_IME_INSETS_HIDE_ANIMATION = 81;
+
+    public static final int CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER = 82;
+
+    public static final int CUJ_LAUNCHER_UNFOLD_ANIM = 83;
+
+    public static final int CUJ_PREDICTIVE_BACK_CROSS_ACTIVITY = 84;
+    public static final int CUJ_PREDICTIVE_BACK_CROSS_TASK = 85;
+    public static final int CUJ_PREDICTIVE_BACK_HOME = 86;
+    public static final int CUJ_LAUNCHER_SEARCH_QSB_OPEN = 87;
+
+    // When adding a CUJ, update this and make sure to also update CUJ_TO_STATSD_INTERACTION_TYPE.
+    @VisibleForTesting
+    static final int LAST_CUJ = CUJ_LAUNCHER_SEARCH_QSB_OPEN;
+
+    /** @hide */
+    @IntDef({
+            CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE,
+            CUJ_NOTIFICATION_SHADE_SCROLL_FLING,
+            CUJ_NOTIFICATION_SHADE_ROW_EXPAND,
+            CUJ_NOTIFICATION_SHADE_ROW_SWIPE,
+            CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE,
+            CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE,
+            CUJ_LAUNCHER_APP_LAUNCH_FROM_RECENTS,
+            CUJ_LAUNCHER_APP_LAUNCH_FROM_ICON,
+            CUJ_LAUNCHER_APP_CLOSE_TO_HOME,
+            CUJ_LAUNCHER_APP_CLOSE_TO_PIP,
+            CUJ_LAUNCHER_QUICK_SWITCH,
+            CUJ_NOTIFICATION_HEADS_UP_APPEAR,
+            CUJ_NOTIFICATION_HEADS_UP_DISAPPEAR,
+            CUJ_NOTIFICATION_ADD,
+            CUJ_NOTIFICATION_REMOVE,
+            CUJ_NOTIFICATION_APP_START,
+            CUJ_LOCKSCREEN_PASSWORD_APPEAR,
+            CUJ_LOCKSCREEN_PATTERN_APPEAR,
+            CUJ_LOCKSCREEN_PIN_APPEAR,
+            CUJ_LOCKSCREEN_PASSWORD_DISAPPEAR,
+            CUJ_LOCKSCREEN_PATTERN_DISAPPEAR,
+            CUJ_LOCKSCREEN_PIN_DISAPPEAR,
+            CUJ_LOCKSCREEN_TRANSITION_FROM_AOD,
+            CUJ_LOCKSCREEN_TRANSITION_TO_AOD,
+            CUJ_LAUNCHER_OPEN_ALL_APPS,
+            CUJ_LAUNCHER_ALL_APPS_SCROLL,
+            CUJ_LAUNCHER_APP_LAUNCH_FROM_WIDGET,
+            CUJ_SETTINGS_PAGE_SCROLL,
+            CUJ_LOCKSCREEN_UNLOCK_ANIMATION,
+            CUJ_SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON,
+            CUJ_SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER,
+            CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE,
+            CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON,
+            CUJ_STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP,
+            CUJ_PIP_TRANSITION,
+            CUJ_WALLPAPER_TRANSITION,
+            CUJ_USER_SWITCH,
+            CUJ_SPLASHSCREEN_AVD,
+            CUJ_SPLASHSCREEN_EXIT_ANIM,
+            CUJ_SCREEN_OFF,
+            CUJ_SCREEN_OFF_SHOW_AOD,
+            CUJ_ONE_HANDED_ENTER_TRANSITION,
+            CUJ_ONE_HANDED_EXIT_TRANSITION,
+            CUJ_UNFOLD_ANIM,
+            CUJ_SUW_LOADING_TO_SHOW_INFO_WITH_ACTIONS,
+            CUJ_SUW_SHOW_FUNCTION_SCREEN_WITH_ACTIONS,
+            CUJ_SUW_LOADING_TO_NEXT_FLOW,
+            CUJ_SUW_LOADING_SCREEN_FOR_STATUS,
+            CUJ_SPLIT_SCREEN_ENTER,
+            CUJ_SPLIT_SCREEN_EXIT,
+            CUJ_LOCKSCREEN_LAUNCH_CAMERA,
+            CUJ_SPLIT_SCREEN_RESIZE,
+            CUJ_SETTINGS_SLIDER,
+            CUJ_TAKE_SCREENSHOT,
+            CUJ_VOLUME_CONTROL,
+            CUJ_BIOMETRIC_PROMPT_TRANSITION,
+            CUJ_SETTINGS_TOGGLE,
+            CUJ_SHADE_DIALOG_OPEN,
+            CUJ_USER_DIALOG_OPEN,
+            CUJ_TASKBAR_EXPAND,
+            CUJ_TASKBAR_COLLAPSE,
+            CUJ_SHADE_CLEAR_ALL,
+            CUJ_LAUNCHER_UNLOCK_ENTRANCE_ANIMATION,
+            CUJ_LOCKSCREEN_OCCLUSION,
+            CUJ_RECENTS_SCROLLING,
+            CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS,
+            CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE,
+            CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME,
+            CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION,
+            CUJ_LAUNCHER_OPEN_SEARCH_RESULT,
+            CUJ_LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK,
+            CUJ_IME_INSETS_SHOW_ANIMATION,
+            CUJ_IME_INSETS_HIDE_ANIMATION,
+            CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER,
+            CUJ_LAUNCHER_UNFOLD_ANIM,
+            CUJ_PREDICTIVE_BACK_CROSS_ACTIVITY,
+            CUJ_PREDICTIVE_BACK_CROSS_TASK,
+            CUJ_PREDICTIVE_BACK_HOME,
+            CUJ_LAUNCHER_SEARCH_QSB_OPEN,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface CujType {
+    }
+
+    private static final int NO_STATSD_LOGGING = -1;
+
+    // Used to convert CujType to InteractionType enum value for statsd logging.
+    // Use NO_STATSD_LOGGING in case the measurement for a given CUJ should not be logged to statsd.
+    private static final int[] CUJ_TO_STATSD_INTERACTION_TYPE = new int[LAST_CUJ + 1];
+    static {
+        Arrays.fill(CUJ_TO_STATSD_INTERACTION_TYPE, NO_STATSD_LOGGING);
+
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__NOTIFICATION_SHADE_SWIPE;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_SCROLL_FLING] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_SCROLL_FLING;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_ROW_EXPAND] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_ROW_EXPAND;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_ROW_SWIPE] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_ROW_SWIPE;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_QS_EXPAND_COLLAPSE;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_QS_SCROLL_SWIPE;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_APP_LAUNCH_FROM_RECENTS] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_LAUNCH_FROM_RECENTS;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_APP_LAUNCH_FROM_ICON] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_LAUNCH_FROM_ICON;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_APP_CLOSE_TO_HOME] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_HOME;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_APP_CLOSE_TO_PIP] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_PIP;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_QUICK_SWITCH] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_QUICK_SWITCH;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_HEADS_UP_APPEAR] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_HEADS_UP_APPEAR;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_HEADS_UP_DISAPPEAR] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_HEADS_UP_DISAPPEAR;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_ADD] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_NOTIFICATION_ADD;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_REMOVE] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_NOTIFICATION_REMOVE;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_APP_START] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_PASSWORD_APPEAR] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PASSWORD_APPEAR;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_PATTERN_APPEAR] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PATTERN_APPEAR;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_PIN_APPEAR] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PIN_APPEAR;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_PASSWORD_DISAPPEAR] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PASSWORD_DISAPPEAR;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_PATTERN_DISAPPEAR] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PATTERN_DISAPPEAR;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_PIN_DISAPPEAR] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PIN_DISAPPEAR;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_TRANSITION_FROM_AOD] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_TRANSITION_FROM_AOD;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_TRANSITION_TO_AOD] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_TRANSITION_TO_AOD;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_OPEN_ALL_APPS] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_OPEN_ALL_APPS;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_ALL_APPS_SCROLL] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_ALL_APPS_SCROLL;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_APP_LAUNCH_FROM_WIDGET] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_LAUNCH_FROM_WIDGET;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SETTINGS_PAGE_SCROLL] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SETTINGS_PAGE_SCROLL;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_UNLOCK_ANIMATION] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_UNLOCK_ANIMATION;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH_FROM_QS_TILE;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_PIP_TRANSITION] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__PIP_TRANSITION;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_WALLPAPER_TRANSITION] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__WALLPAPER_TRANSITION;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_USER_SWITCH] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__USER_SWITCH;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SPLASHSCREEN_AVD] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLASHSCREEN_AVD;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SPLASHSCREEN_EXIT_ANIM] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLASHSCREEN_EXIT_ANIM;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SCREEN_OFF] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SCREEN_OFF;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SCREEN_OFF_SHOW_AOD] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SCREEN_OFF_SHOW_AOD;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_ONE_HANDED_ENTER_TRANSITION] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__ONE_HANDED_ENTER_TRANSITION;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_ONE_HANDED_EXIT_TRANSITION] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__ONE_HANDED_EXIT_TRANSITION;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_UNFOLD_ANIM] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__UNFOLD_ANIM;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SUW_LOADING_TO_SHOW_INFO_WITH_ACTIONS] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SUW_LOADING_TO_SHOW_INFO_WITH_ACTIONS;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SUW_SHOW_FUNCTION_SCREEN_WITH_ACTIONS] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SUW_SHOW_FUNCTION_SCREEN_WITH_ACTIONS;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SUW_LOADING_TO_NEXT_FLOW] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SUW_LOADING_TO_NEXT_FLOW;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SUW_LOADING_SCREEN_FOR_STATUS] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SUW_LOADING_SCREEN_FOR_STATUS;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SPLIT_SCREEN_ENTER] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_ENTER;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SPLIT_SCREEN_EXIT] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_EXIT;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_LAUNCH_CAMERA] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_LAUNCH_CAMERA;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SPLIT_SCREEN_RESIZE] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_RESIZE;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SETTINGS_SLIDER] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SETTINGS_SLIDER;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_TAKE_SCREENSHOT] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__TAKE_SCREENSHOT;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_VOLUME_CONTROL] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__VOLUME_CONTROL;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_BIOMETRIC_PROMPT_TRANSITION] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__BIOMETRIC_PROMPT_TRANSITION;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SETTINGS_TOGGLE] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SETTINGS_TOGGLE;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SHADE_DIALOG_OPEN] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_DIALOG_OPEN;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_USER_DIALOG_OPEN] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__USER_DIALOG_OPEN;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_TASKBAR_EXPAND] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__TASKBAR_EXPAND;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_TASKBAR_COLLAPSE] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__TASKBAR_COLLAPSE;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SHADE_CLEAR_ALL] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_CLEAR_ALL;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_UNLOCK_ENTRANCE_ANIMATION] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_UNLOCK_ENTRANCE_ANIMATION;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_OCCLUSION] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_OCCLUSION;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_RECENTS_SCROLLING] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__RECENTS_SCROLLING;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_SWIPE_TO_RECENTS;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_CLOSE_ALL_APPS_SWIPE;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_CLOSE_ALL_APPS_TO_HOME;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_CLOCK_MOVE_ANIMATION;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_OPEN_SEARCH_RESULT] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_OPEN_SEARCH_RESULT;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_IME_INSETS_SHOW_ANIMATION] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__IME_INSETS_SHOW_ANIMATION;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_IME_INSETS_HIDE_ANIMATION] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__IME_INSETS_HIDE_ANIMATION;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_DOUBLE_TAP_DIVIDER;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_UNFOLD_ANIM] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_UNFOLD_ANIM;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_PREDICTIVE_BACK_CROSS_ACTIVITY] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__PREDICTIVE_BACK_CROSS_ACTIVITY;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_PREDICTIVE_BACK_CROSS_TASK] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__PREDICTIVE_BACK_CROSS_TASK;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_PREDICTIVE_BACK_HOME] = FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__PREDICTIVE_BACK_HOME;
+        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_SEARCH_QSB_OPEN] =
+            FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_SEARCH_QSB_OPEN;
+    }
+
+    private Cuj() {
+    }
+
+    /**
+     * A helper method to translate CUJ type to CUJ name.
+     *
+     * @param cujType the cuj type defined in this file
+     * @return the name of the cuj type
+     */
+    public static String getNameOfCuj(int cujType) {
+        // Please note:
+        // 1. The length of the returned string shouldn't exceed MAX_LENGTH_OF_CUJ_NAME.
+        // 2. The returned string should be the same with the name defined in atoms.proto.
+        switch (cujType) {
+            case CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE:
+                return "NOTIFICATION_SHADE_EXPAND_COLLAPSE";
+            case CUJ_NOTIFICATION_SHADE_SCROLL_FLING:
+                return "NOTIFICATION_SHADE_SCROLL_FLING";
+            case CUJ_NOTIFICATION_SHADE_ROW_EXPAND:
+                return "NOTIFICATION_SHADE_ROW_EXPAND";
+            case CUJ_NOTIFICATION_SHADE_ROW_SWIPE:
+                return "NOTIFICATION_SHADE_ROW_SWIPE";
+            case CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE:
+                return "NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE";
+            case CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE:
+                return "NOTIFICATION_SHADE_QS_SCROLL_SWIPE";
+            case CUJ_LAUNCHER_APP_LAUNCH_FROM_RECENTS:
+                return "LAUNCHER_APP_LAUNCH_FROM_RECENTS";
+            case CUJ_LAUNCHER_APP_LAUNCH_FROM_ICON:
+                return "LAUNCHER_APP_LAUNCH_FROM_ICON";
+            case CUJ_LAUNCHER_APP_CLOSE_TO_HOME:
+                return "LAUNCHER_APP_CLOSE_TO_HOME";
+            case CUJ_LAUNCHER_APP_CLOSE_TO_PIP:
+                return "LAUNCHER_APP_CLOSE_TO_PIP";
+            case CUJ_LAUNCHER_QUICK_SWITCH:
+                return "LAUNCHER_QUICK_SWITCH";
+            case CUJ_NOTIFICATION_HEADS_UP_APPEAR:
+                return "NOTIFICATION_HEADS_UP_APPEAR";
+            case CUJ_NOTIFICATION_HEADS_UP_DISAPPEAR:
+                return "NOTIFICATION_HEADS_UP_DISAPPEAR";
+            case CUJ_NOTIFICATION_ADD:
+                return "NOTIFICATION_ADD";
+            case CUJ_NOTIFICATION_REMOVE:
+                return "NOTIFICATION_REMOVE";
+            case CUJ_NOTIFICATION_APP_START:
+                return "NOTIFICATION_APP_START";
+            case CUJ_LOCKSCREEN_PASSWORD_APPEAR:
+                return "LOCKSCREEN_PASSWORD_APPEAR";
+            case CUJ_LOCKSCREEN_PATTERN_APPEAR:
+                return "LOCKSCREEN_PATTERN_APPEAR";
+            case CUJ_LOCKSCREEN_PIN_APPEAR:
+                return "LOCKSCREEN_PIN_APPEAR";
+            case CUJ_LOCKSCREEN_PASSWORD_DISAPPEAR:
+                return "LOCKSCREEN_PASSWORD_DISAPPEAR";
+            case CUJ_LOCKSCREEN_PATTERN_DISAPPEAR:
+                return "LOCKSCREEN_PATTERN_DISAPPEAR";
+            case CUJ_LOCKSCREEN_PIN_DISAPPEAR:
+                return "LOCKSCREEN_PIN_DISAPPEAR";
+            case CUJ_LOCKSCREEN_TRANSITION_FROM_AOD:
+                return "LOCKSCREEN_TRANSITION_FROM_AOD";
+            case CUJ_LOCKSCREEN_TRANSITION_TO_AOD:
+                return "LOCKSCREEN_TRANSITION_TO_AOD";
+            case CUJ_LAUNCHER_OPEN_ALL_APPS :
+                return "LAUNCHER_OPEN_ALL_APPS";
+            case CUJ_LAUNCHER_ALL_APPS_SCROLL:
+                return "LAUNCHER_ALL_APPS_SCROLL";
+            case CUJ_LAUNCHER_APP_LAUNCH_FROM_WIDGET:
+                return "LAUNCHER_APP_LAUNCH_FROM_WIDGET";
+            case CUJ_SETTINGS_PAGE_SCROLL:
+                return "SETTINGS_PAGE_SCROLL";
+            case CUJ_LOCKSCREEN_UNLOCK_ANIMATION:
+                return "LOCKSCREEN_UNLOCK_ANIMATION";
+            case CUJ_SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON:
+                return "SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON";
+            case CUJ_SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER:
+                return "SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER";
+            case CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE:
+                return "SHADE_APP_LAUNCH_FROM_QS_TILE";
+            case CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON:
+                return "SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON";
+            case CUJ_STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP:
+                return "STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP";
+            case CUJ_PIP_TRANSITION:
+                return "PIP_TRANSITION";
+            case CUJ_WALLPAPER_TRANSITION:
+                return "WALLPAPER_TRANSITION";
+            case CUJ_USER_SWITCH:
+                return "USER_SWITCH";
+            case CUJ_SPLASHSCREEN_AVD:
+                return "SPLASHSCREEN_AVD";
+            case CUJ_SPLASHSCREEN_EXIT_ANIM:
+                return "SPLASHSCREEN_EXIT_ANIM";
+            case CUJ_SCREEN_OFF:
+                return "SCREEN_OFF";
+            case CUJ_SCREEN_OFF_SHOW_AOD:
+                return "SCREEN_OFF_SHOW_AOD";
+            case CUJ_ONE_HANDED_ENTER_TRANSITION:
+                return "ONE_HANDED_ENTER_TRANSITION";
+            case CUJ_ONE_HANDED_EXIT_TRANSITION:
+                return "ONE_HANDED_EXIT_TRANSITION";
+            case CUJ_UNFOLD_ANIM:
+                return "UNFOLD_ANIM";
+            case CUJ_SUW_LOADING_TO_SHOW_INFO_WITH_ACTIONS:
+                return "SUW_LOADING_TO_SHOW_INFO_WITH_ACTIONS";
+            case CUJ_SUW_SHOW_FUNCTION_SCREEN_WITH_ACTIONS:
+                return "SUW_SHOW_FUNCTION_SCREEN_WITH_ACTIONS";
+            case CUJ_SUW_LOADING_TO_NEXT_FLOW:
+                return "SUW_LOADING_TO_NEXT_FLOW";
+            case CUJ_SUW_LOADING_SCREEN_FOR_STATUS:
+                return "SUW_LOADING_SCREEN_FOR_STATUS";
+            case CUJ_SPLIT_SCREEN_ENTER:
+                return "SPLIT_SCREEN_ENTER";
+            case CUJ_SPLIT_SCREEN_EXIT:
+                return "SPLIT_SCREEN_EXIT";
+            case CUJ_LOCKSCREEN_LAUNCH_CAMERA:
+                return "LOCKSCREEN_LAUNCH_CAMERA";
+            case CUJ_SPLIT_SCREEN_RESIZE:
+                return "SPLIT_SCREEN_RESIZE";
+            case CUJ_SETTINGS_SLIDER:
+                return "SETTINGS_SLIDER";
+            case CUJ_TAKE_SCREENSHOT:
+                return "TAKE_SCREENSHOT";
+            case CUJ_VOLUME_CONTROL:
+                return "VOLUME_CONTROL";
+            case CUJ_BIOMETRIC_PROMPT_TRANSITION:
+                return "BIOMETRIC_PROMPT_TRANSITION";
+            case CUJ_SETTINGS_TOGGLE:
+                return "SETTINGS_TOGGLE";
+            case CUJ_SHADE_DIALOG_OPEN:
+                return "SHADE_DIALOG_OPEN";
+            case CUJ_USER_DIALOG_OPEN:
+                return "USER_DIALOG_OPEN";
+            case CUJ_TASKBAR_EXPAND:
+                return "TASKBAR_EXPAND";
+            case CUJ_TASKBAR_COLLAPSE:
+                return "TASKBAR_COLLAPSE";
+            case CUJ_SHADE_CLEAR_ALL:
+                return "SHADE_CLEAR_ALL";
+            case CUJ_LAUNCHER_UNLOCK_ENTRANCE_ANIMATION:
+                return "LAUNCHER_UNLOCK_ENTRANCE_ANIMATION";
+            case CUJ_LOCKSCREEN_OCCLUSION:
+                return "LOCKSCREEN_OCCLUSION";
+            case CUJ_RECENTS_SCROLLING:
+                return "RECENTS_SCROLLING";
+            case CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS:
+                return "LAUNCHER_APP_SWIPE_TO_RECENTS";
+            case CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE:
+                return "LAUNCHER_CLOSE_ALL_APPS_SWIPE";
+            case CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME:
+                return "LAUNCHER_CLOSE_ALL_APPS_TO_HOME";
+            case CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION:
+                return "LOCKSCREEN_CLOCK_MOVE_ANIMATION";
+            case CUJ_LAUNCHER_OPEN_SEARCH_RESULT:
+                return "LAUNCHER_OPEN_SEARCH_RESULT";
+            case CUJ_LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK:
+                return "LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK";
+            case CUJ_IME_INSETS_SHOW_ANIMATION:
+                return "IME_INSETS_SHOW_ANIMATION";
+            case CUJ_IME_INSETS_HIDE_ANIMATION:
+                return "IME_INSETS_HIDE_ANIMATION";
+            case CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER:
+                return "SPLIT_SCREEN_DOUBLE_TAP_DIVIDER";
+            case CUJ_LAUNCHER_UNFOLD_ANIM:
+                return "LAUNCHER_UNFOLD_ANIM";
+            case CUJ_PREDICTIVE_BACK_CROSS_ACTIVITY:
+                return "PREDICTIVE_BACK_CROSS_ACTIVITY";
+            case CUJ_PREDICTIVE_BACK_CROSS_TASK:
+                return "PREDICTIVE_BACK_CROSS_TASK";
+            case CUJ_PREDICTIVE_BACK_HOME:
+                return "PREDICTIVE_BACK_HOME";
+            case CUJ_LAUNCHER_SEARCH_QSB_OPEN:
+                return "LAUNCHER_SEARCH_QSB_OPEN";
+        }
+        return "UNKNOWN";
+    }
+
+    public static int getStatsdInteractionType(@CujType int cujType) {
+        return CUJ_TO_STATSD_INTERACTION_TYPE[cujType];
+    }
+
+    /** Returns whether the measurements for the given CUJ should be written to statsd. */
+    public static boolean logToStatsd(@CujType int cujType) {
+        return getStatsdInteractionType(cujType) != NO_STATSD_LOGGING;
+    }
+
+    /**
+     * A helper method to translate interaction type to CUJ name.
+     *
+     * @param interactionType the interaction type defined in AtomsProto.java
+     * @return the name of the interaction type
+     */
+    public static String getNameOfInteraction(int interactionType) {
+        // There is an offset amount of 1 between cujType and interactionType.
+        return Cuj.getNameOfCuj(getCujTypeFromInteraction(interactionType));
+    }
+
+    /**
+     * A helper method to translate interaction type to CUJ type.
+     *
+     * @param interactionType the interaction type defined in AtomsProto.java
+     * @return the integer in {@link Cuj.CujType}
+     */
+    private static int getCujTypeFromInteraction(int interactionType) {
+        return interactionType - 1;
+    }
+}
diff --git a/core/java/com/android/internal/jank/FrameTracker.java b/core/java/com/android/internal/jank/FrameTracker.java
index c83452d..86729f7 100644
--- a/core/java/com/android/internal/jank/FrameTracker.java
+++ b/core/java/com/android/internal/jank/FrameTracker.java
@@ -53,7 +53,6 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.jank.DisplayRefreshRate.RefreshRate;
 import com.android.internal.jank.InteractionJankMonitor.Configuration;
-import com.android.internal.jank.InteractionJankMonitor.Session;
 import com.android.internal.util.FrameworkStatsLog;
 
 import java.lang.annotation.Retention;
@@ -67,7 +66,6 @@
 public class FrameTracker extends SurfaceControl.OnJankDataListener
         implements HardwareRendererObserver.OnFrameMetricsAvailableListener {
     private static final String TAG = "FrameTracker";
-    private static final boolean DEBUG = false;
 
     private static final long INVALID_ID = -1;
     public static final int NANOS_IN_MILLISECOND = 1_000_000;
@@ -93,20 +91,19 @@
             REASON_CANCEL_NORMAL,
             REASON_CANCEL_NOT_BEGUN,
             REASON_CANCEL_SAME_VSYNC,
+            REASON_CANCEL_TIMEOUT,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface Reasons {
     }
 
-    @VisibleForTesting
-    public final InteractionJankMonitor mMonitor;
     private final HardwareRendererObserver mObserver;
     private final int mTraceThresholdMissedFrames;
     private final int mTraceThresholdFrameTimeMillis;
     private final ThreadedRendererWrapper mRendererWrapper;
     private final FrameMetricsWrapper mMetricsWrapper;
     private final SparseArray<JankInfo> mJankInfos = new SparseArray<>();
-    private final Session mSession;
+    private final Configuration mConfig;
     private final ViewRootWrapper mViewRoot;
     private final SurfaceControlWrapper mSurfaceControlWrapper;
     private final int mDisplayId;
@@ -197,19 +194,18 @@
         }
     }
 
-    public FrameTracker(@NonNull InteractionJankMonitor monitor, @NonNull Session session,
-            @NonNull Handler handler, @Nullable ThreadedRendererWrapper renderer,
+    public FrameTracker(@NonNull Configuration config,
+            @Nullable ThreadedRendererWrapper renderer,
             @Nullable ViewRootWrapper viewRootWrapper,
             @NonNull SurfaceControlWrapper surfaceControlWrapper,
             @NonNull ChoreographerWrapper choreographer,
             @Nullable FrameMetricsWrapper metrics,
             @NonNull StatsLogWrapper statsLog,
             int traceThresholdMissedFrames, int traceThresholdFrameTimeMillis,
-            @Nullable FrameTrackerListener listener, @NonNull Configuration config) {
-        mMonitor = monitor;
+            @Nullable FrameTrackerListener listener) {
         mSurfaceOnly = config.isSurfaceOnly();
-        mSession = session;
-        mHandler = handler;
+        mConfig = config;
+        mHandler = config.getHandler();
         mChoreographer = choreographer;
         mSurfaceControlWrapper = surfaceControlWrapper;
         mStatsLog = statsLog;
@@ -222,7 +218,7 @@
         mObserver = mSurfaceOnly
                 ? null
                 : new HardwareRendererObserver(this, mMetricsWrapper.getTiming(),
-                        handler, /* waitForPresentTime= */ false);
+                        mHandler, /* waitForPresentTime= */ false);
 
         mTraceThresholdMissedFrames = traceThresholdMissedFrames;
         mTraceThresholdFrameTimeMillis = traceThresholdFrameTimeMillis;
@@ -242,7 +238,7 @@
             mSurfaceChangedCallback = new ViewRootImpl.SurfaceChangedCallback() {
                 @Override
                 public void surfaceCreated(SurfaceControl.Transaction t) {
-                    getHandler().runWithScissors(() -> {
+                    mHandler.runWithScissors(() -> {
                         if (mSurfaceControl == null) {
                             mSurfaceControl = mViewRoot.getSurfaceControl();
                             if (mBeginVsyncId != INVALID_ID) {
@@ -262,13 +258,7 @@
 
                     // Wait a while to give the system a chance for the remaining
                     // frames to arrive, then force finish the session.
-                    getHandler().postDelayed(() -> {
-                        if (DEBUG) {
-                            Log.d(TAG, "surfaceDestroyed: " + mSession.getName()
-                                    + ", finalized=" + mMetricsFinalized
-                                    + ", info=" + mJankInfos.size()
-                                    + ", vsync=" + mBeginVsyncId);
-                        }
+                    mHandler.postDelayed(() -> {
                         if (!mMetricsFinalized) {
                             end(REASON_END_SURFACE_DESTROYED);
                             finish();
@@ -282,11 +272,6 @@
         }
     }
 
-    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
-    public Handler getHandler() {
-        return mHandler;
-    }
-
     /**
      * Begin a trace session of the CUJ.
      */
@@ -300,10 +285,6 @@
             mBeginVsyncId = mDeferMonitoring ? currentVsync + 1 : currentVsync;
         }
         if (mSurfaceControl != null) {
-            if (DEBUG) {
-                Log.d(TAG, "begin: " + mSession.getName() + ", begin=" + mBeginVsyncId
-                        + ", defer=" + mDeferMonitoring + ", current=" + currentVsync);
-            }
             if (mDeferMonitoring && currentVsync < mBeginVsyncId) {
                 markEvent("FT#deferMonitoring", 0);
                 // Normal case, we begin the instrument from the very beginning,
@@ -314,11 +295,6 @@
                 // there is no need to skip the frame where the begin invocation happens.
                 beginInternal();
             }
-        } else {
-            if (DEBUG) {
-                Log.d(TAG, "begin: defer beginning since the surface is not ready for CUJ="
-                        + mSession.getName());
-            }
         }
     }
 
@@ -336,8 +312,8 @@
             return;
         }
         mTracingStarted = true;
-        Trace.asyncTraceForTrackBegin(Trace.TRACE_TAG_APP, mSession.getName(), mSession.getName(),
-                (int) mBeginVsyncId);
+        String name = mConfig.getSessionName();
+        Trace.asyncTraceForTrackBegin(Trace.TRACE_TAG_APP, name, name, (int) mBeginVsyncId);
         markEvent("FT#beginVsync", mBeginVsyncId);
         markEvent("FT#layerId", mSurfaceControl.getLayerId());
         mSurfaceControlWrapper.addJankStatsListener(this, mSurfaceControl);
@@ -361,15 +337,10 @@
         } else if (mEndVsyncId <= mBeginVsyncId) {
             return cancel(REASON_CANCEL_SAME_VSYNC);
         } else {
-            if (DEBUG) {
-                Log.d(TAG, "end: " + mSession.getName()
-                        + ", end=" + mEndVsyncId + ", reason=" + reason);
-            }
+            final String name = mConfig.getSessionName();
             markEvent("FT#end", reason);
             markEvent("FT#endVsync", mEndVsyncId);
-            Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_APP, mSession.getName(),
-                    (int) mBeginVsyncId);
-            mSession.setReason(reason);
+            Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_APP, name, (int) mBeginVsyncId);
 
             // We don't remove observer here,
             // will remove it when all the frame metrics in this duration are called back.
@@ -395,16 +366,16 @@
                         mFlushAttempts++;
                     } else {
                         mWaitForFinishTimedOut = () -> {
-                            Log.e(TAG, "force finish cuj, time out: " + mSession.getName());
+                            Log.e(TAG, "force finish cuj, time out: " + name);
                             finish();
                         };
                         delay = TimeUnit.SECONDS.toMillis(10);
                     }
-                    getHandler().postDelayed(mWaitForFinishTimedOut, delay);
+                    mHandler.postDelayed(mWaitForFinishTimedOut, delay);
                 }
             };
-            getHandler().postDelayed(mWaitForFinishTimedOut, FLUSH_DELAY_MILLISECOND);
-            notifyCujEvent(ACTION_SESSION_END);
+            mHandler.postDelayed(mWaitForFinishTimedOut, FLUSH_DELAY_MILLISECOND);
+            notifyCujEvent(ACTION_SESSION_END, reason);
             return true;
         }
     }
@@ -421,22 +392,16 @@
         markEvent("FT#cancel", reason);
         // We don't need to end the trace section if it has never begun.
         if (mTracingStarted) {
-            Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_APP, mSession.getName(),
-                    (int) mBeginVsyncId);
+            Trace.asyncTraceForTrackEnd(
+                    Trace.TRACE_TAG_APP, mConfig.getSessionName(), (int) mBeginVsyncId);
         }
 
         // Always remove the observers in cancel call to avoid leakage.
         removeObservers();
 
-        if (DEBUG) {
-            Log.d(TAG, "cancel: " + mSession.getName() + ", begin=" + mBeginVsyncId
-                    + ", end=" + mEndVsyncId + ", reason=" + reason);
-        }
-
-        mSession.setReason(reason);
         // Notify the listener the session has been cancelled.
         // We don't notify the listeners if the session never begun.
-        notifyCujEvent(ACTION_SESSION_CANCEL);
+        notifyCujEvent(ACTION_SESSION_CANCEL, reason);
         return true;
     }
 
@@ -455,13 +420,13 @@
                         "The length of the trace event description <%s> exceeds %d",
                         event, MAX_LENGTH_EVENT_DESC));
             }
-            Trace.instantForTrack(Trace.TRACE_TAG_APP, mSession.getName(), event);
+            Trace.instantForTrack(Trace.TRACE_TAG_APP, mConfig.getSessionName(), event);
         }
     }
 
-    private void notifyCujEvent(String action) {
+    private void notifyCujEvent(String action, @Reasons int reason) {
         if (mListener == null) return;
-        mListener.onCujEvents(mSession, action);
+        mListener.onCujEvents(this, action, reason);
     }
 
     @Override
@@ -496,7 +461,7 @@
      */
     @VisibleForTesting
     public void postCallback(Runnable callback) {
-        getHandler().post(callback);
+        mHandler.post(callback);
     }
 
     @Nullable
@@ -587,13 +552,15 @@
         if (mMetricsFinalized || mCancelled) return;
         mMetricsFinalized = true;
 
-        getHandler().removeCallbacks(mWaitForFinishTimedOut);
+        mHandler.removeCallbacks(mWaitForFinishTimedOut);
         mWaitForFinishTimedOut = null;
         markEvent("FT#finish", mJankInfos.size());
 
         // The tracing has been ended, remove the observer, see if need to trigger perfetto.
         removeObservers();
 
+        final String name = mConfig.getSessionName();
+
         int totalFramesCount = 0;
         long maxFrameTimeNanos = 0;
         int missedFramesCount = 0;
@@ -616,7 +583,7 @@
                 totalFramesCount++;
                 boolean missedFrame = false;
                 if ((info.jankType & JANK_APP_DEADLINE_MISSED) != 0) {
-                    Log.w(TAG, "Missed App frame:" + info + ", CUJ=" + mSession.getName());
+                    Log.w(TAG, "Missed App frame:" + info + ", CUJ=" + name);
                     missedAppFramesCount++;
                     missedFrame = true;
                 }
@@ -625,7 +592,7 @@
                         || (info.jankType & JANK_SURFACEFLINGER_GPU_DEADLINE_MISSED) != 0
                         || (info.jankType & SURFACE_FLINGER_SCHEDULING) != 0
                         || (info.jankType & PREDICTION_ERROR) != 0) {
-                    Log.w(TAG, "Missed SF frame:" + info + ", CUJ=" + mSession.getName());
+                    Log.w(TAG, "Missed SF frame:" + info + ", CUJ=" + name);
                     missedSfFramesCount++;
                     missedFrame = true;
                 }
@@ -646,7 +613,7 @@
                 if (!mSurfaceOnly && !info.hwuiCallbackFired) {
                     markEvent("FT#MissedHWUICallback", info.frameVsyncId);
                     Log.w(TAG, "Missing HWUI jank callback for vsyncId: " + info.frameVsyncId
-                            + ", CUJ=" + mSession.getName());
+                            + ", CUJ=" + name);
                 }
             }
             if (!mSurfaceOnly && info.hwuiCallbackFired) {
@@ -654,7 +621,7 @@
                 if (!info.surfaceControlCallbackFired) {
                     markEvent("FT#MissedSFCallback", info.frameVsyncId);
                     Log.w(TAG, "Missing SF jank callback for vsyncId: " + info.frameVsyncId
-                            + ", CUJ=" + mSession.getName());
+                            + ", CUJ=" + name);
                 }
             }
         }
@@ -662,29 +629,26 @@
                 maxSuccessiveMissedFramesCount, successiveMissedFramesCount);
 
         // Log the frame stats as counters to make them easily accessible in traces.
-        Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#missedFrames",
-                missedFramesCount);
-        Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#missedAppFrames",
-                missedAppFramesCount);
-        Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#missedSfFrames",
-                missedSfFramesCount);
-        Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#totalFrames",
-                totalFramesCount);
-        Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#maxFrameTimeMillis",
+        Trace.traceCounter(Trace.TRACE_TAG_APP, name + "#missedFrames", missedFramesCount);
+        Trace.traceCounter(Trace.TRACE_TAG_APP, name + "#missedAppFrames", missedAppFramesCount);
+        Trace.traceCounter(Trace.TRACE_TAG_APP, name + "#missedSfFrames", missedSfFramesCount);
+        Trace.traceCounter(Trace.TRACE_TAG_APP, name + "#totalFrames", totalFramesCount);
+        Trace.traceCounter(Trace.TRACE_TAG_APP, name + "#maxFrameTimeMillis",
                 (int) (maxFrameTimeNanos / NANOS_IN_MILLISECOND));
-        Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#maxSuccessiveMissedFrames",
+        Trace.traceCounter(Trace.TRACE_TAG_APP, name + "#maxSuccessiveMissedFrames",
                 maxSuccessiveMissedFramesCount);
 
         // Trigger perfetto if necessary.
-        if (shouldTriggerPerfetto(missedFramesCount, (int) maxFrameTimeNanos)) {
-            triggerPerfetto();
+        if (mListener != null
+                && shouldTriggerPerfetto(missedFramesCount, (int) maxFrameTimeNanos)) {
+            mListener.triggerPerfetto(mConfig);
         }
-        if (mSession.logToStatsd()) {
+        if (mConfig.logToStatsd()) {
             mStatsLog.write(
                     FrameworkStatsLog.UI_INTERACTION_FRAME_INFO_REPORTED,
                     mDisplayId,
                     refreshRate,
-                    mSession.getStatsdInteractionType(),
+                    mConfig.getStatsdInteractionType(),
                     totalFramesCount,
                     missedFramesCount,
                     maxFrameTimeNanos, /* will be 0 if mSurfaceOnly == true */
@@ -692,16 +656,6 @@
                     missedAppFramesCount,
                     maxSuccessiveMissedFramesCount);
         }
-        if (DEBUG) {
-            Log.i(TAG, "finish: CUJ=" + mSession.getName()
-                    + " (" + mBeginVsyncId + "," + mEndVsyncId + ")"
-                    + " totalFrames=" + totalFramesCount
-                    + " missedAppFrames=" + missedAppFramesCount
-                    + " missedSfFrames=" + missedSfFramesCount
-                    + " missedFrames=" + missedFramesCount
-                    + " maxFrameTimeMillis=" + maxFrameTimeNanos / NANOS_IN_MILLISECOND
-                    + " maxSuccessiveMissedFramesCount=" + maxSuccessiveMissedFramesCount);
-        }
     }
 
     ThreadedRendererWrapper getThreadedRenderer() {
@@ -737,13 +691,6 @@
     }
 
     /**
-     * Trigger the prefetto daemon.
-     */
-    public void triggerPerfetto() {
-        mMonitor.trigger(mSession);
-    }
-
-    /**
      * A wrapper class that we can spy FrameMetrics (a final class) in unit tests.
      */
     public static class FrameMetricsWrapper {
@@ -895,9 +842,17 @@
         /**
          * Notify that the CUJ session was created.
          *
-         * @param session the CUJ session
+         * @param tracker the tracker
          * @param action the specific action
+         * @param reason the reason for the action
          */
-        void onCujEvents(Session session, String action);
+        void onCujEvents(FrameTracker tracker, String action, @Reasons int reason);
+
+        /**
+         * Notify that the Perfetto trace should be triggered.
+         *
+         * @param config the tracker configuration
+         */
+        void triggerPerfetto(Configuration config);
     }
 }
diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java
index e6b036c..8b1879f 100644
--- a/core/java/com/android/internal/jank/InteractionJankMonitor.java
+++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java
@@ -23,89 +23,9 @@
 import static com.android.internal.jank.FrameTracker.REASON_CANCEL_NORMAL;
 import static com.android.internal.jank.FrameTracker.REASON_CANCEL_TIMEOUT;
 import static com.android.internal.jank.FrameTracker.REASON_END_NORMAL;
-import static com.android.internal.jank.FrameTracker.REASON_END_UNKNOWN;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__BIOMETRIC_PROMPT_TRANSITION;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__IME_INSETS_HIDE_ANIMATION;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__IME_INSETS_SHOW_ANIMATION;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_ALL_APPS_SCROLL;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_HOME;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_PIP;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_LAUNCH_FROM_ICON;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_LAUNCH_FROM_RECENTS;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_LAUNCH_FROM_WIDGET;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_SWIPE_TO_RECENTS;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_CLOSE_ALL_APPS_SWIPE;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_CLOSE_ALL_APPS_TO_HOME;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_OPEN_ALL_APPS;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_OPEN_SEARCH_RESULT;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_QUICK_SWITCH;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_UNFOLD_ANIM;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_UNLOCK_ENTRANCE_ANIMATION;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_CLOCK_MOVE_ANIMATION;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_LAUNCH_CAMERA;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_OCCLUSION;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PASSWORD_APPEAR;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PASSWORD_DISAPPEAR;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PATTERN_APPEAR;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PATTERN_DISAPPEAR;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PIN_APPEAR;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PIN_DISAPPEAR;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_TRANSITION_FROM_AOD;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_TRANSITION_TO_AOD;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_UNLOCK_ANIMATION;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__NOTIFICATION_SHADE_SWIPE;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__ONE_HANDED_ENTER_TRANSITION;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__ONE_HANDED_EXIT_TRANSITION;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__PIP_TRANSITION;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__PREDICTIVE_BACK_CROSS_ACTIVITY;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__PREDICTIVE_BACK_CROSS_TASK;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__PREDICTIVE_BACK_HOME;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__RECENTS_SCROLLING;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SCREEN_OFF;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SCREEN_OFF_SHOW_AOD;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SETTINGS_PAGE_SCROLL;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SETTINGS_SLIDER;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SETTINGS_TOGGLE;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH_FROM_QS_TILE;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_CLEAR_ALL;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_DIALOG_OPEN;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_HEADS_UP_APPEAR;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_HEADS_UP_DISAPPEAR;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_NOTIFICATION_ADD;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_NOTIFICATION_REMOVE;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_QS_EXPAND_COLLAPSE;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_QS_SCROLL_SWIPE;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_ROW_EXPAND;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_ROW_SWIPE;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_SCROLL_FLING;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLASHSCREEN_AVD;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLASHSCREEN_EXIT_ANIM;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_DOUBLE_TAP_DIVIDER;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_ENTER;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_EXIT;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_RESIZE;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SUW_LOADING_SCREEN_FOR_STATUS;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SUW_LOADING_TO_NEXT_FLOW;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SUW_LOADING_TO_SHOW_INFO_WITH_ACTIONS;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SUW_SHOW_FUNCTION_SCREEN_WITH_ACTIONS;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__TAKE_SCREENSHOT;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__TASKBAR_COLLAPSE;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__TASKBAR_EXPAND;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__UNFOLD_ANIM;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__USER_DIALOG_OPEN;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__USER_SWITCH;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__VOLUME_CONTROL;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__WALLPAPER_TRANSITION;
 
 import android.Manifest;
 import android.annotation.ColorInt;
-import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
 import android.annotation.UiThread;
@@ -137,34 +57,31 @@
 import com.android.internal.jank.FrameTracker.ViewRootWrapper;
 import com.android.internal.util.PerfettoTrigger;
 
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 import java.time.Instant;
-import java.util.Locale;
 import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.TimeUnit;
+import java.util.function.Supplier;
 
 /**
- * This class let users to begin and end the always on tracing mechanism.
+ * This class lets users begin and end the always on tracing mechanism.
  *
  * Enabling for local development:
- *
+ *<pre>
  * adb shell device_config put interaction_jank_monitor enabled true
  * adb shell device_config put interaction_jank_monitor sampling_interval 1
- *
+ * </pre>
  * On debuggable builds, an overlay can be used to display the name of the
  * currently running cuj using:
- *
+ * <pre>
  * adb shell device_config put interaction_jank_monitor debug_overlay_enabled true
- *
- * NOTE: The overlay will interfere with metrics, so it should only be used
- * for understanding which UI events correspeond to which CUJs.
+ * </pre>
+ * <b>NOTE</b>: The overlay will interfere with metrics, so it should only be used
+ * for understanding which UI events correspond to which CUJs.
  *
  * @hide
  */
 public class InteractionJankMonitor {
     private static final String TAG = InteractionJankMonitor.class.getSimpleName();
-    private static final boolean DEBUG = false;
     private static final String ACTION_PREFIX = InteractionJankMonitor.class.getCanonicalName();
 
     private static final String DEFAULT_WORKER_NAME = TAG + "-Worker";
@@ -186,218 +103,79 @@
     private static final int DEFAULT_TRACE_THRESHOLD_FRAME_TIME_MILLIS = 64;
     private static final boolean DEFAULT_DEBUG_OVERLAY_ENABLED = false;
 
-    @VisibleForTesting
-    public static final int MAX_LENGTH_OF_CUJ_NAME = 80;
     private static final int MAX_LENGTH_SESSION_NAME = 100;
 
     public static final String ACTION_SESSION_END = ACTION_PREFIX + ".ACTION_SESSION_END";
     public static final String ACTION_SESSION_CANCEL = ACTION_PREFIX + ".ACTION_SESSION_CANCEL";
 
-    // Every value must have a corresponding entry in CUJ_STATSD_INTERACTION_TYPE.
-    public static final int CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE = 0;
-    public static final int CUJ_NOTIFICATION_SHADE_SCROLL_FLING = 2;
-    public static final int CUJ_NOTIFICATION_SHADE_ROW_EXPAND = 3;
-    public static final int CUJ_NOTIFICATION_SHADE_ROW_SWIPE = 4;
-    public static final int CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE = 5;
-    public static final int CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE = 6;
-    public static final int CUJ_LAUNCHER_APP_LAUNCH_FROM_RECENTS = 7;
-    public static final int CUJ_LAUNCHER_APP_LAUNCH_FROM_ICON = 8;
-    public static final int CUJ_LAUNCHER_APP_CLOSE_TO_HOME = 9;
-    public static final int CUJ_LAUNCHER_APP_CLOSE_TO_PIP = 10;
-    public static final int CUJ_LAUNCHER_QUICK_SWITCH = 11;
-    public static final int CUJ_NOTIFICATION_HEADS_UP_APPEAR = 12;
-    public static final int CUJ_NOTIFICATION_HEADS_UP_DISAPPEAR = 13;
-    public static final int CUJ_NOTIFICATION_ADD = 14;
-    public static final int CUJ_NOTIFICATION_REMOVE = 15;
-    public static final int CUJ_NOTIFICATION_APP_START = 16;
-    public static final int CUJ_LOCKSCREEN_PASSWORD_APPEAR = 17;
-    public static final int CUJ_LOCKSCREEN_PATTERN_APPEAR = 18;
-    public static final int CUJ_LOCKSCREEN_PIN_APPEAR = 19;
-    public static final int CUJ_LOCKSCREEN_PASSWORD_DISAPPEAR = 20;
-    public static final int CUJ_LOCKSCREEN_PATTERN_DISAPPEAR = 21;
-    public static final int CUJ_LOCKSCREEN_PIN_DISAPPEAR = 22;
-    public static final int CUJ_LOCKSCREEN_TRANSITION_FROM_AOD = 23;
-    public static final int CUJ_LOCKSCREEN_TRANSITION_TO_AOD = 24;
-    public static final int CUJ_LAUNCHER_OPEN_ALL_APPS = 25;
-    public static final int CUJ_LAUNCHER_ALL_APPS_SCROLL = 26;
-    public static final int CUJ_LAUNCHER_APP_LAUNCH_FROM_WIDGET = 27;
-    public static final int CUJ_SETTINGS_PAGE_SCROLL = 28;
-    public static final int CUJ_LOCKSCREEN_UNLOCK_ANIMATION = 29;
-    public static final int CUJ_SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON = 30;
-    public static final int CUJ_SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER = 31;
-    public static final int CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE = 32;
-    public static final int CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON = 33;
-    public static final int CUJ_STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP = 34;
-    public static final int CUJ_PIP_TRANSITION = 35;
-    public static final int CUJ_WALLPAPER_TRANSITION = 36;
-    public static final int CUJ_USER_SWITCH = 37;
-    public static final int CUJ_SPLASHSCREEN_AVD = 38;
-    public static final int CUJ_SPLASHSCREEN_EXIT_ANIM = 39;
-    public static final int CUJ_SCREEN_OFF = 40;
-    public static final int CUJ_SCREEN_OFF_SHOW_AOD = 41;
-    public static final int CUJ_ONE_HANDED_ENTER_TRANSITION = 42;
-    public static final int CUJ_ONE_HANDED_EXIT_TRANSITION = 43;
-    public static final int CUJ_UNFOLD_ANIM = 44;
-    public static final int CUJ_SUW_LOADING_TO_SHOW_INFO_WITH_ACTIONS = 45;
-    public static final int CUJ_SUW_SHOW_FUNCTION_SCREEN_WITH_ACTIONS = 46;
-    public static final int CUJ_SUW_LOADING_TO_NEXT_FLOW = 47;
-    public static final int CUJ_SUW_LOADING_SCREEN_FOR_STATUS = 48;
-    public static final int CUJ_SPLIT_SCREEN_ENTER = 49;
-    public static final int CUJ_SPLIT_SCREEN_EXIT = 50;
-    public static final int CUJ_LOCKSCREEN_LAUNCH_CAMERA = 51; // reserved.
-    public static final int CUJ_SPLIT_SCREEN_RESIZE = 52;
-    public static final int CUJ_SETTINGS_SLIDER = 53;
-    public static final int CUJ_TAKE_SCREENSHOT = 54;
-    public static final int CUJ_VOLUME_CONTROL = 55;
-    public static final int CUJ_BIOMETRIC_PROMPT_TRANSITION = 56;
-    public static final int CUJ_SETTINGS_TOGGLE = 57;
-    public static final int CUJ_SHADE_DIALOG_OPEN = 58;
-    public static final int CUJ_USER_DIALOG_OPEN = 59;
-    public static final int CUJ_TASKBAR_EXPAND = 60;
-    public static final int CUJ_TASKBAR_COLLAPSE = 61;
-    public static final int CUJ_SHADE_CLEAR_ALL = 62;
-    public static final int CUJ_LAUNCHER_UNLOCK_ENTRANCE_ANIMATION = 63;
-    public static final int CUJ_LOCKSCREEN_OCCLUSION = 64;
-    public static final int CUJ_RECENTS_SCROLLING = 65;
-    public static final int CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS = 66;
-    public static final int CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE = 67;
-    public static final int CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME = 68;
-    public static final int CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION = 70;
-    public static final int CUJ_LAUNCHER_OPEN_SEARCH_RESULT = 71;
-    // 72 - 77 are reserved for b/281564325.
-
-    /**
-     * In some cases when we do not have any end-target, we play a simple slide-down animation.
-     * eg: Open an app from Overview/Task switcher such that there is no home-screen icon.
-     * eg: Exit the app using back gesture.
-     */
-    public static final int CUJ_LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK = 78;
-    public static final int CUJ_IME_INSETS_SHOW_ANIMATION = 80;
-    public static final int CUJ_IME_INSETS_HIDE_ANIMATION = 81;
-
-    public static final int CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER = 82;
-
-    public static final int CUJ_LAUNCHER_UNFOLD_ANIM = 83;
-
-    public static final int CUJ_PREDICTIVE_BACK_CROSS_ACTIVITY = 84;
-    public static final int CUJ_PREDICTIVE_BACK_CROSS_TASK = 85;
-    public static final int CUJ_PREDICTIVE_BACK_HOME = 86;
-
-    private static final int LAST_CUJ = CUJ_PREDICTIVE_BACK_HOME;
-    private static final int NO_STATSD_LOGGING = -1;
-
-    // Used to convert CujType to InteractionType enum value for statsd logging.
-    // Use NO_STATSD_LOGGING in case the measurement for a given CUJ should not be logged to statsd.
-    @VisibleForTesting
-    public static final int[] CUJ_TO_STATSD_INTERACTION_TYPE = new int[LAST_CUJ + 1];
-
-    static {
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__NOTIFICATION_SHADE_SWIPE;
-        CUJ_TO_STATSD_INTERACTION_TYPE[1] = NO_STATSD_LOGGING; // This is deprecated.
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_SCROLL_FLING] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_SCROLL_FLING;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_ROW_EXPAND] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_ROW_EXPAND;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_ROW_SWIPE] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_ROW_SWIPE;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_QS_EXPAND_COLLAPSE;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_QS_SCROLL_SWIPE;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_APP_LAUNCH_FROM_RECENTS] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_LAUNCH_FROM_RECENTS;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_APP_LAUNCH_FROM_ICON] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_LAUNCH_FROM_ICON;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_APP_CLOSE_TO_HOME] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_HOME;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_APP_CLOSE_TO_PIP] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_PIP;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_QUICK_SWITCH] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_QUICK_SWITCH;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_HEADS_UP_APPEAR] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_HEADS_UP_APPEAR;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_HEADS_UP_DISAPPEAR] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_HEADS_UP_DISAPPEAR;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_ADD] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_NOTIFICATION_ADD;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_REMOVE] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_NOTIFICATION_REMOVE;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_APP_START] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_PASSWORD_APPEAR] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PASSWORD_APPEAR;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_PATTERN_APPEAR] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PATTERN_APPEAR;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_PIN_APPEAR] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PIN_APPEAR;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_PASSWORD_DISAPPEAR] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PASSWORD_DISAPPEAR;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_PATTERN_DISAPPEAR] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PATTERN_DISAPPEAR;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_PIN_DISAPPEAR] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PIN_DISAPPEAR;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_TRANSITION_FROM_AOD] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_TRANSITION_FROM_AOD;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_TRANSITION_TO_AOD] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_TRANSITION_TO_AOD;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_OPEN_ALL_APPS] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_OPEN_ALL_APPS;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_ALL_APPS_SCROLL] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_ALL_APPS_SCROLL;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_APP_LAUNCH_FROM_WIDGET] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_LAUNCH_FROM_WIDGET;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SETTINGS_PAGE_SCROLL] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SETTINGS_PAGE_SCROLL;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_UNLOCK_ANIMATION] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_UNLOCK_ANIMATION;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH_FROM_QS_TILE;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_PIP_TRANSITION] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__PIP_TRANSITION;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_WALLPAPER_TRANSITION] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__WALLPAPER_TRANSITION;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_USER_SWITCH] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__USER_SWITCH;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SPLASHSCREEN_AVD] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLASHSCREEN_AVD;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SPLASHSCREEN_EXIT_ANIM] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLASHSCREEN_EXIT_ANIM;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SCREEN_OFF] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SCREEN_OFF;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SCREEN_OFF_SHOW_AOD] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SCREEN_OFF_SHOW_AOD;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_ONE_HANDED_ENTER_TRANSITION] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__ONE_HANDED_ENTER_TRANSITION;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_ONE_HANDED_EXIT_TRANSITION] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__ONE_HANDED_EXIT_TRANSITION;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_UNFOLD_ANIM] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__UNFOLD_ANIM;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SUW_LOADING_TO_SHOW_INFO_WITH_ACTIONS] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SUW_LOADING_TO_SHOW_INFO_WITH_ACTIONS;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SUW_SHOW_FUNCTION_SCREEN_WITH_ACTIONS] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SUW_SHOW_FUNCTION_SCREEN_WITH_ACTIONS;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SUW_LOADING_TO_NEXT_FLOW] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SUW_LOADING_TO_NEXT_FLOW;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SUW_LOADING_SCREEN_FOR_STATUS] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SUW_LOADING_SCREEN_FOR_STATUS;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SPLIT_SCREEN_ENTER] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_ENTER;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SPLIT_SCREEN_EXIT] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_EXIT;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_LAUNCH_CAMERA] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_LAUNCH_CAMERA;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SPLIT_SCREEN_RESIZE] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_RESIZE;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SETTINGS_SLIDER] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SETTINGS_SLIDER;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_TAKE_SCREENSHOT] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__TAKE_SCREENSHOT;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_VOLUME_CONTROL] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__VOLUME_CONTROL;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_BIOMETRIC_PROMPT_TRANSITION] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__BIOMETRIC_PROMPT_TRANSITION;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SETTINGS_TOGGLE] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SETTINGS_TOGGLE;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SHADE_DIALOG_OPEN] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_DIALOG_OPEN;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_USER_DIALOG_OPEN] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__USER_DIALOG_OPEN;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_TASKBAR_EXPAND] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__TASKBAR_EXPAND;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_TASKBAR_COLLAPSE] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__TASKBAR_COLLAPSE;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SHADE_CLEAR_ALL] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SHADE_CLEAR_ALL;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_UNLOCK_ENTRANCE_ANIMATION] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_UNLOCK_ENTRANCE_ANIMATION;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_OCCLUSION] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_OCCLUSION;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_RECENTS_SCROLLING] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__RECENTS_SCROLLING;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_SWIPE_TO_RECENTS;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_CLOSE_ALL_APPS_SWIPE;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_CLOSE_ALL_APPS_TO_HOME;
-        CUJ_TO_STATSD_INTERACTION_TYPE[69] = NO_STATSD_LOGGING; // This is deprecated.
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_CLOCK_MOVE_ANIMATION;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_OPEN_SEARCH_RESULT] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_OPEN_SEARCH_RESULT;
-        // 72 - 77 are reserved for b/281564325.
-        CUJ_TO_STATSD_INTERACTION_TYPE[72] = NO_STATSD_LOGGING;
-        CUJ_TO_STATSD_INTERACTION_TYPE[73] = NO_STATSD_LOGGING;
-        CUJ_TO_STATSD_INTERACTION_TYPE[74] = NO_STATSD_LOGGING;
-        CUJ_TO_STATSD_INTERACTION_TYPE[75] = NO_STATSD_LOGGING;
-        CUJ_TO_STATSD_INTERACTION_TYPE[76] = NO_STATSD_LOGGING;
-        CUJ_TO_STATSD_INTERACTION_TYPE[77] = NO_STATSD_LOGGING;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK;
-        CUJ_TO_STATSD_INTERACTION_TYPE[79] = NO_STATSD_LOGGING; // This is deprecated.
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_IME_INSETS_SHOW_ANIMATION] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__IME_INSETS_SHOW_ANIMATION;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_IME_INSETS_HIDE_ANIMATION] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__IME_INSETS_HIDE_ANIMATION;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_DOUBLE_TAP_DIVIDER;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_LAUNCHER_UNFOLD_ANIM] = UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_UNFOLD_ANIM;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_PREDICTIVE_BACK_CROSS_ACTIVITY] =
-            UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__PREDICTIVE_BACK_CROSS_ACTIVITY;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_PREDICTIVE_BACK_CROSS_TASK] =
-            UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__PREDICTIVE_BACK_CROSS_TASK;
-        CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_PREDICTIVE_BACK_HOME] =
-            UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__PREDICTIVE_BACK_HOME;
-    }
+    // These are not the CUJ constants you are looking for. These constants simply forward their
+    // definition from {@link Cuj}. They are here only as a transition measure until all references
+    // have been updated to the new location.
+    @Deprecated public static final int CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE = Cuj.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE;
+    @Deprecated public static final int CUJ_NOTIFICATION_SHADE_SCROLL_FLING = Cuj.CUJ_NOTIFICATION_SHADE_SCROLL_FLING;
+    @Deprecated public static final int CUJ_NOTIFICATION_SHADE_ROW_EXPAND = Cuj.CUJ_NOTIFICATION_SHADE_ROW_EXPAND;
+    @Deprecated public static final int CUJ_NOTIFICATION_SHADE_ROW_SWIPE = Cuj.CUJ_NOTIFICATION_SHADE_ROW_SWIPE;
+    @Deprecated public static final int CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE = Cuj.CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE;
+    @Deprecated public static final int CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE = Cuj.CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE;
+    @Deprecated public static final int CUJ_LAUNCHER_APP_CLOSE_TO_HOME = Cuj.CUJ_LAUNCHER_APP_CLOSE_TO_HOME;
+    @Deprecated public static final int CUJ_LAUNCHER_QUICK_SWITCH = Cuj.CUJ_LAUNCHER_QUICK_SWITCH;
+    @Deprecated public static final int CUJ_NOTIFICATION_HEADS_UP_APPEAR = Cuj.CUJ_NOTIFICATION_HEADS_UP_APPEAR;
+    @Deprecated public static final int CUJ_NOTIFICATION_HEADS_UP_DISAPPEAR = Cuj.CUJ_NOTIFICATION_HEADS_UP_DISAPPEAR;
+    @Deprecated public static final int CUJ_NOTIFICATION_ADD = Cuj.CUJ_NOTIFICATION_ADD;
+    @Deprecated public static final int CUJ_NOTIFICATION_REMOVE = Cuj.CUJ_NOTIFICATION_REMOVE;
+    @Deprecated public static final int CUJ_NOTIFICATION_APP_START = Cuj.CUJ_NOTIFICATION_APP_START;
+    @Deprecated public static final int CUJ_LOCKSCREEN_PASSWORD_APPEAR = Cuj.CUJ_LOCKSCREEN_PASSWORD_APPEAR;
+    @Deprecated public static final int CUJ_LOCKSCREEN_PATTERN_APPEAR = Cuj.CUJ_LOCKSCREEN_PATTERN_APPEAR;
+    @Deprecated public static final int CUJ_LOCKSCREEN_PIN_APPEAR = Cuj.CUJ_LOCKSCREEN_PIN_APPEAR;
+    @Deprecated public static final int CUJ_LOCKSCREEN_PASSWORD_DISAPPEAR = Cuj.CUJ_LOCKSCREEN_PASSWORD_DISAPPEAR;
+    @Deprecated public static final int CUJ_LOCKSCREEN_PATTERN_DISAPPEAR = Cuj.CUJ_LOCKSCREEN_PATTERN_DISAPPEAR;
+    @Deprecated public static final int CUJ_LOCKSCREEN_PIN_DISAPPEAR = Cuj.CUJ_LOCKSCREEN_PIN_DISAPPEAR;
+    @Deprecated public static final int CUJ_LOCKSCREEN_TRANSITION_FROM_AOD = Cuj.CUJ_LOCKSCREEN_TRANSITION_FROM_AOD;
+    @Deprecated public static final int CUJ_LOCKSCREEN_TRANSITION_TO_AOD = Cuj.CUJ_LOCKSCREEN_TRANSITION_TO_AOD;
+    @Deprecated public static final int CUJ_SETTINGS_PAGE_SCROLL = Cuj.CUJ_SETTINGS_PAGE_SCROLL;
+    @Deprecated public static final int CUJ_LOCKSCREEN_UNLOCK_ANIMATION = Cuj.CUJ_LOCKSCREEN_UNLOCK_ANIMATION;
+    @Deprecated public static final int CUJ_SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON = Cuj.CUJ_SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON;
+    @Deprecated public static final int CUJ_SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER = Cuj.CUJ_SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER;
+    @Deprecated public static final int CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE = Cuj.CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE;
+    @Deprecated public static final int CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON = Cuj.CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON;
+    @Deprecated public static final int CUJ_STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP = Cuj.CUJ_STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP;
+    @Deprecated public static final int CUJ_PIP_TRANSITION = Cuj.CUJ_PIP_TRANSITION;
+    @Deprecated public static final int CUJ_USER_SWITCH = Cuj.CUJ_USER_SWITCH;
+    @Deprecated public static final int CUJ_SPLASHSCREEN_AVD = Cuj.CUJ_SPLASHSCREEN_AVD;
+    @Deprecated public static final int CUJ_SPLASHSCREEN_EXIT_ANIM = Cuj.CUJ_SPLASHSCREEN_EXIT_ANIM;
+    @Deprecated public static final int CUJ_SCREEN_OFF = Cuj.CUJ_SCREEN_OFF;
+    @Deprecated public static final int CUJ_SCREEN_OFF_SHOW_AOD = Cuj.CUJ_SCREEN_OFF_SHOW_AOD;
+    @Deprecated public static final int CUJ_UNFOLD_ANIM = Cuj.CUJ_UNFOLD_ANIM;
+    @Deprecated public static final int CUJ_SUW_LOADING_TO_SHOW_INFO_WITH_ACTIONS = Cuj.CUJ_SUW_LOADING_TO_SHOW_INFO_WITH_ACTIONS;
+    @Deprecated public static final int CUJ_SUW_SHOW_FUNCTION_SCREEN_WITH_ACTIONS = Cuj.CUJ_SUW_SHOW_FUNCTION_SCREEN_WITH_ACTIONS;
+    @Deprecated public static final int CUJ_SUW_LOADING_TO_NEXT_FLOW = Cuj.CUJ_SUW_LOADING_TO_NEXT_FLOW;
+    @Deprecated public static final int CUJ_SUW_LOADING_SCREEN_FOR_STATUS = Cuj.CUJ_SUW_LOADING_SCREEN_FOR_STATUS;
+    @Deprecated public static final int CUJ_SPLIT_SCREEN_RESIZE = Cuj.CUJ_SPLIT_SCREEN_RESIZE;
+    @Deprecated public static final int CUJ_SETTINGS_SLIDER = Cuj.CUJ_SETTINGS_SLIDER;
+    @Deprecated public static final int CUJ_TAKE_SCREENSHOT = Cuj.CUJ_TAKE_SCREENSHOT;
+    @Deprecated public static final int CUJ_VOLUME_CONTROL = Cuj.CUJ_VOLUME_CONTROL;
+    @Deprecated public static final int CUJ_BIOMETRIC_PROMPT_TRANSITION = Cuj.CUJ_BIOMETRIC_PROMPT_TRANSITION;
+    @Deprecated public static final int CUJ_SETTINGS_TOGGLE = Cuj.CUJ_SETTINGS_TOGGLE;
+    @Deprecated public static final int CUJ_SHADE_DIALOG_OPEN = Cuj.CUJ_SHADE_DIALOG_OPEN;
+    @Deprecated public static final int CUJ_USER_DIALOG_OPEN = Cuj.CUJ_USER_DIALOG_OPEN;
+    @Deprecated public static final int CUJ_TASKBAR_EXPAND = Cuj.CUJ_TASKBAR_EXPAND;
+    @Deprecated public static final int CUJ_TASKBAR_COLLAPSE = Cuj.CUJ_TASKBAR_COLLAPSE;
+    @Deprecated public static final int CUJ_SHADE_CLEAR_ALL = Cuj.CUJ_SHADE_CLEAR_ALL;
+    @Deprecated public static final int CUJ_LOCKSCREEN_OCCLUSION = Cuj.CUJ_LOCKSCREEN_OCCLUSION;
+    @Deprecated public static final int CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION = Cuj.CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION;
+    @Deprecated public static final int CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER = Cuj.CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER;
+    @Deprecated public static final int CUJ_PREDICTIVE_BACK_CROSS_ACTIVITY = Cuj.CUJ_PREDICTIVE_BACK_CROSS_ACTIVITY;
+    @Deprecated public static final int CUJ_PREDICTIVE_BACK_CROSS_TASK = Cuj.CUJ_PREDICTIVE_BACK_CROSS_TASK;
+    @Deprecated public static final int CUJ_PREDICTIVE_BACK_HOME = Cuj.CUJ_PREDICTIVE_BACK_HOME;
 
     private static class InstanceHolder {
         public static final InteractionJankMonitor INSTANCE =
             new InteractionJankMonitor(new HandlerThread(DEFAULT_WORKER_NAME));
     }
 
-    private final DeviceConfig.OnPropertiesChangedListener mPropertiesChangedListener =
-            this::updateProperties;
-
     @GuardedBy("mLock")
-    private final SparseArray<FrameTracker> mRunningTrackers;
-    @GuardedBy("mLock")
-    private final SparseArray<Runnable> mTimeoutActions;
-    private final HandlerThread mWorker;
+    private final SparseArray<RunningTracker> mRunningTrackers = new SparseArray<>();
+    private final Handler mWorker;
     private final DisplayResolutionTracker mDisplayResolutionTracker;
     private final Object mLock = new Object();
     private @ColorInt int mDebugBgColor = Color.CYAN;
@@ -409,91 +187,6 @@
     private int mTraceThresholdMissedFrames = DEFAULT_TRACE_THRESHOLD_MISSED_FRAMES;
     private int mTraceThresholdFrameTimeMillis = DEFAULT_TRACE_THRESHOLD_FRAME_TIME_MILLIS;
 
-    /** @hide */
-    @IntDef({
-            CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE,
-            CUJ_NOTIFICATION_SHADE_SCROLL_FLING,
-            CUJ_NOTIFICATION_SHADE_ROW_EXPAND,
-            CUJ_NOTIFICATION_SHADE_ROW_SWIPE,
-            CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE,
-            CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE,
-            CUJ_LAUNCHER_APP_LAUNCH_FROM_RECENTS,
-            CUJ_LAUNCHER_APP_LAUNCH_FROM_ICON,
-            CUJ_LAUNCHER_APP_CLOSE_TO_HOME,
-            CUJ_LAUNCHER_APP_CLOSE_TO_PIP,
-            CUJ_LAUNCHER_QUICK_SWITCH,
-            CUJ_NOTIFICATION_HEADS_UP_APPEAR,
-            CUJ_NOTIFICATION_HEADS_UP_DISAPPEAR,
-            CUJ_NOTIFICATION_ADD,
-            CUJ_NOTIFICATION_REMOVE,
-            CUJ_NOTIFICATION_APP_START,
-            CUJ_LOCKSCREEN_PASSWORD_APPEAR,
-            CUJ_LOCKSCREEN_PATTERN_APPEAR,
-            CUJ_LOCKSCREEN_PIN_APPEAR,
-            CUJ_LOCKSCREEN_PASSWORD_DISAPPEAR,
-            CUJ_LOCKSCREEN_PATTERN_DISAPPEAR,
-            CUJ_LOCKSCREEN_PIN_DISAPPEAR,
-            CUJ_LOCKSCREEN_TRANSITION_FROM_AOD,
-            CUJ_LOCKSCREEN_TRANSITION_TO_AOD,
-            CUJ_LAUNCHER_OPEN_ALL_APPS,
-            CUJ_LAUNCHER_ALL_APPS_SCROLL,
-            CUJ_LAUNCHER_APP_LAUNCH_FROM_WIDGET,
-            CUJ_SETTINGS_PAGE_SCROLL,
-            CUJ_LOCKSCREEN_UNLOCK_ANIMATION,
-            CUJ_SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON,
-            CUJ_SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER,
-            CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE,
-            CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON,
-            CUJ_STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP,
-            CUJ_PIP_TRANSITION,
-            CUJ_WALLPAPER_TRANSITION,
-            CUJ_USER_SWITCH,
-            CUJ_SPLASHSCREEN_AVD,
-            CUJ_SPLASHSCREEN_EXIT_ANIM,
-            CUJ_SCREEN_OFF,
-            CUJ_SCREEN_OFF_SHOW_AOD,
-            CUJ_ONE_HANDED_ENTER_TRANSITION,
-            CUJ_ONE_HANDED_EXIT_TRANSITION,
-            CUJ_UNFOLD_ANIM,
-            CUJ_SUW_LOADING_TO_SHOW_INFO_WITH_ACTIONS,
-            CUJ_SUW_SHOW_FUNCTION_SCREEN_WITH_ACTIONS,
-            CUJ_SUW_LOADING_TO_NEXT_FLOW,
-            CUJ_SUW_LOADING_SCREEN_FOR_STATUS,
-            CUJ_SPLIT_SCREEN_ENTER,
-            CUJ_SPLIT_SCREEN_EXIT,
-            CUJ_LOCKSCREEN_LAUNCH_CAMERA,
-            CUJ_SPLIT_SCREEN_RESIZE,
-            CUJ_SETTINGS_SLIDER,
-            CUJ_TAKE_SCREENSHOT,
-            CUJ_VOLUME_CONTROL,
-            CUJ_BIOMETRIC_PROMPT_TRANSITION,
-            CUJ_SETTINGS_TOGGLE,
-            CUJ_SHADE_DIALOG_OPEN,
-            CUJ_USER_DIALOG_OPEN,
-            CUJ_TASKBAR_EXPAND,
-            CUJ_TASKBAR_COLLAPSE,
-            CUJ_SHADE_CLEAR_ALL,
-            CUJ_LAUNCHER_UNLOCK_ENTRANCE_ANIMATION,
-            CUJ_LOCKSCREEN_OCCLUSION,
-            CUJ_RECENTS_SCROLLING,
-            CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS,
-            CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE,
-            CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME,
-            CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION,
-            CUJ_LAUNCHER_OPEN_SEARCH_RESULT,
-            CUJ_LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK,
-            CUJ_IME_INSETS_SHOW_ANIMATION,
-            CUJ_IME_INSETS_HIDE_ANIMATION,
-            CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER,
-            CUJ_LAUNCHER_UNFOLD_ANIM,
-            CUJ_PREDICTIVE_BACK_CROSS_ACTIVITY,
-            CUJ_PREDICTIVE_BACK_CROSS_TASK,
-            CUJ_PREDICTIVE_BACK_HOME,
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface CujType {
-    }
-
     /**
      * Get the singleton of InteractionJankMonitor.
      *
@@ -511,71 +204,44 @@
     @VisibleForTesting
     @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
     public InteractionJankMonitor(@NonNull HandlerThread worker) {
-        mRunningTrackers = new SparseArray<>();
-        mTimeoutActions = new SparseArray<>();
-        mWorker = worker;
-        mWorker.start();
-        mDisplayResolutionTracker = new DisplayResolutionTracker(worker.getThreadHandler());
-        mSamplingInterval = DEFAULT_SAMPLING_INTERVAL;
-        mEnabled = DEFAULT_ENABLED;
+        worker.start();
+        mWorker = worker.getThreadHandler();
+        mDisplayResolutionTracker = new DisplayResolutionTracker(mWorker);
 
         final Context context = ActivityThread.currentApplication();
-        if (context.checkCallingOrSelfPermission(READ_DEVICE_CONFIG) != PERMISSION_GRANTED) {
-            if (DEBUG) {
-                Log.d(TAG, "Initialized the InteractionJankMonitor."
-                        + " (No READ_DEVICE_CONFIG permission to change configs)"
-                        + " enabled=" + mEnabled + ", interval=" + mSamplingInterval
-                        + ", missedFrameThreshold=" + mTraceThresholdMissedFrames
-                        + ", frameTimeThreshold=" + mTraceThresholdFrameTimeMillis
-                        + ", package=" + context.getPackageName());
-            }
+        if (context == null || context.checkCallingOrSelfPermission(READ_DEVICE_CONFIG) != PERMISSION_GRANTED) {
+            Log.w(TAG, "Initializing without READ_DEVICE_CONFIG permission."
+                    + " enabled=" + mEnabled + ", interval=" + mSamplingInterval
+                    + ", missedFrameThreshold=" + mTraceThresholdMissedFrames
+                    + ", frameTimeThreshold=" + mTraceThresholdFrameTimeMillis
+                    + ", package=" + (context == null ? "null" : context.getPackageName()));
             return;
         }
 
         // Post initialization to the background in case we're running on the main thread.
-        mWorker.getThreadHandler().post(
-                () -> {
-                    try {
-                        mPropertiesChangedListener.onPropertiesChanged(
-                                DeviceConfig.getProperties(NAMESPACE_INTERACTION_JANK_MONITOR));
-                        DeviceConfig.addOnPropertiesChangedListener(
-                                NAMESPACE_INTERACTION_JANK_MONITOR,
-                                new HandlerExecutor(mWorker.getThreadHandler()),
-                                mPropertiesChangedListener);
-                    } catch (SecurityException ex) {
-                        Log.d(TAG, "Can't get properties: READ_DEVICE_CONFIG granted="
-                                + context.checkCallingOrSelfPermission(READ_DEVICE_CONFIG)
-                                + ", package=" + context.getPackageName());
-                    }
-                });
+        mWorker.post(() -> {
+            try {
+                updateProperties(DeviceConfig.getProperties(NAMESPACE_INTERACTION_JANK_MONITOR));
+                DeviceConfig.addOnPropertiesChangedListener(NAMESPACE_INTERACTION_JANK_MONITOR,
+                        new HandlerExecutor(mWorker), this::updateProperties);
+            } catch (SecurityException ex) {
+                Log.d(TAG, "Can't get properties: READ_DEVICE_CONFIG granted="
+                        + context.checkCallingOrSelfPermission(READ_DEVICE_CONFIG)
+                        + ", package=" + context.getPackageName());
+            }
+        });
     }
 
     /**
      * Creates a {@link FrameTracker} instance.
      *
-     * @param config the config used in instrumenting
-     * @param session the session associates with this tracker
+     * @param config the conifg associates with this tracker
      * @return instance of the FrameTracker
      */
     @VisibleForTesting
-    public FrameTracker createFrameTracker(Configuration config, Session session) {
+    public FrameTracker createFrameTracker(Configuration config) {
         final View view = config.mView;
 
-        if (!config.hasValidView()) {
-            boolean attached = false;
-            boolean hasViewRoot = false;
-            boolean hasRenderer = false;
-            if (view != null) {
-                attached = view.isAttachedToWindow();
-                hasViewRoot = view.getViewRootImpl() != null;
-                hasRenderer = view.getThreadedRenderer() != null;
-            }
-            Log.d(TAG, "create FrameTracker fails: view=" + view
-                    + ", attached=" + attached + ", hasViewRoot=" + hasViewRoot
-                    + ", hasRenderer=" + hasRenderer, new Throwable());
-            return null;
-        }
-
         final ThreadedRendererWrapper threadedRenderer =
                 view == null ? null : new ThreadedRendererWrapper(view.getThreadedRenderer());
         final ViewRootWrapper viewRoot =
@@ -583,52 +249,50 @@
         final SurfaceControlWrapper surfaceControl = new SurfaceControlWrapper();
         final ChoreographerWrapper choreographer =
                 new ChoreographerWrapper(Choreographer.getInstance());
-        final FrameTrackerListener eventsListener = (s, act) -> handleCujEvents(act, s);
+        final FrameTrackerListener eventsListener = new FrameTrackerListener() {
+            @Override
+            public void onCujEvents(FrameTracker tracker, String action, int reason) {
+                config.getHandler().runWithScissors(() ->
+                        handleCujEvents(config.mCujType, tracker, action, reason),
+                        EXECUTOR_TASK_TIMEOUT);
+            }
+
+            @Override
+            public void triggerPerfetto(Configuration config) {
+                mWorker.post(() -> PerfettoTrigger.trigger(config.getPerfettoTrigger()));
+            }
+        };
         final FrameMetricsWrapper frameMetrics = new FrameMetricsWrapper();
 
-        return new FrameTracker(this, session, config.getHandler(), threadedRenderer, viewRoot,
+        return new FrameTracker(config, threadedRenderer, viewRoot,
                 surfaceControl, choreographer, frameMetrics,
                 new FrameTracker.StatsLogWrapper(mDisplayResolutionTracker),
                 mTraceThresholdMissedFrames, mTraceThresholdFrameTimeMillis,
-                eventsListener, config);
+                eventsListener);
     }
 
     @UiThread
-    private void handleCujEvents(String action, Session session) {
+    private void handleCujEvents(
+            @Cuj.CujType int cuj, FrameTracker tracker, String action, @Reasons int reason) {
         // Clear the running and timeout tasks if the end / cancel was fired within the tracker.
         // Or we might have memory leaks.
-        if (needRemoveTasks(action, session)) {
-            getTracker(session.getCuj()).getHandler().runWithScissors(() -> {
-                removeTimeout(session.getCuj());
-                removeTracker(session.getCuj(), session.getReason());
-            }, EXECUTOR_TASK_TIMEOUT);
+        if (needRemoveTasks(action, reason)) {
+            removeTrackerIfCurrent(cuj, tracker, reason);
         }
     }
 
-    private boolean needRemoveTasks(String action, Session session) {
-        final boolean badEnd = action.equals(ACTION_SESSION_END)
-                && session.getReason() != REASON_END_NORMAL;
+    private static boolean needRemoveTasks(String action, @Reasons int reason) {
+        final boolean badEnd = action.equals(ACTION_SESSION_END) && reason != REASON_END_NORMAL;
         final boolean badCancel = action.equals(ACTION_SESSION_CANCEL)
-                && !(session.getReason() == REASON_CANCEL_NORMAL
-                || session.getReason() == REASON_CANCEL_TIMEOUT);
+                && !(reason == REASON_CANCEL_NORMAL || reason == REASON_CANCEL_TIMEOUT);
         return badEnd || badCancel;
     }
 
-    private void removeTimeout(@CujType int cujType) {
-        synchronized (mLock) {
-            Runnable timeout = mTimeoutActions.get(cujType);
-            if (timeout != null) {
-                getTracker(cujType).getHandler().removeCallbacks(timeout);
-                mTimeoutActions.remove(cujType);
-            }
-        }
-    }
-
     /**
      * @param cujType cuj type
      * @return true if the cuj is under instrumenting, false otherwise.
      */
-    public boolean isInstrumenting(@CujType int cujType) {
+    public boolean isInstrumenting(@Cuj.CujType int cujType) {
         synchronized (mLock) {
             return mRunningTrackers.contains(cujType);
         }
@@ -638,10 +302,10 @@
      * Begins a trace session.
      *
      * @param v an attached view.
-     * @param cujType the specific {@link InteractionJankMonitor.CujType}.
+     * @param cujType the specific {@link Cuj.CujType}.
      * @return boolean true if the tracker is started successfully, false otherwise.
      */
-    public boolean begin(View v, @CujType int cujType) {
+    public boolean begin(View v, @Cuj.CujType int cujType) {
         try {
             return begin(Configuration.Builder.withView(cujType, v));
         } catch (IllegalArgumentException ex) {
@@ -667,7 +331,7 @@
             final boolean success = config.getHandler().runWithScissors(
                     () -> result.mResult = beginInternal(config), EXECUTOR_TASK_TIMEOUT);
             if (!success) {
-                Log.d(TAG, "begin failed due to timeout, CUJ=" + getNameOfCuj(config.mCujType));
+                Log.d(TAG, "begin failed due to timeout, CUJ=" + Cuj.getNameOfCuj(config.mCujType));
                 return false;
             }
             return result.mResult;
@@ -680,75 +344,59 @@
     @UiThread
     private boolean beginInternal(@NonNull Configuration conf) {
         int cujType = conf.mCujType;
-        if (!shouldMonitor(cujType)) return false;
-        FrameTracker tracker = getTracker(cujType);
-        // Skip subsequent calls if we already have an ongoing tracing.
-        if (tracker != null) return false;
+        if (!shouldMonitor()) {
+            return false;
+        }
 
-        // begin a new trace session.
-        tracker = createFrameTracker(conf, new Session(cujType, conf.mTag));
-        if (tracker == null) return false;
-        putTracker(cujType, tracker);
-        tracker.begin();
+        RunningTracker tracker = putTrackerIfNoCurrent(cujType, () ->
+                new RunningTracker(
+                    conf, createFrameTracker(conf), () -> cancel(cujType, REASON_CANCEL_TIMEOUT)));
+        if (tracker == null) {
+            return false;
+        }
 
+        tracker.mTracker.begin();
         // Cancel the trace if we don't get an end() call in specified duration.
-        scheduleTimeoutAction(
-                cujType, conf.mTimeout, () -> cancel(cujType, REASON_CANCEL_TIMEOUT));
+        scheduleTimeoutAction(tracker.mConfig, tracker.mTimeoutAction);
+
         return true;
     }
 
     /**
      * Check if the monitoring is enabled and if it should be sampled.
      */
-    @SuppressWarnings("RandomModInteger")
     @VisibleForTesting
-    public boolean shouldMonitor(@CujType int cujType) {
-        boolean shouldSample = ThreadLocalRandom.current().nextInt() % mSamplingInterval == 0;
-        if (!mEnabled || !shouldSample) {
-            if (DEBUG) {
-                Log.d(TAG, "Skip monitoring cuj: " + getNameOfCuj(cujType)
-                        + ", enable=" + mEnabled + ", debuggable=" + DEFAULT_ENABLED
-                        + ", sample=" + shouldSample + ", interval=" + mSamplingInterval);
-            }
-            return false;
-        }
-        return true;
+    public boolean shouldMonitor() {
+        return mEnabled && (ThreadLocalRandom.current().nextInt(mSamplingInterval) == 0);
     }
 
-    /**
-     * Schedules a timeout action.
-     * @param cuj cuj type
-     * @param timeout duration to timeout
-     * @param action action once timeout
-     */
     @VisibleForTesting
-    public void scheduleTimeoutAction(@CujType int cuj, long timeout, Runnable action) {
-        synchronized (mLock) {
-            mTimeoutActions.put(cuj, action);
-            getTracker(cuj).getHandler().postDelayed(action, timeout);
-        }
+    public void scheduleTimeoutAction(Configuration config, Runnable action) {
+        config.getHandler().postDelayed(action, config.mTimeout);
     }
 
     /**
      * Ends a trace session.
      *
-     * @param cujType the specific {@link InteractionJankMonitor.CujType}.
+     * @param cujType the specific {@link Cuj.CujType}.
      * @return boolean true if the tracker is ended successfully, false otherwise.
      */
-    public boolean end(@CujType int cujType) {
+    public boolean end(@Cuj.CujType int cujType) {
         postEventLogToWorkerThread((unixNanos, elapsedNanos, realtimeNanos) -> {
             EventLogTags.writeJankCujEventsEndRequest(
                     cujType, unixNanos, elapsedNanos, realtimeNanos);
         });
-        FrameTracker tracker = getTracker(cujType);
+        RunningTracker tracker = getTracker(cujType);
         // Skip this call since we haven't started a trace yet.
-        if (tracker == null) return false;
+        if (tracker == null) {
+            return false;
+        }
         try {
             final TrackerResult result = new TrackerResult();
-            final boolean success = tracker.getHandler().runWithScissors(
-                    () -> result.mResult = endInternal(cujType), EXECUTOR_TASK_TIMEOUT);
+            final boolean success = tracker.mConfig.getHandler().runWithScissors(
+                    () -> result.mResult = endInternal(tracker), EXECUTOR_TASK_TIMEOUT);
             if (!success) {
-                Log.d(TAG, "end failed due to timeout, CUJ=" + getNameOfCuj(cujType));
+                Log.d(TAG, "end failed due to timeout, CUJ=" + Cuj.getNameOfCuj(cujType));
                 return false;
             }
             return result.mResult;
@@ -759,15 +407,11 @@
     }
 
     @UiThread
-    private boolean endInternal(@CujType int cujType) {
-        // remove the timeout action first.
-        removeTimeout(cujType);
-        FrameTracker tracker = getTracker(cujType);
-        if (tracker == null) return false;
-        // if the end call doesn't return true, another thread is handling end of the cuj.
-        if (tracker.end(REASON_END_NORMAL)) {
-            removeTracker(cujType, REASON_END_NORMAL);
+    private boolean endInternal(RunningTracker tracker) {
+        if (removeTrackerIfCurrent(tracker, REASON_END_NORMAL)) {
+            return false;
         }
+        tracker.mTracker.end(REASON_END_NORMAL);
         return true;
     }
 
@@ -776,7 +420,7 @@
      *
      * @return boolean true if the tracker is cancelled successfully, false otherwise.
      */
-    public boolean cancel(@CujType int cujType) {
+    public boolean cancel(@Cuj.CujType int cujType) {
         postEventLogToWorkerThread((unixNanos, elapsedNanos, realtimeNanos) -> {
             EventLogTags.writeJankCujEventsCancelRequest(
                     cujType, unixNanos, elapsedNanos, realtimeNanos);
@@ -790,16 +434,18 @@
      * @return boolean true if the tracker is cancelled successfully, false otherwise.
      */
     @VisibleForTesting
-    public boolean cancel(@CujType int cujType, @Reasons int reason) {
-        FrameTracker tracker = getTracker(cujType);
+    public boolean cancel(@Cuj.CujType int cujType, @Reasons int reason) {
+        RunningTracker tracker = getTracker(cujType);
         // Skip this call since we haven't started a trace yet.
-        if (tracker == null) return false;
+        if (tracker == null) {
+            return false;
+        }
         try {
             final TrackerResult result = new TrackerResult();
-            final boolean success = tracker.getHandler().runWithScissors(
-                    () -> result.mResult = cancelInternal(cujType, reason), EXECUTOR_TASK_TIMEOUT);
+            final boolean success = tracker.mConfig.getHandler().runWithScissors(
+                    () -> result.mResult = cancelInternal(tracker, reason), EXECUTOR_TASK_TIMEOUT);
             if (!success) {
-                Log.d(TAG, "cancel failed due to timeout, CUJ=" + getNameOfCuj(cujType));
+                Log.d(TAG, "cancel failed due to timeout, CUJ=" + Cuj.getNameOfCuj(cujType));
                 return false;
             }
             return result.mResult;
@@ -810,71 +456,86 @@
     }
 
     @UiThread
-    private boolean cancelInternal(@CujType int cujType, @Reasons int reason) {
-        // remove the timeout action first.
-        removeTimeout(cujType);
-        FrameTracker tracker = getTracker(cujType);
-        if (tracker == null) return false;
-        // if the cancel call doesn't return true, another thread is handling cancel of the cuj.
-        if (tracker.cancel(reason)) {
-            removeTracker(cujType, reason);
+    private boolean cancelInternal(RunningTracker tracker, @Reasons int reason) {
+        if (removeTrackerIfCurrent(tracker, reason)) {
+            return false;
         }
+        tracker.mTracker.cancel(reason);
         return true;
     }
 
     @UiThread
-    private void putTracker(@CujType int cuj, @NonNull FrameTracker tracker) {
+    private RunningTracker putTrackerIfNoCurrent(
+            @Cuj.CujType int cuj, Supplier<RunningTracker> supplier) {
         synchronized (mLock) {
+            if (mRunningTrackers.contains(cuj)) {
+                return null;
+            }
+
+            RunningTracker tracker = supplier.get();
+            if (tracker == null) {
+                return null;
+            }
+
             mRunningTrackers.put(cuj, tracker);
             if (mDebugOverlay != null) {
                 mDebugOverlay.onTrackerAdded(cuj, tracker);
             }
-            if (DEBUG) {
-                Log.d(TAG, "Added tracker for " + getNameOfCuj(cuj)
-                        + ". mRunningTrackers=" + listNamesOfCujs(mRunningTrackers));
-            }
+
+            return tracker;
         }
     }
 
-    private FrameTracker getTracker(@CujType int cuj) {
+    private RunningTracker getTracker(@Cuj.CujType int cuj) {
         synchronized (mLock) {
             return mRunningTrackers.get(cuj);
         }
     }
 
+    /**
+     * @return {@code true} if another tracker is current
+     */
     @UiThread
-    private void removeTracker(@CujType int cuj, int reason) {
+    private boolean removeTrackerIfCurrent(RunningTracker tracker, int reason) {
+        return removeTrackerIfCurrent(tracker.mConfig.mCujType, tracker.mTracker, reason);
+    }
+
+    /**
+     * @return {@code true} if another tracker is current
+     */
+    @UiThread
+    private boolean removeTrackerIfCurrent(@Cuj.CujType int cuj, FrameTracker tracker, int reason) {
         synchronized (mLock) {
+            RunningTracker running = mRunningTrackers.get(cuj);
+            if (running == null || running.mTracker != tracker) {
+                return true;
+            }
+
+            running.mConfig.getHandler().removeCallbacks(running.mTimeoutAction);
             mRunningTrackers.remove(cuj);
             if (mDebugOverlay != null) {
                 mDebugOverlay.onTrackerRemoved(cuj, reason, mRunningTrackers);
             }
-            if (DEBUG) {
-                Log.d(TAG, "Removed tracker for " + getNameOfCuj(cuj)
-                        + ". mRunningTrackers=" + listNamesOfCujs(mRunningTrackers));
-            }
+            return false;
         }
     }
 
     @WorkerThread
-    private void updateProperties(DeviceConfig.Properties properties) {
+    @VisibleForTesting
+    public void updateProperties(DeviceConfig.Properties properties) {
         for (String property : properties.getKeyset()) {
             switch (property) {
-                case SETTINGS_SAMPLING_INTERVAL_KEY:
-                    mSamplingInterval = properties.getInt(property, DEFAULT_SAMPLING_INTERVAL);
-                    break;
-                case SETTINGS_THRESHOLD_MISSED_FRAMES_KEY:
-                    mTraceThresholdMissedFrames =
-                            properties.getInt(property, DEFAULT_TRACE_THRESHOLD_MISSED_FRAMES);
-                    break;
-                case SETTINGS_THRESHOLD_FRAME_TIME_MILLIS_KEY:
-                    mTraceThresholdFrameTimeMillis =
-                            properties.getInt(property, DEFAULT_TRACE_THRESHOLD_FRAME_TIME_MILLIS);
-                    break;
-                case SETTINGS_ENABLED_KEY:
-                    mEnabled = properties.getBoolean(property, DEFAULT_ENABLED);
-                    break;
-                case SETTINGS_DEBUG_OVERLAY_ENABLED_KEY:
+                case SETTINGS_SAMPLING_INTERVAL_KEY ->
+                        mSamplingInterval = properties.getInt(property, DEFAULT_SAMPLING_INTERVAL);
+                case SETTINGS_THRESHOLD_MISSED_FRAMES_KEY ->
+                        mTraceThresholdMissedFrames =
+                                properties.getInt(property, DEFAULT_TRACE_THRESHOLD_MISSED_FRAMES);
+                case SETTINGS_THRESHOLD_FRAME_TIME_MILLIS_KEY ->
+                        mTraceThresholdFrameTimeMillis =
+                                properties.getInt(property, DEFAULT_TRACE_THRESHOLD_FRAME_TIME_MILLIS);
+                case SETTINGS_ENABLED_KEY ->
+                        mEnabled = properties.getBoolean(property, DEFAULT_ENABLED);
+                case SETTINGS_DEBUG_OVERLAY_ENABLED_KEY -> {
                     // Never allow the debug overlay to be used on user builds
                     boolean debugOverlayEnabled = Build.IS_DEBUGGABLE
                             && properties.getBoolean(property, DEFAULT_DEBUG_OVERLAY_ENABLED);
@@ -885,49 +546,35 @@
                         mDebugOverlay.dispose();
                         mDebugOverlay = null;
                     }
-                    break;
-                default:
-                    if (DEBUG) {
-                        Log.d(TAG, "Got a change event for an unknown property: "
-                                + property + " => " + properties.getString(property, ""));
-                    }
+                }
+                default -> Log.w(TAG, "Got a change event for an unknown property: "
+                        + property + " => " + properties.getString(property, ""));
             }
         }
     }
 
-    @VisibleForTesting
-    public DeviceConfig.OnPropertiesChangedListener getPropertiesChangedListener() {
-        return mPropertiesChangedListener;
-    }
-
-    /**
-     * Triggers the perfetto daemon to collect and upload data.
-     */
-    @VisibleForTesting
-    public void trigger(Session session) {
-        mWorker.getThreadHandler().post(
-                () -> PerfettoTrigger.trigger(session.getPerfettoTrigger()));
-    }
-
     /**
      * A helper method to translate interaction type to CUJ name.
      *
      * @param interactionType the interaction type defined in AtomsProto.java
      * @return the name of the interaction type
+     * @deprecated use {@link Cuj#getNameOfInteraction(int)}
      */
+    @Deprecated
     public static String getNameOfInteraction(int interactionType) {
-        // There is an offset amount of 1 between cujType and interactionType.
-        return getNameOfCuj(getCujTypeFromInteraction(interactionType));
+        return Cuj.getNameOfInteraction(interactionType);
     }
 
     /**
-     * A helper method to translate interaction type to CUJ type.
+     * A helper method to translate CUJ type to CUJ name.
      *
-     * @param interactionType the interaction type defined in AtomsProto.java
-     * @return the integer in {@link CujType}
+     * @param cujType the cuj type defined in this file
+     * @return the name of the cuj type
+     * @deprecated use {@link Cuj#getNameOfCuj(int)}
      */
-    private static int getCujTypeFromInteraction(int interactionType) {
-        return interactionType - 1;
+    @Deprecated
+    public static String getNameOfCuj(int cujType) {
+        return Cuj.getNameOfCuj(cujType);
     }
 
     /**
@@ -943,195 +590,14 @@
         mDebugYOffset = yOffset;
     }
 
-    /**
-     * A helper method for getting a string representation of all running CUJs. For example,
-     * "(LOCKSCREEN_TRANSITION_FROM_AOD, IME_INSETS_ANIMATION)"
-     */
-    private static String listNamesOfCujs(SparseArray<FrameTracker> trackers) {
-        if (!DEBUG) {
-            return null;
-        }
-        StringBuilder sb = new StringBuilder();
-        sb.append('(');
-        for (int i = 0; i < trackers.size(); i++) {
-            sb.append(getNameOfCuj(trackers.keyAt(i)));
-            if (i < trackers.size() - 1) {
-                sb.append(", ");
-            }
-        }
-        sb.append(')');
-        return sb.toString();
-    }
+    private void postEventLogToWorkerThread(TimeFunction logFunction) {
+        final Instant now = Instant.now();
+        final long unixNanos = TimeUnit.NANOSECONDS.convert(now.getEpochSecond(), TimeUnit.SECONDS)
+                + now.getNano();
+        final long elapsedNanos = SystemClock.elapsedRealtimeNanos();
+        final long realtimeNanos = SystemClock.uptimeNanos();
 
-    /**
-     * A helper method to translate CUJ type to CUJ name.
-     *
-     * @param cujType the cuj type defined in this file
-     * @return the name of the cuj type
-     */
-    public static String getNameOfCuj(int cujType) {
-        // Please note:
-        // 1. The length of the returned string shouldn't exceed MAX_LENGTH_OF_CUJ_NAME.
-        // 2. The returned string should be the same with the name defined in atoms.proto.
-        switch (cujType) {
-            case CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE:
-                return "NOTIFICATION_SHADE_EXPAND_COLLAPSE";
-            case CUJ_NOTIFICATION_SHADE_SCROLL_FLING:
-                return "NOTIFICATION_SHADE_SCROLL_FLING";
-            case CUJ_NOTIFICATION_SHADE_ROW_EXPAND:
-                return "NOTIFICATION_SHADE_ROW_EXPAND";
-            case CUJ_NOTIFICATION_SHADE_ROW_SWIPE:
-                return "NOTIFICATION_SHADE_ROW_SWIPE";
-            case CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE:
-                return "NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE";
-            case CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE:
-                return "NOTIFICATION_SHADE_QS_SCROLL_SWIPE";
-            case CUJ_LAUNCHER_APP_LAUNCH_FROM_RECENTS:
-                return "LAUNCHER_APP_LAUNCH_FROM_RECENTS";
-            case CUJ_LAUNCHER_APP_LAUNCH_FROM_ICON:
-                return "LAUNCHER_APP_LAUNCH_FROM_ICON";
-            case CUJ_LAUNCHER_APP_CLOSE_TO_HOME:
-                return "LAUNCHER_APP_CLOSE_TO_HOME";
-            case CUJ_LAUNCHER_APP_CLOSE_TO_PIP:
-                return "LAUNCHER_APP_CLOSE_TO_PIP";
-            case CUJ_LAUNCHER_QUICK_SWITCH:
-                return "LAUNCHER_QUICK_SWITCH";
-            case CUJ_NOTIFICATION_HEADS_UP_APPEAR:
-                return "NOTIFICATION_HEADS_UP_APPEAR";
-            case CUJ_NOTIFICATION_HEADS_UP_DISAPPEAR:
-                return "NOTIFICATION_HEADS_UP_DISAPPEAR";
-            case CUJ_NOTIFICATION_ADD:
-                return "NOTIFICATION_ADD";
-            case CUJ_NOTIFICATION_REMOVE:
-                return "NOTIFICATION_REMOVE";
-            case CUJ_NOTIFICATION_APP_START:
-                return "NOTIFICATION_APP_START";
-            case CUJ_LOCKSCREEN_PASSWORD_APPEAR:
-                return "LOCKSCREEN_PASSWORD_APPEAR";
-            case CUJ_LOCKSCREEN_PATTERN_APPEAR:
-                return "LOCKSCREEN_PATTERN_APPEAR";
-            case CUJ_LOCKSCREEN_PIN_APPEAR:
-                return "LOCKSCREEN_PIN_APPEAR";
-            case CUJ_LOCKSCREEN_PASSWORD_DISAPPEAR:
-                return "LOCKSCREEN_PASSWORD_DISAPPEAR";
-            case CUJ_LOCKSCREEN_PATTERN_DISAPPEAR:
-                return "LOCKSCREEN_PATTERN_DISAPPEAR";
-            case CUJ_LOCKSCREEN_PIN_DISAPPEAR:
-                return "LOCKSCREEN_PIN_DISAPPEAR";
-            case CUJ_LOCKSCREEN_TRANSITION_FROM_AOD:
-                return "LOCKSCREEN_TRANSITION_FROM_AOD";
-            case CUJ_LOCKSCREEN_TRANSITION_TO_AOD:
-                return "LOCKSCREEN_TRANSITION_TO_AOD";
-            case CUJ_LAUNCHER_OPEN_ALL_APPS :
-                return "LAUNCHER_OPEN_ALL_APPS";
-            case CUJ_LAUNCHER_ALL_APPS_SCROLL:
-                return "LAUNCHER_ALL_APPS_SCROLL";
-            case CUJ_LAUNCHER_APP_LAUNCH_FROM_WIDGET:
-                return "LAUNCHER_APP_LAUNCH_FROM_WIDGET";
-            case CUJ_SETTINGS_PAGE_SCROLL:
-                return "SETTINGS_PAGE_SCROLL";
-            case CUJ_LOCKSCREEN_UNLOCK_ANIMATION:
-                return "LOCKSCREEN_UNLOCK_ANIMATION";
-            case CUJ_SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON:
-                return "SHADE_APP_LAUNCH_FROM_HISTORY_BUTTON";
-            case CUJ_SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER:
-                return "SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER";
-            case CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE:
-                return "SHADE_APP_LAUNCH_FROM_QS_TILE";
-            case CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON:
-                return "SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON";
-            case CUJ_STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP:
-                return "STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP";
-            case CUJ_PIP_TRANSITION:
-                return "PIP_TRANSITION";
-            case CUJ_WALLPAPER_TRANSITION:
-                return "WALLPAPER_TRANSITION";
-            case CUJ_USER_SWITCH:
-                return "USER_SWITCH";
-            case CUJ_SPLASHSCREEN_AVD:
-                return "SPLASHSCREEN_AVD";
-            case CUJ_SPLASHSCREEN_EXIT_ANIM:
-                return "SPLASHSCREEN_EXIT_ANIM";
-            case CUJ_SCREEN_OFF:
-                return "SCREEN_OFF";
-            case CUJ_SCREEN_OFF_SHOW_AOD:
-                return "SCREEN_OFF_SHOW_AOD";
-            case CUJ_ONE_HANDED_ENTER_TRANSITION:
-                return "ONE_HANDED_ENTER_TRANSITION";
-            case CUJ_ONE_HANDED_EXIT_TRANSITION:
-                return "ONE_HANDED_EXIT_TRANSITION";
-            case CUJ_UNFOLD_ANIM:
-                return "UNFOLD_ANIM";
-            case CUJ_SUW_LOADING_TO_SHOW_INFO_WITH_ACTIONS:
-                return "SUW_LOADING_TO_SHOW_INFO_WITH_ACTIONS";
-            case CUJ_SUW_SHOW_FUNCTION_SCREEN_WITH_ACTIONS:
-                return "SUW_SHOW_FUNCTION_SCREEN_WITH_ACTIONS";
-            case CUJ_SUW_LOADING_TO_NEXT_FLOW:
-                return "SUW_LOADING_TO_NEXT_FLOW";
-            case CUJ_SUW_LOADING_SCREEN_FOR_STATUS:
-                return "SUW_LOADING_SCREEN_FOR_STATUS";
-            case CUJ_SPLIT_SCREEN_ENTER:
-                return "SPLIT_SCREEN_ENTER";
-            case CUJ_SPLIT_SCREEN_EXIT:
-                return "SPLIT_SCREEN_EXIT";
-            case CUJ_LOCKSCREEN_LAUNCH_CAMERA:
-                return "LOCKSCREEN_LAUNCH_CAMERA";
-            case CUJ_SPLIT_SCREEN_RESIZE:
-                return "SPLIT_SCREEN_RESIZE";
-            case CUJ_SETTINGS_SLIDER:
-                return "SETTINGS_SLIDER";
-            case CUJ_TAKE_SCREENSHOT:
-                return "TAKE_SCREENSHOT";
-            case CUJ_VOLUME_CONTROL:
-                return "VOLUME_CONTROL";
-            case CUJ_BIOMETRIC_PROMPT_TRANSITION:
-                return "BIOMETRIC_PROMPT_TRANSITION";
-            case CUJ_SETTINGS_TOGGLE:
-                return "SETTINGS_TOGGLE";
-            case CUJ_SHADE_DIALOG_OPEN:
-                return "SHADE_DIALOG_OPEN";
-            case CUJ_USER_DIALOG_OPEN:
-                return "USER_DIALOG_OPEN";
-            case CUJ_TASKBAR_EXPAND:
-                return "TASKBAR_EXPAND";
-            case CUJ_TASKBAR_COLLAPSE:
-                return "TASKBAR_COLLAPSE";
-            case CUJ_SHADE_CLEAR_ALL:
-                return "SHADE_CLEAR_ALL";
-            case CUJ_LAUNCHER_UNLOCK_ENTRANCE_ANIMATION:
-                return "LAUNCHER_UNLOCK_ENTRANCE_ANIMATION";
-            case CUJ_LOCKSCREEN_OCCLUSION:
-                return "LOCKSCREEN_OCCLUSION";
-            case CUJ_RECENTS_SCROLLING:
-                return "RECENTS_SCROLLING";
-            case CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS:
-                return "LAUNCHER_APP_SWIPE_TO_RECENTS";
-            case CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE:
-                return "LAUNCHER_CLOSE_ALL_APPS_SWIPE";
-            case CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME:
-                return "LAUNCHER_CLOSE_ALL_APPS_TO_HOME";
-            case CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION:
-                return "LOCKSCREEN_CLOCK_MOVE_ANIMATION";
-            case CUJ_LAUNCHER_OPEN_SEARCH_RESULT:
-                return "LAUNCHER_OPEN_SEARCH_RESULT";
-            case CUJ_LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK:
-                return "LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK";
-            case CUJ_IME_INSETS_SHOW_ANIMATION:
-                return "IME_INSETS_SHOW_ANIMATION";
-            case CUJ_IME_INSETS_HIDE_ANIMATION:
-                return "IME_INSETS_HIDE_ANIMATION";
-            case CUJ_SPLIT_SCREEN_DOUBLE_TAP_DIVIDER:
-                return "SPLIT_SCREEN_DOUBLE_TAP_DIVIDER";
-            case CUJ_LAUNCHER_UNFOLD_ANIM:
-                return "LAUNCHER_UNFOLD_ANIM";
-            case CUJ_PREDICTIVE_BACK_CROSS_ACTIVITY:
-                return "PREDICTIVE_BACK_CROSS_ACTIVITY";
-            case CUJ_PREDICTIVE_BACK_CROSS_TASK:
-                return "PREDICTIVE_BACK_CROSS_TASK";
-            case CUJ_PREDICTIVE_BACK_HOME:
-                return "PREDICTIVE_BACK_HOME";
-        }
-        return "UNKNOWN";
+        mWorker.post(() -> logFunction.invoke(unixNanos, elapsedNanos, realtimeNanos));
     }
 
     private static class TrackerResult {
@@ -1147,9 +613,10 @@
         private final Context mContext;
         private final long mTimeout;
         private final String mTag;
+        private final String mSessionName;
         private final boolean mSurfaceOnly;
         private final SurfaceControl mSurfaceControl;
-        private final @CujType int mCujType;
+        private final @Cuj.CujType int mCujType;
         private final boolean mDeferMonitor;
         private final Handler mHandler;
 
@@ -1167,17 +634,17 @@
             private String mAttrTag = "";
             private boolean mAttrSurfaceOnly;
             private SurfaceControl mAttrSurfaceControl;
-            private @CujType int mAttrCujType;
+            private final @Cuj.CujType int mAttrCujType;
             private boolean mAttrDeferMonitor = true;
 
             /**
              * Creates a builder which instruments only surface.
-             * @param cuj The enum defined in {@link InteractionJankMonitor.CujType}.
+             * @param cuj The enum defined in {@link Cuj.CujType}.
              * @param context context
              * @param surfaceControl surface control
              * @return builder
              */
-            public static Builder withSurface(@CujType int cuj, @NonNull Context context,
+            public static Builder withSurface(@Cuj.CujType int cuj, @NonNull Context context,
                     @NonNull SurfaceControl surfaceControl) {
                 return new Builder(cuj)
                         .setContext(context)
@@ -1187,16 +654,17 @@
 
             /**
              * Creates a builder which instruments both surface and view.
-             * @param cuj The enum defined in {@link InteractionJankMonitor.CujType}.
+             * @param cuj The enum defined in {@link Cuj.CujType}.
              * @param view view
              * @return builder
              */
-            public static Builder withView(@CujType int cuj, @NonNull View view) {
-                return new Builder(cuj).setView(view)
+            public static Builder withView(@Cuj.CujType int cuj, @NonNull View view) {
+                return new Builder(cuj)
+                        .setView(view)
                         .setContext(view.getContext());
             }
 
-            private Builder(@CujType int cuj) {
+            private Builder(@Cuj.CujType int cuj) {
                 mAttrCujType = cuj;
             }
 
@@ -1281,11 +749,12 @@
             }
         }
 
-        private Configuration(@CujType int cuj, View view, String tag, long timeout,
+        private Configuration(@Cuj.CujType int cuj, View view, @NonNull String tag, long timeout,
                 boolean surfaceOnly, Context context, SurfaceControl surfaceControl,
                 boolean deferMonitor) {
             mCujType = cuj;
             mTag = tag;
+            mSessionName = generateSessionName(Cuj.getNameOfCuj(cuj), tag);
             mTimeout = timeout;
             mView = view;
             mSurfaceOnly = surfaceOnly;
@@ -1298,6 +767,23 @@
             mHandler = mSurfaceOnly ? mContext.getMainThreadHandler() : mView.getHandler();
         }
 
+        @VisibleForTesting
+        public static String generateSessionName(
+                @NonNull String cujName, @NonNull String cujPostfix) {
+            final boolean hasPostfix = !TextUtils.isEmpty(cujPostfix);
+            if (hasPostfix) {
+                final int remaining = MAX_LENGTH_SESSION_NAME - cujName.length();
+                if (cujPostfix.length() > remaining) {
+                    cujPostfix = cujPostfix.substring(0, remaining - 3).concat("...");
+                }
+            }
+            // The max length of the whole string should be:
+            // 105 with postfix, 83 without postfix
+            return hasPostfix
+                    ? TextUtils.formatSimple("J<%s::%s>", cujName, cujPostfix)
+                    : TextUtils.formatSimple("J<%s>", cujName);
+        }
+
         private void validate() {
             boolean shouldThrow = false;
             final StringBuilder msg = new StringBuilder();
@@ -1360,10 +846,10 @@
             return mSurfaceControl;
         }
 
-        @VisibleForTesting
         /**
          * @return a view which is attached to the view tree.
          */
+        @VisibleForTesting
         public View getView() {
             return mView;
         }
@@ -1375,7 +861,7 @@
             return mDeferMonitor;
         }
 
-        @VisibleForTesting
+        @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
         public Handler getHandler() {
             return mHandler;
         }
@@ -1387,79 +873,27 @@
         public int getDisplayId() {
             return (mSurfaceOnly ? mContext : mView.getContext()).getDisplayId();
         }
-    }
 
-    /**
-     * A class to represent a session.
-     */
-    public static class Session {
-        @CujType
-        private final int mCujType;
-        private final long mTimeStamp;
-        @Reasons
-        private int mReason = REASON_END_UNKNOWN;
-        private final String mName;
-
-        public Session(@CujType int cujType, @NonNull String postfix) {
-            mCujType = cujType;
-            mTimeStamp = System.nanoTime();
-            mName = generateSessionName(getNameOfCuj(cujType), postfix);
-        }
-
-        private String generateSessionName(@NonNull String cujName, @NonNull String cujPostfix) {
-            final boolean hasPostfix = !TextUtils.isEmpty(cujPostfix);
-            // We assert that the cujName shouldn't exceed MAX_LENGTH_OF_CUJ_NAME.
-            if (cujName.length() > MAX_LENGTH_OF_CUJ_NAME) {
-                throw new IllegalArgumentException(TextUtils.formatSimple(
-                        "The length of cuj name <%s> exceeds %d", cujName, MAX_LENGTH_OF_CUJ_NAME));
-            }
-            if (hasPostfix) {
-                final int remaining = MAX_LENGTH_SESSION_NAME - cujName.length();
-                if (cujPostfix.length() > remaining) {
-                    cujPostfix = cujPostfix.substring(0, remaining - 3).concat("...");
-                }
-            }
-            // The max length of the whole string should be:
-            // 105 with postfix, 83 without postfix
-            return hasPostfix
-                    ? TextUtils.formatSimple("J<%s::%s>", cujName, cujPostfix)
-                    : TextUtils.formatSimple("J<%s>", cujName);
-        }
-
-        @CujType
-        public int getCuj() {
-            return mCujType;
+        public String getSessionName() {
+            return mSessionName;
         }
 
         public int getStatsdInteractionType() {
-            return CUJ_TO_STATSD_INTERACTION_TYPE[mCujType];
+            return Cuj.getStatsdInteractionType(mCujType);
         }
 
         /** Describes whether the measurement from this session should be written to statsd. */
         public boolean logToStatsd() {
-            return getStatsdInteractionType() != NO_STATSD_LOGGING;
+            return Cuj.logToStatsd(mCujType);
         }
 
         public String getPerfettoTrigger() {
-            return String.format(Locale.US, "com.android.telemetry.interaction-jank-monitor-%d",
-                    mCujType);
+            return TextUtils.formatSimple(
+                    "com.android.telemetry.interaction-jank-monitor-%d", mCujType);
         }
 
-        public String getName() {
-            return mName;
-        }
-
-        public long getTimeStamp() {
-            return mTimeStamp;
-        }
-
-        public void setReason(@Reasons int reason) {
-            mReason = reason;
-        }
-
-        @Reasons
-        public int getReason() {
-            return mReason;
+        public @Cuj.CujType int getCujType() {
+            return mCujType;
         }
     }
 
@@ -1468,15 +902,15 @@
         void invoke(long unixNanos, long elapsedNanos, long realtimeNanos);
     }
 
-    private void postEventLogToWorkerThread(TimeFunction logFunction) {
-        final Instant now = Instant.now();
-        final long unixNanos = TimeUnit.NANOSECONDS.convert(now.getEpochSecond(), TimeUnit.SECONDS)
-                + now.getNano();
-        final long elapsedNanos = SystemClock.elapsedRealtimeNanos();
-        final long realtimeNanos = SystemClock.uptimeNanos();
+    static class RunningTracker {
+        public final Configuration mConfig;
+        public final FrameTracker mTracker;
+        public final Runnable mTimeoutAction;
 
-        mWorker.getThreadHandler().post(() -> {
-            logFunction.invoke(unixNanos, elapsedNanos, realtimeNanos);
-        });
+        RunningTracker(Configuration config, FrameTracker tracker, Runnable timeoutAction) {
+            this.mConfig = config;
+            this.mTracker = tracker;
+            this.mTimeoutAction = timeoutAction;
+        }
     }
 }
diff --git a/core/java/com/android/internal/jank/InteractionMonitorDebugOverlay.java b/core/java/com/android/internal/jank/InteractionMonitorDebugOverlay.java
index ef7944c..f3f16a0 100644
--- a/core/java/com/android/internal/jank/InteractionMonitorDebugOverlay.java
+++ b/core/java/com/android/internal/jank/InteractionMonitorDebugOverlay.java
@@ -34,7 +34,6 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.jank.FrameTracker.Reasons;
-import com.android.internal.jank.InteractionJankMonitor.CujType;
 
 /**
  * An overlay that uses WindowCallbacks to draw the names of all running CUJs to the window
@@ -94,14 +93,14 @@
     }
 
     @UiThread
-    private boolean attachViewRootIfNeeded(FrameTracker tracker) {
-        FrameTracker.ViewRootWrapper viewRoot = tracker.getViewRoot();
+    private boolean attachViewRootIfNeeded(InteractionJankMonitor.RunningTracker tracker) {
+        FrameTracker.ViewRootWrapper viewRoot = tracker.mTracker.getViewRoot();
         if (mViewRoot == null && viewRoot != null) {
             // Add a trace marker so we can identify traces that were captured while the debug
             // overlay was enabled. Traces that use the debug overlay should NOT be used for
             // performance analysis.
             Trace.asyncTraceForTrackBegin(Trace.TRACE_TAG_APP, TRACK_NAME, "DEBUG_OVERLAY_DRAW", 0);
-            mHandler = tracker.getHandler();
+            mHandler = tracker.mConfig.getHandler();
             mViewRoot = viewRoot;
             mHandler.runWithScissors(() -> viewRoot.addWindowCallbacks(this),
                     InteractionJankMonitor.EXECUTOR_TASK_TIMEOUT);
@@ -111,11 +110,12 @@
         return false;
     }
 
+    @GuardedBy("mLock")
     private float getWidthOfLongestCujName(int cujFontSize) {
         mDebugPaint.setTextSize(cujFontSize);
         float maxLength = 0;
         for (int i = 0; i < mRunningCujs.size(); i++) {
-            String cujName = InteractionJankMonitor.getNameOfCuj(mRunningCujs.keyAt(i));
+            String cujName = Cuj.getNameOfCuj(mRunningCujs.keyAt(i));
             float textLength = mDebugPaint.measureText(cujName);
             if (textLength > maxLength) {
                 maxLength = textLength;
@@ -149,8 +149,8 @@
     }
 
     @UiThread
-    void onTrackerRemoved(@CujType int removedCuj, @Reasons int reason,
-                          SparseArray<FrameTracker> runningTrackers) {
+    void onTrackerRemoved(@Cuj.CujType int removedCuj, @Reasons int reason,
+                          SparseArray<InteractionJankMonitor.RunningTracker> runningTrackers) {
         synchronized (mLock) {
             mRunningCujs.put(removedCuj, reason);
             // If REASON_STILL_RUNNING is not in mRunningCujs, then all CUJs have ended
@@ -164,7 +164,7 @@
                     // trackers
                     for (int i = 0; i < runningTrackers.size(); i++) {
                         if (mViewRoot.equals(
-                                runningTrackers.valueAt(i).getViewRoot())) {
+                                runningTrackers.valueAt(i).mTracker.getViewRoot())) {
                             needsNewViewRoot = false;
                             break;
                         }
@@ -185,7 +185,7 @@
     }
 
     @UiThread
-    void onTrackerAdded(@CujType int addedCuj, FrameTracker tracker) {
+    void onTrackerAdded(@Cuj.CujType int addedCuj, InteractionJankMonitor.RunningTracker tracker) {
         synchronized (mLock) {
             // Use REASON_STILL_RUNNING (not technically one of the '@Reasons') to indicate the CUJ
             // is still running
@@ -230,41 +230,44 @@
         int cujFontSize = dipToPx(18);
         final float cujNameTextHeight = getTextHeight(cujFontSize);
         final float packageNameTextHeight = getTextHeight(packageNameFontSize);
-        float maxLength = getWidthOfLongestCujName(cujFontSize);
 
-        final int dx = (int) ((w - maxLength) / 2f);
-        canvas.translate(dx, dy);
-        // Draw background rectangle for displaying the text showing the CUJ name
-        mDebugPaint.setColor(mBgColor);
-        canvas.drawRect(
-                -padding * 2, // more padding on top so we can draw the package name
-                -padding,
-                padding * 2 + maxLength,
-                padding * 2 + packageNameTextHeight + cujNameTextHeight * mRunningCujs.size(),
-                mDebugPaint);
-        mDebugPaint.setTextSize(packageNameFontSize);
-        mDebugPaint.setColor(Color.BLACK);
-        mDebugPaint.setStrikeThruText(false);
-        canvas.translate(0, packageNameTextHeight);
-        canvas.drawText("package:" + mPackageName, 0, 0, mDebugPaint);
-        mDebugPaint.setTextSize(cujFontSize);
-        // Draw text for CUJ names
-        for (int i = 0; i < mRunningCujs.size(); i++) {
-            int status = mRunningCujs.valueAt(i);
-            if (status == REASON_STILL_RUNNING) {
-                mDebugPaint.setColor(Color.BLACK);
-                mDebugPaint.setStrikeThruText(false);
-            } else if (status == REASON_END_NORMAL) {
-                mDebugPaint.setColor(Color.GRAY);
-                mDebugPaint.setStrikeThruText(false);
-            } else {
-                // Cancelled, or otherwise ended for a bad reason
-                mDebugPaint.setColor(Color.RED);
-                mDebugPaint.setStrikeThruText(true);
+        synchronized (mLock) {
+            float maxLength = getWidthOfLongestCujName(cujFontSize);
+
+            final int dx = (int) ((w - maxLength) / 2f);
+            canvas.translate(dx, dy);
+            // Draw background rectangle for displaying the text showing the CUJ name
+            mDebugPaint.setColor(mBgColor);
+            canvas.drawRect(
+                    -padding * 2, // more padding on top so we can draw the package name
+                    -padding,
+                    padding * 2 + maxLength,
+                    padding * 2 + packageNameTextHeight + cujNameTextHeight * mRunningCujs.size(),
+                    mDebugPaint);
+            mDebugPaint.setTextSize(packageNameFontSize);
+            mDebugPaint.setColor(Color.BLACK);
+            mDebugPaint.setStrikeThruText(false);
+            canvas.translate(0, packageNameTextHeight);
+            canvas.drawText("package:" + mPackageName, 0, 0, mDebugPaint);
+            mDebugPaint.setTextSize(cujFontSize);
+            // Draw text for CUJ names
+            for (int i = 0; i < mRunningCujs.size(); i++) {
+                int status = mRunningCujs.valueAt(i);
+                if (status == REASON_STILL_RUNNING) {
+                    mDebugPaint.setColor(Color.BLACK);
+                    mDebugPaint.setStrikeThruText(false);
+                } else if (status == REASON_END_NORMAL) {
+                    mDebugPaint.setColor(Color.GRAY);
+                    mDebugPaint.setStrikeThruText(false);
+                } else {
+                    // Cancelled, or otherwise ended for a bad reason
+                    mDebugPaint.setColor(Color.RED);
+                    mDebugPaint.setStrikeThruText(true);
+                }
+                String cujName = Cuj.getNameOfCuj(mRunningCujs.keyAt(i));
+                canvas.translate(0, cujNameTextHeight);
+                canvas.drawText(cujName, 0, 0, mDebugPaint);
             }
-            String cujName = InteractionJankMonitor.getNameOfCuj(mRunningCujs.keyAt(i));
-            canvas.translate(0, cujNameTextHeight);
-            canvas.drawText(cujName, 0, 0, mDebugPaint);
         }
     }
 }
diff --git a/core/java/com/android/internal/net/TEST_MAPPING b/core/java/com/android/internal/net/TEST_MAPPING
new file mode 100644
index 0000000..f935946c
--- /dev/null
+++ b/core/java/com/android/internal/net/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+  "presubmit": [
+    {
+      "name": "FrameworksNetTests",
+      "options": [
+        {
+          "exclude-annotation": "com.android.testutils.SkipPresubmit"
+        }
+      ]
+    }
+  ]
+}
diff --git a/core/java/com/android/internal/os/BatteryStatsHistory.java b/core/java/com/android/internal/os/BatteryStatsHistory.java
index 7d78f29..1330e16 100644
--- a/core/java/com/android/internal/os/BatteryStatsHistory.java
+++ b/core/java/com/android/internal/os/BatteryStatsHistory.java
@@ -72,6 +72,7 @@
  * All interfaces in BatteryStatsHistory should only be called by BatteryStatsImpl and protected by
  * locks on BatteryStatsImpl object.
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class BatteryStatsHistory {
     private static final boolean DEBUG = false;
     private static final String TAG = "BatteryStatsHistory";
@@ -259,6 +260,7 @@
      * until the first change occurs.
      */
     @VisibleForTesting
+    @android.ravenwood.annotation.RavenwoodKeepWholeClass
     public static class TraceDelegate {
         // Note: certain tests currently run as platform_app which is not allowed
         // to set debug system properties. To ensure that system properties are set
@@ -391,10 +393,18 @@
     public BatteryStatsHistory(int maxHistoryFiles, int maxHistoryBufferSize,
             HistoryStepDetailsCalculator stepDetailsCalculator, Clock clock,
             MonotonicClock monotonicClock) {
+        this(maxHistoryFiles, maxHistoryBufferSize, stepDetailsCalculator, clock, monotonicClock,
+                new TraceDelegate());
+    }
+
+    @VisibleForTesting
+    public BatteryStatsHistory(int maxHistoryFiles, int maxHistoryBufferSize,
+            HistoryStepDetailsCalculator stepDetailsCalculator, Clock clock,
+            MonotonicClock monotonicClock, TraceDelegate traceDelegate) {
         mMaxHistoryFiles = maxHistoryFiles;
         mMaxHistoryBufferSize = maxHistoryBufferSize;
         mStepDetailsCalculator = stepDetailsCalculator;
-        mTracer = new TraceDelegate();
+        mTracer = traceDelegate;
         mClock = clock;
         mMonotonicClock = monotonicClock;
 
@@ -619,7 +629,7 @@
      * @param startTimeMs monotonic time (the HistoryItem.time field) to start iterating from,
      *                    inclusive
      * @param endTimeMs monotonic time to stop iterating, exclusive.
-     *                  Pass 0 to indicate current time.
+     *                  Pass {@link MonotonicClock#UNDEFINED} to indicate current time.
      */
     @NonNull
     public BatteryStatsHistoryIterator iterate(long startTimeMs, long endTimeMs) {
@@ -2096,6 +2106,7 @@
      * fewer bytes.  It is a bit more expensive than just writing the long into the parcel,
      * but at scale saves a lot of storage and allows recording of longer battery history.
      */
+    @android.ravenwood.annotation.RavenwoodKeepWholeClass
     public static final class VarintParceler {
         /**
          * Writes an array of longs into Parcel using the varint format, see
diff --git a/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java b/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java
index 6bd5898..739ee48 100644
--- a/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java
+++ b/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java
@@ -28,6 +28,7 @@
 /**
  * An iterator for {@link BatteryStats.HistoryItem}'s.
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class BatteryStatsHistoryIterator implements Iterator<BatteryStats.HistoryItem>,
         AutoCloseable {
     private static final boolean DEBUG = false;
@@ -48,7 +49,7 @@
             long endTimeMs) {
         mBatteryStatsHistory = history;
         mStartTimeMs = startTimeMs;
-        mEndTimeMs = (endTimeMs != 0) ? endTimeMs : Long.MAX_VALUE;
+        mEndTimeMs = (endTimeMs != MonotonicClock.UNDEFINED) ? endTimeMs : Long.MAX_VALUE;
         mHistoryItem.clear();
     }
 
diff --git a/core/java/com/android/internal/os/BinderCallHeavyHitterWatcher.java b/core/java/com/android/internal/os/BinderCallHeavyHitterWatcher.java
index 7701761..00043cf 100644
--- a/core/java/com/android/internal/os/BinderCallHeavyHitterWatcher.java
+++ b/core/java/com/android/internal/os/BinderCallHeavyHitterWatcher.java
@@ -33,6 +33,7 @@
  * A watcher which makes stats on the incoming binder transaction, if the amount of some type of
  * transactions exceeds the threshold, the listener will be notified.
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public final class BinderCallHeavyHitterWatcher {
     private static final String TAG = "BinderCallHeavyHitterWatcher";
 
diff --git a/core/java/com/android/internal/os/BinderDeathDispatcher.java b/core/java/com/android/internal/os/BinderDeathDispatcher.java
index 8ca6241..e7abe2a 100644
--- a/core/java/com/android/internal/os/BinderDeathDispatcher.java
+++ b/core/java/com/android/internal/os/BinderDeathDispatcher.java
@@ -36,6 +36,7 @@
  *
  * test with: atest FrameworksCoreTests:BinderDeathDispatcherTest
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class BinderDeathDispatcher<T extends IInterface> {
     private static final String TAG = "BinderDeathDispatcher";
 
diff --git a/core/java/com/android/internal/os/BinderLatencyBuckets.java b/core/java/com/android/internal/os/BinderLatencyBuckets.java
index d7d2d6a..5679bc7 100644
--- a/core/java/com/android/internal/os/BinderLatencyBuckets.java
+++ b/core/java/com/android/internal/os/BinderLatencyBuckets.java
@@ -26,6 +26,7 @@
  * Generates the bucket thresholds (with a custom logarithmic scale) for a histogram to store
  * latency samples in.
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class BinderLatencyBuckets {
     private static final String TAG = "BinderLatencyBuckets";
     private final int[] mBuckets;
diff --git a/core/java/com/android/internal/os/BinderfsStatsReader.java b/core/java/com/android/internal/os/BinderfsStatsReader.java
index 9cc4a35..66f91e1 100644
--- a/core/java/com/android/internal/os/BinderfsStatsReader.java
+++ b/core/java/com/android/internal/os/BinderfsStatsReader.java
@@ -43,6 +43,7 @@
  * free async space 520192
  * ...
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class BinderfsStatsReader {
     private final String mPath;
 
diff --git a/core/java/com/android/internal/os/CachedDeviceState.java b/core/java/com/android/internal/os/CachedDeviceState.java
index 334cca3..ac92f86 100644
--- a/core/java/com/android/internal/os/CachedDeviceState.java
+++ b/core/java/com/android/internal/os/CachedDeviceState.java
@@ -30,6 +30,7 @@
  *
  * @hide
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class CachedDeviceState {
     private volatile boolean mScreenInteractive;
     private volatile boolean mCharging;
diff --git a/core/java/com/android/internal/os/Clock.java b/core/java/com/android/internal/os/Clock.java
index 45007c4..c2403d1 100644
--- a/core/java/com/android/internal/os/Clock.java
+++ b/core/java/com/android/internal/os/Clock.java
@@ -21,6 +21,7 @@
 /**
  * A wrapper for SystemClock, intended for mocking in unit tests.
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public abstract class Clock {
     /** Elapsed Realtime, see SystemClock.elapsedRealtime() */
     public long elapsedRealtime() {
diff --git a/core/java/com/android/internal/os/CpuScalingPolicies.java b/core/java/com/android/internal/os/CpuScalingPolicies.java
index 6dbe8ab..f61cf97 100644
--- a/core/java/com/android/internal/os/CpuScalingPolicies.java
+++ b/core/java/com/android/internal/os/CpuScalingPolicies.java
@@ -27,6 +27,7 @@
  * CPU scaling policies: the policy IDs and corresponding supported scaling for those
  * policies.
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class CpuScalingPolicies {
     private final SparseArray<int[]> mCpusByPolicy;
     private final SparseArray<int[]> mFreqsByPolicy;
diff --git a/core/java/com/android/internal/os/CpuScalingPolicyReader.java b/core/java/com/android/internal/os/CpuScalingPolicyReader.java
index c96089a..0d272fd 100644
--- a/core/java/com/android/internal/os/CpuScalingPolicyReader.java
+++ b/core/java/com/android/internal/os/CpuScalingPolicyReader.java
@@ -40,6 +40,7 @@
  * href="https://www.kernel.org/doc/html/latest/admin-guide/pm/cpufreq.html
  * #policy-interface-in-sysfs">Policy Interface in sysfs</a>
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class CpuScalingPolicyReader {
     private static final String TAG = "CpuScalingPolicyReader";
     private static final String CPUFREQ_DIR = "/sys/devices/system/cpu/cpufreq";
diff --git a/core/java/com/android/internal/os/KernelCpuThreadReader.java b/core/java/com/android/internal/os/KernelCpuThreadReader.java
index 0843741..5b6d1b6 100644
--- a/core/java/com/android/internal/os/KernelCpuThreadReader.java
+++ b/core/java/com/android/internal/os/KernelCpuThreadReader.java
@@ -244,7 +244,8 @@
     }
 
     /** Set the UID predicate for {@link #getProcessCpuUsage} */
-    void setUidPredicate(Predicate<Integer> uidPredicate) {
+    @VisibleForTesting
+    public void setUidPredicate(Predicate<Integer> uidPredicate) {
         mUidPredicate = uidPredicate;
     }
 
diff --git a/core/java/com/android/internal/os/LoggingPrintStream.java b/core/java/com/android/internal/os/LoggingPrintStream.java
index d27874c..4bf92bb 100644
--- a/core/java/com/android/internal/os/LoggingPrintStream.java
+++ b/core/java/com/android/internal/os/LoggingPrintStream.java
@@ -36,6 +36,7 @@
  * {@hide}
  */
 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public abstract class LoggingPrintStream extends PrintStream {
 
     private final StringBuilder builder = new StringBuilder();
diff --git a/core/java/com/android/internal/os/LongArrayMultiStateCounter.java b/core/java/com/android/internal/os/LongArrayMultiStateCounter.java
index 1f44b33..ed943cb 100644
--- a/core/java/com/android/internal/os/LongArrayMultiStateCounter.java
+++ b/core/java/com/android/internal/os/LongArrayMultiStateCounter.java
@@ -55,15 +55,20 @@
  *
  * @hide
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
+@android.ravenwood.annotation.RavenwoodNativeSubstitutionClass(
+        "com.android.hoststubgen.nativesubstitution.LongArrayMultiStateCounter_host")
 public final class LongArrayMultiStateCounter implements Parcelable {
 
     /**
      * Container for a native equivalent of a long[].
      */
+    @android.ravenwood.annotation.RavenwoodKeepWholeClass
+    @android.ravenwood.annotation.RavenwoodNativeSubstitutionClass(
+            "com.android.hoststubgen.nativesubstitution"
+            + ".LongArrayMultiStateCounter_host$LongArrayContainer_host")
     public static class LongArrayContainer {
-        private static final NativeAllocationRegistry sRegistry =
-                NativeAllocationRegistry.createMalloced(
-                        LongArrayContainer.class.getClassLoader(), native_getReleaseFunc());
+        private static NativeAllocationRegistry sRegistry;
 
         // Visible to other objects in this package so that it can be passed to @CriticalNative
         // methods.
@@ -73,9 +78,26 @@
         public LongArrayContainer(int length) {
             mLength = length;
             mNativeObject = native_init(length);
+            registerNativeAllocation();
+        }
+
+        @android.ravenwood.annotation.RavenwoodReplace
+        private void registerNativeAllocation() {
+            if (sRegistry == null) {
+                synchronized (LongArrayMultiStateCounter.class) {
+                    if (sRegistry == null) {
+                        sRegistry = NativeAllocationRegistry.createMalloced(
+                                LongArrayContainer.class.getClassLoader(), native_getReleaseFunc());
+                    }
+                }
+            }
             sRegistry.registerNativeAllocation(this, mNativeObject);
         }
 
+        private void registerNativeAllocation$ravenwood() {
+            // No-op under ravenwood
+        }
+
         /**
          * Copies the supplied values into the underlying native array.
          */
@@ -124,19 +146,17 @@
         private static native long native_getReleaseFunc();
 
         @FastNative
-        private native void native_setValues(long nativeObject, long[] array);
+        private static native void native_setValues(long nativeObject, long[] array);
 
         @FastNative
-        private native void native_getValues(long nativeObject, long[] array);
+        private static native void native_getValues(long nativeObject, long[] array);
 
         @FastNative
-        private native boolean native_combineValues(long nativeObject, long[] array,
+        private static native boolean native_combineValues(long nativeObject, long[] array,
                 int[] indexMap);
     }
 
-    private static final NativeAllocationRegistry sRegistry =
-            NativeAllocationRegistry.createMalloced(
-                    LongArrayMultiStateCounter.class.getClassLoader(), native_getReleaseFunc());
+    private static volatile NativeAllocationRegistry sRegistry;
     private static final AtomicReference<LongArrayContainer> sTmpArrayContainer =
             new AtomicReference<>();
 
@@ -152,12 +172,30 @@
         mStateCount = stateCount;
         mLength = arrayLength;
         mNativeObject = native_init(stateCount, arrayLength);
+        registerNativeAllocation();
+    }
+
+    @android.ravenwood.annotation.RavenwoodReplace
+    private void registerNativeAllocation() {
+        if (sRegistry == null) {
+            synchronized (LongArrayMultiStateCounter.class) {
+                if (sRegistry == null) {
+                    sRegistry = NativeAllocationRegistry.createMalloced(
+                            LongArrayMultiStateCounter.class.getClassLoader(),
+                            native_getReleaseFunc());
+                }
+            }
+        }
         sRegistry.registerNativeAllocation(this, mNativeObject);
     }
 
+    private void registerNativeAllocation$ravenwood() {
+        // No-op under ravenwood
+    }
+
     private LongArrayMultiStateCounter(Parcel in) {
         mNativeObject = native_initFromParcel(in);
-        sRegistry.registerNativeAllocation(this, mNativeObject);
+        registerNativeAllocation();
 
         mStateCount = native_getStateCount(mNativeObject);
         mLength = native_getArrayLength(mNativeObject);
@@ -361,10 +399,10 @@
             long longArrayContainerNativeObject, int state);
 
     @FastNative
-    private native String native_toString(long nativeObject);
+    private static native String native_toString(long nativeObject);
 
     @FastNative
-    private native void native_writeToParcel(long nativeObject, Parcel dest, int flags);
+    private static native void native_writeToParcel(long nativeObject, Parcel dest, int flags);
 
     @FastNative
     private static native long native_initFromParcel(Parcel parcel);
diff --git a/core/java/com/android/internal/os/LooperStats.java b/core/java/com/android/internal/os/LooperStats.java
index 0645eb7..bbcea8a 100644
--- a/core/java/com/android/internal/os/LooperStats.java
+++ b/core/java/com/android/internal/os/LooperStats.java
@@ -36,6 +36,7 @@
  *
  * @hide Only for use within the system server.
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class LooperStats implements Looper.Observer {
     public static final String DEBUG_ENTRY_PREFIX = "__DEBUG_";
     private static final int SESSION_POOL_SIZE = 50;
diff --git a/core/java/com/android/internal/os/MonotonicClock.java b/core/java/com/android/internal/os/MonotonicClock.java
index 661628a..c3bcfa6 100644
--- a/core/java/com/android/internal/os/MonotonicClock.java
+++ b/core/java/com/android/internal/os/MonotonicClock.java
@@ -40,6 +40,7 @@
  * A clock that is similar to SystemClock#elapsedRealtime(), except that it is not reset
  * on reboot, but keeps going.
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class MonotonicClock {
     private static final String TAG = "MonotonicClock";
 
diff --git a/core/java/com/android/internal/os/PowerStats.java b/core/java/com/android/internal/os/PowerStats.java
index 1a7efac..56263fb 100644
--- a/core/java/com/android/internal/os/PowerStats.java
+++ b/core/java/com/android/internal/os/PowerStats.java
@@ -41,6 +41,7 @@
  * Container for power stats, acquired by various PowerStatsCollector classes. See subclasses for
  * details.
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public final class PowerStats {
     private static final String TAG = "PowerStats";
 
@@ -67,6 +68,7 @@
      * This descriptor is used for storing PowerStats and can also be used by power models
      * to adjust the algorithm in accordance with the stats available on the device.
      */
+    @android.ravenwood.annotation.RavenwoodKeepWholeClass
     public static class Descriptor {
         public static final String XML_TAG_DESCRIPTOR = "descriptor";
         private static final String XML_ATTR_ID = "id";
diff --git a/core/java/com/android/internal/os/ProcLocksReader.java b/core/java/com/android/internal/os/ProcLocksReader.java
index 9ddb8c7..6b85e08 100644
--- a/core/java/com/android/internal/os/ProcLocksReader.java
+++ b/core/java/com/android/internal/os/ProcLocksReader.java
@@ -34,6 +34,7 @@
  * 3: POSIX  ADVISORY  READ  3888 fd:09:13992 128 128
  * 4: POSIX  ADVISORY  READ  3888 fd:09:14230 1073741826 1073742335
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class ProcLocksReader {
     private final String mPath;
     private ProcFileReader mReader = null;
diff --git a/core/java/com/android/internal/os/ProcStatsUtil.java b/core/java/com/android/internal/os/ProcStatsUtil.java
index 0002447f..b67190b 100644
--- a/core/java/com/android/internal/os/ProcStatsUtil.java
+++ b/core/java/com/android/internal/os/ProcStatsUtil.java
@@ -30,6 +30,7 @@
  * Utility functions for reading {@code proc} files
  */
 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED)
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public final class ProcStatsUtil {
 
     private static final boolean DEBUG = false;
@@ -92,10 +93,24 @@
      * seen, or at the end of the file
      */
     @Nullable
+    @android.ravenwood.annotation.RavenwoodReplace
     public static String readTerminatedProcFile(String path, byte terminator) {
         // Permit disk reads here, as /proc isn't really "on disk" and should be fast.
         // TODO: make BlockGuard ignore /proc/ and /sys/ files perhaps?
         final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
+        try {
+            return readTerminatedProcFileInternal(path, terminator);
+        } finally {
+            StrictMode.setThreadPolicy(savedPolicy);
+        }
+    }
+
+    public static String readTerminatedProcFile$ravenwood(String path, byte terminator) {
+        // No StrictMode under Ravenwood
+        return readTerminatedProcFileInternal(path, terminator);
+    }
+
+    private static String readTerminatedProcFileInternal(String path, byte terminator) {
         try (FileInputStream is = new FileInputStream(path)) {
             ByteArrayOutputStream byteStream = null;
             final byte[] buffer = new byte[READ_SIZE];
@@ -147,8 +162,6 @@
                 Slog.d(TAG, "Failed to open proc file", e);
             }
             return null;
-        } finally {
-            StrictMode.setThreadPolicy(savedPolicy);
         }
     }
 }
diff --git a/core/java/com/android/internal/os/SomeArgs.java b/core/java/com/android/internal/os/SomeArgs.java
index b12df6e..4701af3 100644
--- a/core/java/com/android/internal/os/SomeArgs.java
+++ b/core/java/com/android/internal/os/SomeArgs.java
@@ -26,6 +26,7 @@
  * it is responsibility of the client to recycle and instance
  * once it is no longer used.
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public final class SomeArgs {
 
     private static final int MAX_POOL_SIZE = 10;
diff --git a/core/java/com/android/internal/os/StoragedUidIoStatsReader.java b/core/java/com/android/internal/os/StoragedUidIoStatsReader.java
index 9b03469..2d485da 100644
--- a/core/java/com/android/internal/os/StoragedUidIoStatsReader.java
+++ b/core/java/com/android/internal/os/StoragedUidIoStatsReader.java
@@ -38,6 +38,7 @@
  * This provides the number of bytes/chars read/written in foreground/background for each uid.
  * The file contains a monotonically increasing count of bytes/chars for a single boot.
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class StoragedUidIoStatsReader {
 
     private static final String TAG = StoragedUidIoStatsReader.class.getSimpleName();
@@ -73,8 +74,21 @@
      *
      * @param callback The callback to invoke for each line of the proc file.
      */
+    @android.ravenwood.annotation.RavenwoodReplace
     public void readAbsolute(Callback callback) {
         final int oldMask = StrictMode.allowThreadDiskReadsMask();
+        try {
+            readAbsoluteInternal(callback);
+        } finally {
+            StrictMode.setThreadPolicyMask(oldMask);
+        }
+    }
+
+    public void readAbsolute$ravenwood(Callback callback) {
+        readAbsoluteInternal(callback);
+    }
+
+    private void readAbsoluteInternal(Callback callback) {
         File file = new File(sUidIoFile);
         try (BufferedReader reader = Files.newBufferedReader(file.toPath())) {
             String line;
@@ -106,8 +120,6 @@
             }
         } catch (IOException e) {
             Slog.e(TAG, "Failed to read " + sUidIoFile + ": " + e.getMessage());
-        } finally {
-            StrictMode.setThreadPolicyMask(oldMask);
         }
     }
 }
diff --git a/core/java/com/android/internal/pm/parsing/AppInfoUtils.java b/core/java/com/android/internal/pm/parsing/AppInfoUtils.java
new file mode 100644
index 0000000..38a2fe2
--- /dev/null
+++ b/core/java/com/android/internal/pm/parsing/AppInfoUtils.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.pm.parsing;
+
+import android.annotation.CheckResult;
+import android.content.pm.ApplicationInfo;
+
+import com.android.internal.pm.parsing.pkg.AndroidPackageLegacyUtils;
+import com.android.internal.pm.pkg.parsing.ParsingPackageUtils;
+import com.android.server.pm.pkg.AndroidPackage;
+
+public class AppInfoUtils {
+
+    /**
+     * @see ApplicationInfo#flags
+     */
+    public static int appInfoFlags(AndroidPackage pkg) {
+        // @formatter:off
+        int pkgWithoutStateFlags = flag(pkg.isExternalStorage(), ApplicationInfo.FLAG_EXTERNAL_STORAGE)
+                | flag(pkg.isHardwareAccelerated(), ApplicationInfo.FLAG_HARDWARE_ACCELERATED)
+                | flag(pkg.isBackupAllowed(), ApplicationInfo.FLAG_ALLOW_BACKUP)
+                | flag(pkg.isKillAfterRestoreAllowed(), ApplicationInfo.FLAG_KILL_AFTER_RESTORE)
+                | flag(pkg.isRestoreAnyVersion(), ApplicationInfo.FLAG_RESTORE_ANY_VERSION)
+                | flag(pkg.isFullBackupOnly(), ApplicationInfo.FLAG_FULL_BACKUP_ONLY)
+                | flag(pkg.isPersistent(), ApplicationInfo.FLAG_PERSISTENT)
+                | flag(pkg.isDebuggable(), ApplicationInfo.FLAG_DEBUGGABLE)
+                | flag(pkg.isVmSafeMode(), ApplicationInfo.FLAG_VM_SAFE_MODE)
+                | flag(pkg.isDeclaredHavingCode(), ApplicationInfo.FLAG_HAS_CODE)
+                | flag(pkg.isTaskReparentingAllowed(), ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING)
+                | flag(pkg.isClearUserDataAllowed(), ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA)
+                | flag(pkg.isLargeHeap(), ApplicationInfo.FLAG_LARGE_HEAP)
+                | flag(pkg.isCleartextTrafficAllowed(), ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC)
+                | flag(pkg.isRtlSupported(), ApplicationInfo.FLAG_SUPPORTS_RTL)
+                | flag(pkg.isTestOnly(), ApplicationInfo.FLAG_TEST_ONLY)
+                | flag(pkg.isMultiArch(), ApplicationInfo.FLAG_MULTIARCH)
+                | flag(pkg.isExtractNativeLibrariesRequested(), ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS)
+                | flag(pkg.isGame(), ApplicationInfo.FLAG_IS_GAME)
+                | flag(pkg.isSmallScreensSupported(), ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS)
+                | flag(pkg.isNormalScreensSupported(), ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS)
+                | flag(pkg.isLargeScreensSupported(), ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS)
+                | flag(pkg.isExtraLargeScreensSupported(), ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS)
+                | flag(pkg.isResizeable(), ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS)
+                | flag(pkg.isAnyDensity(), ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
+                | flag(AndroidPackageLegacyUtils.isSystem(pkg), ApplicationInfo.FLAG_SYSTEM)
+                | flag(pkg.isFactoryTest(), ApplicationInfo.FLAG_FACTORY_TEST);
+
+        return pkgWithoutStateFlags;
+        // @formatter:on
+    }
+
+    /** @see ApplicationInfo#privateFlags */
+    public static int appInfoPrivateFlags(AndroidPackage pkg) {
+        // @formatter:off
+        int pkgWithoutStateFlags = flag(pkg.isStaticSharedLibrary(), ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY)
+                | flag(pkg.isResourceOverlay(), ApplicationInfo.PRIVATE_FLAG_IS_RESOURCE_OVERLAY)
+                | flag(pkg.isIsolatedSplitLoading(), ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING)
+                | flag(pkg.isHasDomainUrls(), ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS)
+                | flag(pkg.isProfileableByShell(), ApplicationInfo.PRIVATE_FLAG_PROFILEABLE_BY_SHELL)
+                | flag(pkg.isBackupInForeground(), ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND)
+                | flag(pkg.isUseEmbeddedDex(), ApplicationInfo.PRIVATE_FLAG_USE_EMBEDDED_DEX)
+                | flag(pkg.isDefaultToDeviceProtectedStorage(), ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE)
+                | flag(pkg.isDirectBootAware(), ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE)
+                | flag(pkg.isPartiallyDirectBootAware(), ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE)
+                | flag(pkg.isClearUserDataOnFailedRestoreAllowed(), ApplicationInfo.PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE)
+                | flag(pkg.isAllowAudioPlaybackCapture(), ApplicationInfo.PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE)
+                | flag(pkg.isRequestLegacyExternalStorage(), ApplicationInfo.PRIVATE_FLAG_REQUEST_LEGACY_EXTERNAL_STORAGE)
+                | flag(pkg.isNonSdkApiRequested(), ApplicationInfo.PRIVATE_FLAG_USES_NON_SDK_API)
+                | flag(pkg.isUserDataFragile(), ApplicationInfo.PRIVATE_FLAG_HAS_FRAGILE_USER_DATA)
+                | flag(pkg.isSaveStateDisallowed(), ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
+                | flag(pkg.isResizeableActivityViaSdkVersion(), ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION)
+                | flag(pkg.isAllowNativeHeapPointerTagging(), ApplicationInfo.PRIVATE_FLAG_ALLOW_NATIVE_HEAP_POINTER_TAGGING)
+                | flag(AndroidPackageLegacyUtils.isSystemExt(pkg), ApplicationInfo.PRIVATE_FLAG_SYSTEM_EXT)
+                | flag(AndroidPackageLegacyUtils.isPrivileged(pkg), ApplicationInfo.PRIVATE_FLAG_PRIVILEGED)
+                | flag(AndroidPackageLegacyUtils.isOem(pkg), ApplicationInfo.PRIVATE_FLAG_OEM)
+                | flag(AndroidPackageLegacyUtils.isVendor(pkg), ApplicationInfo.PRIVATE_FLAG_VENDOR)
+                | flag(AndroidPackageLegacyUtils.isProduct(pkg), ApplicationInfo.PRIVATE_FLAG_PRODUCT)
+                | flag(AndroidPackageLegacyUtils.isOdm(pkg), ApplicationInfo.PRIVATE_FLAG_ODM)
+                | flag(pkg.isSignedWithPlatformKey(), ApplicationInfo.PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY);
+
+        Boolean resizeableActivity = pkg.getResizeableActivity();
+        if (resizeableActivity != null) {
+            if (resizeableActivity) {
+                pkgWithoutStateFlags |= ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE;
+            } else {
+                pkgWithoutStateFlags |= ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE;
+            }
+        }
+
+        return pkgWithoutStateFlags;
+        // @formatter:on
+    }
+
+
+    /** @see ApplicationInfo#privateFlagsExt */
+    public static int appInfoPrivateFlagsExt(AndroidPackage pkg,
+            boolean isAllowlistedForHiddenApis) {
+        // @formatter:off
+        int pkgWithoutStateFlags = flag(pkg.isProfileable(), ApplicationInfo.PRIVATE_FLAG_EXT_PROFILEABLE)
+                | flag(pkg.hasRequestForegroundServiceExemption(), ApplicationInfo.PRIVATE_FLAG_EXT_REQUEST_FOREGROUND_SERVICE_EXEMPTION)
+                | flag(pkg.isAttributionsUserVisible(), ApplicationInfo.PRIVATE_FLAG_EXT_ATTRIBUTIONS_ARE_USER_VISIBLE)
+                | flag(pkg.isOnBackInvokedCallbackEnabled(), ApplicationInfo.PRIVATE_FLAG_EXT_ENABLE_ON_BACK_INVOKED_CALLBACK)
+                | flag(isAllowlistedForHiddenApis, ApplicationInfo.PRIVATE_FLAG_EXT_ALLOWLISTED_FOR_HIDDEN_APIS);
+        return pkgWithoutStateFlags;
+        // @formatter:on
+    }
+
+    @CheckResult
+    private static int flag(boolean hasFlag, int flag) {
+        return hasFlag ? flag : 0;
+    }
+}
diff --git a/core/java/com/android/internal/pm/parsing/PackageParserException.java b/core/java/com/android/internal/pm/parsing/PackageParserException.java
new file mode 100644
index 0000000..4250bbd
--- /dev/null
+++ b/core/java/com/android/internal/pm/parsing/PackageParserException.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.pm.parsing;
+
+public class PackageParserException extends Exception {
+    public final int error;
+
+    public PackageParserException(int error, String detailMessage) {
+        super(detailMessage);
+        this.error = error;
+    }
+
+    public PackageParserException(int error, String detailMessage, Throwable throwable) {
+        super(detailMessage, throwable);
+        this.error = error;
+    }
+}
\ No newline at end of file
diff --git a/core/java/com/android/internal/pm/parsing/pkg/AndroidPackageLegacyUtils.java b/core/java/com/android/internal/pm/parsing/pkg/AndroidPackageLegacyUtils.java
new file mode 100644
index 0000000..e65f1c9
--- /dev/null
+++ b/core/java/com/android/internal/pm/parsing/pkg/AndroidPackageLegacyUtils.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.pm.parsing.pkg;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+
+import com.android.internal.pm.pkg.parsing.ParsingPackageHidden;
+import com.android.server.pm.pkg.AndroidPackage;
+
+/** @hide */
+public class AndroidPackageLegacyUtils {
+
+    private AndroidPackageLegacyUtils() {
+    }
+
+    /**
+     * Returns the primary ABI as parsed from the package. Used only during parsing and derivation.
+     * Otherwise prefer {@link PackageState#getPrimaryCpuAbi()}.
+     */
+    public static String getRawPrimaryCpuAbi(AndroidPackage pkg) {
+        return ((AndroidPackageHidden) pkg).getPrimaryCpuAbi();
+    }
+
+    /**
+     * Returns the secondary ABI as parsed from the package. Used only during parsing and
+     * derivation. Otherwise prefer {@link PackageState#getSecondaryCpuAbi()}.
+     */
+    public static String getRawSecondaryCpuAbi(@NonNull AndroidPackage pkg) {
+        return ((AndroidPackageHidden) pkg).getSecondaryCpuAbi();
+    }
+
+    @Deprecated
+    @NonNull
+    public static ApplicationInfo generateAppInfoWithoutState(AndroidPackage pkg) {
+        return ((AndroidPackageHidden) pkg).toAppInfoWithoutState();
+    }
+
+    /**
+     * Replacement of unnecessary legacy getRealPackage. Only returns a value if the package was
+     * actually renamed.
+     */
+    @Nullable
+    public static String getRealPackageOrNull(@NonNull AndroidPackage pkg, boolean isSystem) {
+        if (pkg.getOriginalPackages().isEmpty() || !isSystem) {
+            return null;
+        }
+
+        return pkg.getManifestPackageName();
+    }
+
+    public static void fillVersionCodes(@NonNull AndroidPackage pkg, @NonNull PackageInfo info) {
+        info.versionCode = ((ParsingPackageHidden) pkg).getVersionCode();
+        info.versionCodeMajor = ((ParsingPackageHidden) pkg).getVersionCodeMajor();
+    }
+
+    /**
+     * @deprecated Use {@link PackageState#isSystem}
+     */
+    @Deprecated
+    public static boolean isSystem(@NonNull AndroidPackage pkg) {
+        return ((AndroidPackageHidden) pkg).isSystem();
+    }
+
+    /**
+     * @deprecated Use {@link PackageState#isSystemExt}
+     */
+    @Deprecated
+    public static boolean isSystemExt(@NonNull AndroidPackage pkg) {
+        return ((AndroidPackageHidden) pkg).isSystemExt();
+    }
+
+    /**
+     * @deprecated Use {@link PackageState#isPrivileged}
+     */
+    @Deprecated
+    public static boolean isPrivileged(@NonNull AndroidPackage pkg) {
+        return ((AndroidPackageHidden) pkg).isPrivileged();
+    }
+
+    /**
+     * @deprecated Use {@link PackageState#isOem}
+     */
+    @Deprecated
+    public static boolean isOem(@NonNull AndroidPackage pkg) {
+        return ((AndroidPackageHidden) pkg).isOem();
+    }
+
+    /**
+     * @deprecated Use {@link PackageState#isVendor}
+     */
+    @Deprecated
+    public static boolean isVendor(@NonNull AndroidPackage pkg) {
+        return ((AndroidPackageHidden) pkg).isVendor();
+    }
+
+    /**
+     * @deprecated Use {@link PackageState#isProduct}
+     */
+    @Deprecated
+    public static boolean isProduct(@NonNull AndroidPackage pkg) {
+        return ((AndroidPackageHidden) pkg).isProduct();
+    }
+
+    /**
+     * @deprecated Use {@link PackageState#isOdm}
+     */
+    @Deprecated
+    public static boolean isOdm(@NonNull AndroidPackage pkg) {
+        return ((AndroidPackageHidden) pkg).isOdm();
+    }
+}
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java b/core/java/com/android/internal/pm/parsing/pkg/PackageImpl.java
similarity index 97%
rename from services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
rename to core/java/com/android/internal/pm/parsing/pkg/PackageImpl.java
index 85d95ea..83acc47 100644
--- a/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
+++ b/core/java/com/android/internal/pm/parsing/pkg/PackageImpl.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.pm.parsing.pkg;
+package com.android.internal.pm.parsing.pkg;
 
 import static java.util.Collections.emptyList;
 import static java.util.Collections.emptyMap;
@@ -50,47 +50,44 @@
 
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.pm.parsing.pkg.AndroidPackageHidden;
-import com.android.internal.pm.parsing.pkg.AndroidPackageInternal;
-import com.android.internal.pm.parsing.pkg.ParsedPackage;
+import com.android.internal.pm.parsing.AppInfoUtils;
 import com.android.internal.pm.pkg.AndroidPackageSplitImpl;
+import com.android.internal.pm.pkg.SEInfoUtil;
+import com.android.internal.pm.pkg.component.ComponentMutateUtils;
 import com.android.internal.pm.pkg.component.ParsedActivity;
+import com.android.internal.pm.pkg.component.ParsedActivityImpl;
 import com.android.internal.pm.pkg.component.ParsedApexSystemService;
+import com.android.internal.pm.pkg.component.ParsedApexSystemServiceImpl;
 import com.android.internal.pm.pkg.component.ParsedAttribution;
+import com.android.internal.pm.pkg.component.ParsedAttributionImpl;
 import com.android.internal.pm.pkg.component.ParsedComponent;
 import com.android.internal.pm.pkg.component.ParsedInstrumentation;
+import com.android.internal.pm.pkg.component.ParsedInstrumentationImpl;
 import com.android.internal.pm.pkg.component.ParsedIntentInfo;
 import com.android.internal.pm.pkg.component.ParsedMainComponent;
 import com.android.internal.pm.pkg.component.ParsedPermission;
 import com.android.internal.pm.pkg.component.ParsedPermissionGroup;
+import com.android.internal.pm.pkg.component.ParsedPermissionGroupImpl;
+import com.android.internal.pm.pkg.component.ParsedPermissionImpl;
 import com.android.internal.pm.pkg.component.ParsedProcess;
+import com.android.internal.pm.pkg.component.ParsedProcessImpl;
 import com.android.internal.pm.pkg.component.ParsedProvider;
+import com.android.internal.pm.pkg.component.ParsedProviderImpl;
 import com.android.internal.pm.pkg.component.ParsedService;
+import com.android.internal.pm.pkg.component.ParsedServiceImpl;
 import com.android.internal.pm.pkg.component.ParsedUsesPermission;
+import com.android.internal.pm.pkg.component.ParsedUsesPermissionImpl;
 import com.android.internal.pm.pkg.parsing.ParsingPackage;
 import com.android.internal.pm.pkg.parsing.ParsingPackageHidden;
+import com.android.internal.pm.pkg.parsing.ParsingPackageUtils;
+import com.android.internal.pm.pkg.parsing.ParsingUtils;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.CollectionUtils;
 import com.android.internal.util.DataClass;
 import com.android.internal.util.Parcelling;
 import com.android.internal.util.Parcelling.BuiltIn.ForInternedString;
-import com.android.server.pm.parsing.PackageInfoUtils;
 import com.android.server.pm.pkg.AndroidPackage;
 import com.android.server.pm.pkg.AndroidPackageSplit;
-import com.android.server.pm.pkg.SELinuxUtil;
-import com.android.server.pm.pkg.component.ComponentMutateUtils;
-import com.android.server.pm.pkg.component.ParsedActivityImpl;
-import com.android.server.pm.pkg.component.ParsedApexSystemServiceImpl;
-import com.android.server.pm.pkg.component.ParsedAttributionImpl;
-import com.android.server.pm.pkg.component.ParsedInstrumentationImpl;
-import com.android.server.pm.pkg.component.ParsedPermissionGroupImpl;
-import com.android.server.pm.pkg.component.ParsedPermissionImpl;
-import com.android.server.pm.pkg.component.ParsedProcessImpl;
-import com.android.server.pm.pkg.component.ParsedProviderImpl;
-import com.android.server.pm.pkg.component.ParsedServiceImpl;
-import com.android.server.pm.pkg.component.ParsedUsesPermissionImpl;
-import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
-import com.android.server.pm.pkg.parsing.ParsingUtils;
 
 import libcore.util.EmptyArray;
 
@@ -267,6 +264,8 @@
     @Nullable
     private String[][] usesSdkLibrariesCertDigests;
     @Nullable
+    private boolean[] usesSdkLibrariesOptional;
+    @Nullable
     @DataClass.ParcelWith(ForInternedString.class)
     private String sharedUserId;
     private int sharedUserLabel;
@@ -420,8 +419,10 @@
 
     @NonNull
     public static PackageImpl forParsing(@NonNull String packageName, @NonNull String baseCodePath,
-            @NonNull String codePath, @NonNull TypedArray manifestArray, boolean isCoreApp) {
-        return new PackageImpl(packageName, baseCodePath, codePath, manifestArray, isCoreApp);
+            @NonNull String codePath, @NonNull TypedArray manifestArray, boolean isCoreApp,
+            @Nullable ParsingPackageUtils.Callback callback) {
+        return new PackageImpl(
+                packageName, baseCodePath, codePath, manifestArray, isCoreApp, callback);
     }
 
     /**
@@ -451,7 +452,7 @@
     @NonNull
     @VisibleForTesting
     public static ParsingPackage forTesting(String packageName, String baseCodePath) {
-        return new PackageImpl(packageName, baseCodePath, baseCodePath, null, false);
+        return new PackageImpl(packageName, baseCodePath, baseCodePath, null, false, null);
     }
 
     @NonNull
@@ -718,13 +719,15 @@
 
     @Override
     public PackageImpl addUsesSdkLibrary(String libraryName, long versionMajor,
-            String[] certSha256Digests) {
+            String[] certSha256Digests, boolean usesSdkLibrariesOptional) {
         this.usesSdkLibraries = CollectionUtils.add(this.usesSdkLibraries,
                 TextUtils.safeIntern(libraryName));
         this.usesSdkLibrariesVersionsMajor = ArrayUtils.appendLong(
                 this.usesSdkLibrariesVersionsMajor, versionMajor, true);
         this.usesSdkLibrariesCertDigests = ArrayUtils.appendElement(String[].class,
                 this.usesSdkLibrariesCertDigests, certSha256Digests, true);
+        this.usesSdkLibrariesOptional = ArrayUtils.appendBoolean(this.usesSdkLibrariesOptional,
+                usesSdkLibrariesOptional);
         return this;
     }
 
@@ -1468,6 +1471,12 @@
     @Override
     public long[] getUsesSdkLibrariesVersionsMajor() { return usesSdkLibrariesVersionsMajor; }
 
+    @Nullable
+    @Override
+    public boolean[] getUsesSdkLibrariesOptional() {
+        return usesSdkLibrariesOptional;
+    }
+
     @NonNull
     @Override
     public List<String> getUsesStaticLibraries() {
@@ -2669,12 +2678,16 @@
     private String mBaseAppDataCredentialProtectedDirForSystemUser;
     private String mBaseAppDataDeviceProtectedDirForSystemUser;
 
+    ParsingPackageUtils.Callback mCallback;
+
     @VisibleForTesting
     public PackageImpl(@NonNull String packageName, @NonNull String baseApkPath,
-            @NonNull String path, @Nullable TypedArray manifestArray, boolean isCoreApp) {
+            @NonNull String path, @Nullable TypedArray manifestArray, boolean isCoreApp,
+            @Nullable ParsingPackageUtils.Callback callback) {
         this.packageName = TextUtils.safeIntern(packageName);
         this.mBaseApkPath = baseApkPath;
         this.mPath = path;
+        this.mCallback = callback;
 
         if (manifestArray != null) {
             versionCode = manifestArray.getInteger(R.styleable.AndroidManifest_versionCode, 0);
@@ -2725,9 +2738,11 @@
     }
 
     private void assignDerivedFields2() {
-        mBaseAppInfoFlags = PackageInfoUtils.appInfoFlags(this, null);
-        mBaseAppInfoPrivateFlags = PackageInfoUtils.appInfoPrivateFlags(this, null);
-        mBaseAppInfoPrivateFlagsExt = PackageInfoUtils.appInfoPrivateFlagsExt(this, null);
+        mBaseAppInfoFlags = AppInfoUtils.appInfoFlags(this);
+        mBaseAppInfoPrivateFlags = AppInfoUtils.appInfoPrivateFlags(this);
+        mBaseAppInfoPrivateFlagsExt = AppInfoUtils.appInfoPrivateFlagsExt(this,
+                mCallback == null ? false :
+                        mCallback.getHiddenApiWhitelistedApps().contains(this.packageName));
         String baseAppDataDir = Environment.getDataDirectoryPath(getVolumeUuid()) + File.separator;
         String systemUserSuffix = File.separator + UserHandle.USER_SYSTEM + File.separator;
         mBaseAppDataCredentialProtectedDirForSystemUser = TextUtils.safeIntern(
@@ -3062,7 +3077,7 @@
         appInfo.primaryCpuAbi = primaryCpuAbi;
         appInfo.secondaryCpuAbi = secondaryCpuAbi;
         appInfo.secondaryNativeLibraryDir = secondaryNativeLibraryDir;
-        appInfo.seInfoUser = SELinuxUtil.COMPLETE_STR;
+        appInfo.seInfoUser = SEInfoUtil.COMPLETE_STR;
         appInfo.uid = uid;
         return appInfo;
     }
@@ -3126,6 +3141,7 @@
                 dest.writeStringArray(this.usesSdkLibrariesCertDigests[index]);
             }
         }
+        dest.writeBooleanArray(this.usesSdkLibrariesOptional);
 
         sForInternedString.parcel(this.sharedUserId, dest, flags);
         dest.writeInt(this.sharedUserLabel);
@@ -3278,6 +3294,7 @@
                 }
             }
         }
+        this.usesSdkLibrariesOptional = in.createBooleanArray();
 
         this.sharedUserId = sForInternedString.unparcel(in);
         this.sharedUserLabel = in.readInt();
diff --git a/services/core/java/com/android/server/pm/permission/CompatibilityPermissionInfo.java b/core/java/com/android/internal/pm/permission/CompatibilityPermissionInfo.java
similarity index 85%
rename from services/core/java/com/android/server/pm/permission/CompatibilityPermissionInfo.java
rename to core/java/com/android/internal/pm/permission/CompatibilityPermissionInfo.java
index d962505..a670c6d 100644
--- a/services/core/java/com/android/server/pm/permission/CompatibilityPermissionInfo.java
+++ b/core/java/com/android/internal/pm/permission/CompatibilityPermissionInfo.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.pm.permission;
+package com.android.internal.pm.permission;
 
 import android.Manifest;
 import android.annotation.NonNull;
@@ -67,7 +67,7 @@
     // CHECKSTYLE:OFF Generated code
     //
     // To regenerate run:
-    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/permission/CompatibilityPermissionInfo.java
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/com/android/internal/pm/permission/CompatibilityPermissionInfo.java
     //
     // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
     //   Settings > Editor > Code Style > Formatter Control
@@ -97,10 +97,10 @@
     }
 
     @DataClass.Generated(
-            time = 1627674427184L,
+            time = 1701338392152L,
             codegenVersion = "1.0.23",
-            sourceFile = "frameworks/base/core/java/android/content/pm/permission/CompatibilityPermissionInfo.java",
-            inputSignatures = "private final @android.annotation.NonNull java.lang.String mName\nprivate final  int mSdkVersion\npublic static final  android.content.pm.permission.CompatibilityPermissionInfo[] COMPAT_PERMS\nclass CompatibilityPermissionInfo extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genGetters=true, genBuilder=false)")
+            sourceFile = "frameworks/base/core/java/com/android/internal/pm/permission/CompatibilityPermissionInfo.java",
+            inputSignatures = "private final @android.annotation.NonNull java.lang.String mName\nprivate final  int mSdkVersion\npublic static final  com.android.internal.pm.permission.CompatibilityPermissionInfo[] COMPAT_PERMS\nclass CompatibilityPermissionInfo extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genGetters=true, genBuilder=false)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/core/java/com/android/internal/pm/pkg/SEInfoUtil.java b/core/java/com/android/internal/pm/pkg/SEInfoUtil.java
new file mode 100644
index 0000000..a698882
--- /dev/null
+++ b/core/java/com/android/internal/pm/pkg/SEInfoUtil.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.pm.pkg;
+
+/**
+ * Utility methods that need to be used in application space.
+ * @hide
+ */
+public final class SEInfoUtil {
+
+    /** Append to existing seinfo label for instant apps @hide */
+    public static final String INSTANT_APP_STR = ":ephemeralapp";
+
+    /** Append to existing seinfo when modifications are complete @hide */
+    public static final String COMPLETE_STR = ":complete";
+}
diff --git a/services/core/java/com/android/server/pm/pkg/component/ComponentMutateUtils.java b/core/java/com/android/internal/pm/pkg/component/ComponentMutateUtils.java
similarity index 88%
rename from services/core/java/com/android/server/pm/pkg/component/ComponentMutateUtils.java
rename to core/java/com/android/internal/pm/pkg/component/ComponentMutateUtils.java
index 1964df0..fd5f0f0 100644
--- a/services/core/java/com/android/server/pm/pkg/component/ComponentMutateUtils.java
+++ b/core/java/com/android/internal/pm/pkg/component/ComponentMutateUtils.java
@@ -14,19 +14,11 @@
  * limitations under the License.
  */
 
-package com.android.server.pm.pkg.component;
+package com.android.internal.pm.pkg.component;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 
-import com.android.internal.pm.pkg.component.ParsedActivity;
-import com.android.internal.pm.pkg.component.ParsedComponent;
-import com.android.internal.pm.pkg.component.ParsedMainComponent;
-import com.android.internal.pm.pkg.component.ParsedPermission;
-import com.android.internal.pm.pkg.component.ParsedPermissionGroup;
-import com.android.internal.pm.pkg.component.ParsedProcess;
-import com.android.internal.pm.pkg.component.ParsedProvider;
-
 /**
  * Contains mutation methods so that code doesn't have to cast to the Impl. Meant to eventually
  * be removed once all post-parsing mutation is moved to parsing.
diff --git a/services/core/java/com/android/server/pm/pkg/component/ComponentParseUtils.java b/core/java/com/android/internal/pm/pkg/component/ComponentParseUtils.java
similarity index 85%
rename from services/core/java/com/android/server/pm/pkg/component/ComponentParseUtils.java
rename to core/java/com/android/internal/pm/pkg/component/ComponentParseUtils.java
index 019ca13..db08005 100644
--- a/services/core/java/com/android/server/pm/pkg/component/ComponentParseUtils.java
+++ b/core/java/com/android/internal/pm/pkg/component/ComponentParseUtils.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.pm.pkg.component;
+package com.android.internal.pm.pkg.component;
 
 import android.annotation.AttrRes;
 import android.annotation.NonNull;
@@ -29,14 +29,9 @@
 import android.content.res.XmlResourceParser;
 import android.text.TextUtils;
 
-import com.android.internal.pm.pkg.component.ParsedComponent;
-import com.android.internal.pm.pkg.component.ParsedIntentInfo;
-import com.android.internal.pm.pkg.component.ParsedMainComponent;
 import com.android.internal.pm.pkg.parsing.ParsingPackage;
-import com.android.server.pm.pkg.PackageUserState;
-import com.android.server.pm.pkg.PackageUserStateUtils;
-import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
-import com.android.server.pm.pkg.parsing.ParsingUtils;
+import com.android.internal.pm.pkg.parsing.ParsingPackageUtils;
+import com.android.internal.pm.pkg.parsing.ParsingUtils;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -173,16 +168,4 @@
     public static int getIcon(ParsedComponent component) {
         return component.getIcon();
     }
-
-    public static boolean isMatch(PackageUserState state, boolean isSystem,
-            boolean isPackageEnabled, ParsedMainComponent component, long flags) {
-        return PackageUserStateUtils.isMatch(state, isSystem, isPackageEnabled,
-                component.isEnabled(), component.isDirectBootAware(), component.getName(), flags);
-    }
-
-    public static boolean isEnabled(PackageUserState state, boolean isPackageEnabled,
-            ParsedMainComponent parsedComponent, long flags) {
-        return PackageUserStateUtils.isEnabled(state, isPackageEnabled, parsedComponent.isEnabled(),
-                parsedComponent.getName(), flags);
-    }
 }
diff --git a/services/core/java/com/android/server/pm/pkg/component/InstallConstraintsTagParser.java b/core/java/com/android/internal/pm/pkg/component/InstallConstraintsTagParser.java
similarity index 94%
rename from services/core/java/com/android/server/pm/pkg/component/InstallConstraintsTagParser.java
rename to core/java/com/android/internal/pm/pkg/component/InstallConstraintsTagParser.java
index dd54cfc..0b04591 100644
--- a/services/core/java/com/android/server/pm/pkg/component/InstallConstraintsTagParser.java
+++ b/core/java/com/android/internal/pm/pkg/component/InstallConstraintsTagParser.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.pm.pkg.component;
+package com.android.internal.pm.pkg.component;
 
 
 import android.content.pm.parsing.result.ParseInput;
@@ -27,7 +27,6 @@
 
 import com.android.internal.R;
 import com.android.internal.pm.pkg.parsing.ParsingPackage;
-import com.android.server.SystemConfig;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -48,9 +47,8 @@
      * @hide
      */
     public static ParseResult<ParsingPackage> parseInstallConstraints(
-            ParseInput input, ParsingPackage pkg, Resources res, XmlResourceParser parser)
-            throws XmlPullParserException, IOException {
-        Set<String> allowlist = SystemConfig.getInstance().getInstallConstraintsAllowlist();
+            ParseInput input, ParsingPackage pkg, Resources res, XmlResourceParser parser,
+            Set<String> allowlist) throws XmlPullParserException, IOException {
         if (!allowlist.contains(pkg.getPackageName())) {
             return input.skip("install-constraints cannot be used by this package");
         }
diff --git a/services/core/java/com/android/server/pm/pkg/component/ParsedActivityImpl.java b/core/java/com/android/internal/pm/pkg/component/ParsedActivityImpl.java
similarity index 92%
rename from services/core/java/com/android/server/pm/pkg/component/ParsedActivityImpl.java
rename to core/java/com/android/internal/pm/pkg/component/ParsedActivityImpl.java
index f027901..2f977ee 100644
--- a/services/core/java/com/android/server/pm/pkg/component/ParsedActivityImpl.java
+++ b/core/java/com/android/internal/pm/pkg/component/ParsedActivityImpl.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.pm.pkg.component;
+package com.android.internal.pm.pkg.component;
 
 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
@@ -22,8 +22,8 @@
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
 
-import static com.android.server.pm.parsing.pkg.PackageImpl.sForInternedString;
-import static com.android.server.pm.parsing.pkg.PackageImpl.sForStringSet;
+import static com.android.internal.pm.parsing.pkg.PackageImpl.sForInternedString;
+import static com.android.internal.pm.parsing.pkg.PackageImpl.sForStringSet;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -36,10 +36,9 @@
 import android.text.TextUtils;
 import android.util.ArraySet;
 
-import com.android.internal.pm.pkg.component.ParsedActivity;
 import com.android.internal.util.DataClass;
 import com.android.internal.util.Parcelling.BuiltIn.ForInternedString;
-import com.android.server.pm.pkg.parsing.ParsingUtils;
+import com.android.internal.pm.pkg.parsing.ParsingUtils;
 
 import java.util.Collections;
 import java.util.Locale;
@@ -380,7 +379,7 @@
     // CHECKSTYLE:OFF Generated code
     //
     // To regenerate run:
-    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/services/core/java/com/android/server/pm/pkg/component/ParsedActivityImpl.java
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/com/android/internal/pm/pkg/component/ParsedActivityImpl.java
     //
     // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
     //   Settings > Editor > Code Style > Formatter Control
@@ -696,10 +695,10 @@
     }
 
     @DataClass.Generated(
-            time = 1669437519576L,
+            time = 1701338377709L,
             codegenVersion = "1.0.23",
-            sourceFile = "frameworks/base/services/core/java/com/android/server/pm/pkg/component/ParsedActivityImpl.java",
-            inputSignatures = "private  int theme\nprivate  int uiOptions\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String targetActivity\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String parentActivityName\nprivate @android.annotation.Nullable java.lang.String taskAffinity\nprivate  int privateFlags\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String permission\nprivate @android.annotation.Nullable java.util.Set<java.lang.String> mKnownActivityEmbeddingCerts\nprivate  int launchMode\nprivate  int documentLaunchMode\nprivate  int maxRecents\nprivate  int configChanges\nprivate  int softInputMode\nprivate  int persistableMode\nprivate  int lockTaskLaunchMode\nprivate  int screenOrientation\nprivate  int resizeMode\nprivate  float maxAspectRatio\nprivate  float minAspectRatio\nprivate  boolean supportsSizeChanges\nprivate @android.annotation.Nullable java.lang.String requestedVrComponent\nprivate  int rotationAnimation\nprivate  int colorMode\nprivate @android.annotation.Nullable android.content.pm.ActivityInfo.WindowLayout windowLayout\nprivate @android.annotation.Nullable java.lang.String mRequiredDisplayCategory\npublic static final @android.annotation.NonNull android.os.Parcelable.Creator<com.android.server.pm.pkg.component.ParsedActivityImpl> CREATOR\nstatic @android.annotation.NonNull com.android.server.pm.pkg.component.ParsedActivityImpl makeAppDetailsActivity(java.lang.String,java.lang.String,int,java.lang.String,boolean)\nstatic @android.annotation.NonNull com.android.server.pm.pkg.component.ParsedActivityImpl makeAlias(java.lang.String,com.android.internal.pm.pkg.component.ParsedActivity)\npublic  com.android.server.pm.pkg.component.ParsedActivityImpl setMaxAspectRatio(int,float)\npublic  com.android.server.pm.pkg.component.ParsedActivityImpl setMinAspectRatio(int,float)\npublic  com.android.server.pm.pkg.component.ParsedActivityImpl setTargetActivity(java.lang.String)\npublic  com.android.server.pm.pkg.component.ParsedActivityImpl setPermission(java.lang.String)\npublic @android.annotation.NonNull @java.lang.Override java.util.Set<java.lang.String> getKnownActivityEmbeddingCerts()\npublic  void setKnownActivityEmbeddingCerts(java.util.Set<java.lang.String>)\npublic  java.lang.String toString()\npublic @java.lang.Override int describeContents()\npublic @java.lang.Override void writeToParcel(android.os.Parcel,int)\nclass ParsedActivityImpl extends com.android.server.pm.pkg.component.ParsedMainComponentImpl implements [com.android.internal.pm.pkg.component.ParsedActivity, android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=true, genBuilder=false, genParcelable=false)")
+            sourceFile = "frameworks/base/core/java/com/android/internal/pm/pkg/component/ParsedActivityImpl.java",
+            inputSignatures = "private  int theme\nprivate  int uiOptions\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String targetActivity\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String parentActivityName\nprivate @android.annotation.Nullable java.lang.String taskAffinity\nprivate  int privateFlags\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String permission\nprivate @android.annotation.Nullable java.util.Set<java.lang.String> mKnownActivityEmbeddingCerts\nprivate  int launchMode\nprivate  int documentLaunchMode\nprivate  int maxRecents\nprivate  int configChanges\nprivate  int softInputMode\nprivate  int persistableMode\nprivate  int lockTaskLaunchMode\nprivate  int screenOrientation\nprivate  int resizeMode\nprivate  float maxAspectRatio\nprivate  float minAspectRatio\nprivate  boolean supportsSizeChanges\nprivate @android.annotation.Nullable java.lang.String requestedVrComponent\nprivate  int rotationAnimation\nprivate  int colorMode\nprivate @android.annotation.Nullable android.content.pm.ActivityInfo.WindowLayout windowLayout\nprivate @android.annotation.Nullable java.lang.String mRequiredDisplayCategory\npublic static final @android.annotation.NonNull android.os.Parcelable.Creator<com.android.internal.pm.pkg.component.ParsedActivityImpl> CREATOR\npublic static @android.annotation.NonNull com.android.internal.pm.pkg.component.ParsedActivityImpl makeAppDetailsActivity(java.lang.String,java.lang.String,int,java.lang.String,boolean)\nstatic @android.annotation.NonNull com.android.internal.pm.pkg.component.ParsedActivityImpl makeAlias(java.lang.String,com.android.internal.pm.pkg.component.ParsedActivity)\npublic  com.android.internal.pm.pkg.component.ParsedActivityImpl setMaxAspectRatio(int,float)\npublic  com.android.internal.pm.pkg.component.ParsedActivityImpl setMinAspectRatio(int,float)\npublic  com.android.internal.pm.pkg.component.ParsedActivityImpl setTargetActivity(java.lang.String)\npublic  com.android.internal.pm.pkg.component.ParsedActivityImpl setPermission(java.lang.String)\npublic @android.annotation.NonNull @java.lang.Override java.util.Set<java.lang.String> getKnownActivityEmbeddingCerts()\npublic  void setKnownActivityEmbeddingCerts(java.util.Set<java.lang.String>)\npublic  java.lang.String toString()\npublic @java.lang.Override int describeContents()\npublic @java.lang.Override void writeToParcel(android.os.Parcel,int)\nclass ParsedActivityImpl extends com.android.internal.pm.pkg.component.ParsedMainComponentImpl implements [com.android.internal.pm.pkg.component.ParsedActivity, android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=true, genBuilder=false, genParcelable=false)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/services/core/java/com/android/server/pm/pkg/component/ParsedActivityUtils.java b/core/java/com/android/internal/pm/pkg/component/ParsedActivityUtils.java
similarity index 98%
rename from services/core/java/com/android/server/pm/pkg/component/ParsedActivityUtils.java
rename to core/java/com/android/internal/pm/pkg/component/ParsedActivityUtils.java
index 64985bd..c3f7dab 100644
--- a/services/core/java/com/android/server/pm/pkg/component/ParsedActivityUtils.java
+++ b/core/java/com/android/internal/pm/pkg/component/ParsedActivityUtils.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.server.pm.pkg.component;
+package com.android.internal.pm.pkg.component;
 
 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE_PER_TASK;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
 
-import static com.android.server.pm.pkg.component.ComponentParseUtils.flag;
-import static com.android.server.pm.pkg.parsing.ParsingUtils.NOT_SET;
-import static com.android.server.pm.pkg.parsing.ParsingUtils.parseKnownActivityEmbeddingCerts;
+import static com.android.internal.pm.pkg.component.ComponentParseUtils.flag;
+import static com.android.internal.pm.pkg.parsing.ParsingUtils.NOT_SET;
+import static com.android.internal.pm.pkg.parsing.ParsingUtils.parseKnownActivityEmbeddingCerts;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -48,11 +48,10 @@
 
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.pm.pkg.component.ParsedActivity;
 import com.android.internal.pm.pkg.parsing.ParsingPackage;
+import com.android.internal.pm.pkg.parsing.ParsingPackageUtils;
+import com.android.internal.pm.pkg.parsing.ParsingUtils;
 import com.android.internal.util.ArrayUtils;
-import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
-import com.android.server.pm.pkg.parsing.ParsingUtils;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
diff --git a/services/core/java/com/android/server/pm/pkg/component/ParsedApexSystemServiceImpl.java b/core/java/com/android/internal/pm/pkg/component/ParsedApexSystemServiceImpl.java
similarity index 95%
rename from services/core/java/com/android/server/pm/pkg/component/ParsedApexSystemServiceImpl.java
rename to core/java/com/android/internal/pm/pkg/component/ParsedApexSystemServiceImpl.java
index cfed19a..27f7eee 100644
--- a/services/core/java/com/android/server/pm/pkg/component/ParsedApexSystemServiceImpl.java
+++ b/core/java/com/android/internal/pm/pkg/component/ParsedApexSystemServiceImpl.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.pm.pkg.component;
+package com.android.internal.pm.pkg.component;
 
 
 import android.annotation.NonNull;
@@ -22,7 +22,6 @@
 import android.os.Parcelable;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.pm.pkg.component.ParsedApexSystemService;
 import com.android.internal.util.DataClass;
 import com.android.internal.util.Parcelling;
 
@@ -60,7 +59,7 @@
     // CHECKSTYLE:OFF Generated code
     //
     // To regenerate run:
-    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/services/core/java/com/android/server/pm/pkg/component/ParsedApexSystemServiceImpl.java
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/com/android/internal/pm/pkg/component/ParsedApexSystemServiceImpl.java
     //
     // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
     //   Settings > Editor > Code Style > Formatter Control
@@ -248,9 +247,9 @@
     };
 
     @DataClass.Generated(
-            time = 1643723578605L,
+            time = 1701710844088L,
             codegenVersion = "1.0.23",
-            sourceFile = "frameworks/base/services/core/java/com/android/server/pm/pkg/component/ParsedApexSystemServiceImpl.java",
+            sourceFile = "frameworks/base/core/java/com/android/internal/pm/pkg/component/ParsedApexSystemServiceImpl.java",
             inputSignatures = "private @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) @android.annotation.NonNull java.lang.String name\nprivate @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) @android.annotation.Nullable java.lang.String jarPath\nprivate @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) @android.annotation.Nullable java.lang.String minSdkVersion\nprivate @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) @android.annotation.Nullable java.lang.String maxSdkVersion\nprivate  int initOrder\nclass ParsedApexSystemServiceImpl extends java.lang.Object implements [com.android.internal.pm.pkg.component.ParsedApexSystemService, android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genAidl=false, genSetters=true, genParcelable=true)")
     @Deprecated
     private void __metadata() {}
diff --git a/services/core/java/com/android/server/pm/pkg/component/ParsedApexSystemServiceUtils.java b/core/java/com/android/internal/pm/pkg/component/ParsedApexSystemServiceUtils.java
similarity index 95%
rename from services/core/java/com/android/server/pm/pkg/component/ParsedApexSystemServiceUtils.java
rename to core/java/com/android/internal/pm/pkg/component/ParsedApexSystemServiceUtils.java
index d3fb29b..c69213f 100644
--- a/services/core/java/com/android/server/pm/pkg/component/ParsedApexSystemServiceUtils.java
+++ b/core/java/com/android/internal/pm/pkg/component/ParsedApexSystemServiceUtils.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.pm.pkg.component;
+package com.android.internal.pm.pkg.component;
 
 import android.R;
 import android.annotation.NonNull;
@@ -25,8 +25,6 @@
 import android.content.res.XmlResourceParser;
 import android.text.TextUtils;
 
-import com.android.internal.pm.pkg.component.ParsedApexSystemService;
-
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
diff --git a/services/core/java/com/android/server/pm/pkg/component/ParsedAttributionImpl.java b/core/java/com/android/internal/pm/pkg/component/ParsedAttributionImpl.java
similarity index 91%
rename from services/core/java/com/android/server/pm/pkg/component/ParsedAttributionImpl.java
rename to core/java/com/android/internal/pm/pkg/component/ParsedAttributionImpl.java
index 62b9947..e3bfb38 100644
--- a/services/core/java/com/android/server/pm/pkg/component/ParsedAttributionImpl.java
+++ b/core/java/com/android/internal/pm/pkg/component/ParsedAttributionImpl.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.pm.pkg.component;
+package com.android.internal.pm.pkg.component;
 
 import android.annotation.NonNull;
 import android.annotation.StringRes;
@@ -22,7 +22,6 @@
 import android.os.Parcelable;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.pm.pkg.component.ParsedAttribution;
 import com.android.internal.util.DataClass;
 
 import java.util.ArrayList;
@@ -60,7 +59,7 @@
     // CHECKSTYLE:OFF Generated code
     //
     // To regenerate run:
-    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/parsing/component/ParsedAttributionImpl.java
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/com/android/internal/pm/pkg/component/ParsedAttributionImpl.java
     //
     // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
     //   Settings > Editor > Code Style > Formatter Control
@@ -207,10 +206,10 @@
     };
 
     @DataClass.Generated(
-            time = 1641431950829L,
+            time = 1701338881658L,
             codegenVersion = "1.0.23",
-            sourceFile = "frameworks/base/core/java/android/content/pm/parsing/component/ParsedAttributionImpl.java",
-            inputSignatures = "static final  int MAX_NUM_ATTRIBUTIONS\nprivate @android.annotation.NonNull java.lang.String tag\nprivate @android.annotation.StringRes int label\nprivate @android.annotation.NonNull java.util.List<java.lang.String> inheritFrom\nclass ParsedAttributionImpl extends java.lang.Object implements [android.content.pm.parsing.component.ParsedAttribution, android.os.Parcelable]\n@com.android.internal.util.DataClass(genAidl=false, genSetters=true, genBuilder=false, genParcelable=true)")
+            sourceFile = "frameworks/base/core/java/com/android/internal/pm/pkg/component/ParsedAttributionImpl.java",
+            inputSignatures = "static final  int MAX_NUM_ATTRIBUTIONS\nprivate @android.annotation.NonNull java.lang.String tag\nprivate @android.annotation.StringRes int label\nprivate @android.annotation.NonNull java.util.List<java.lang.String> inheritFrom\nclass ParsedAttributionImpl extends java.lang.Object implements [com.android.internal.pm.pkg.component.ParsedAttribution, android.os.Parcelable]\n@com.android.internal.util.DataClass(genAidl=false, genSetters=true, genBuilder=false, genParcelable=true)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/services/core/java/com/android/server/pm/pkg/component/ParsedAttributionUtils.java b/core/java/com/android/internal/pm/pkg/component/ParsedAttributionUtils.java
similarity index 97%
rename from services/core/java/com/android/server/pm/pkg/component/ParsedAttributionUtils.java
rename to core/java/com/android/internal/pm/pkg/component/ParsedAttributionUtils.java
index 411220a..ee5c320 100644
--- a/services/core/java/com/android/server/pm/pkg/component/ParsedAttributionUtils.java
+++ b/core/java/com/android/internal/pm/pkg/component/ParsedAttributionUtils.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.pm.pkg.component;
+package com.android.internal.pm.pkg.component;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -26,7 +26,6 @@
 import android.util.ArraySet;
 
 import com.android.internal.R;
-import com.android.internal.pm.pkg.component.ParsedAttribution;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
diff --git a/services/core/java/com/android/server/pm/pkg/component/ParsedComponentImpl.java b/core/java/com/android/internal/pm/pkg/component/ParsedComponentImpl.java
similarity index 82%
rename from services/core/java/com/android/server/pm/pkg/component/ParsedComponentImpl.java
rename to core/java/com/android/internal/pm/pkg/component/ParsedComponentImpl.java
index 512e5c7..7ee22f3 100644
--- a/services/core/java/com/android/server/pm/pkg/component/ParsedComponentImpl.java
+++ b/core/java/com/android/internal/pm/pkg/component/ParsedComponentImpl.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.server.pm.pkg.component;
+package com.android.internal.pm.pkg.component;
 
-import static com.android.server.pm.parsing.pkg.PackageImpl.sForInternedString;
+import static com.android.internal.pm.parsing.pkg.PackageImpl.sForInternedString;
 
 import static java.util.Collections.emptyMap;
 
@@ -32,12 +32,10 @@
 import android.util.ArrayMap;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.pm.pkg.component.ParsedComponent;
-import com.android.internal.pm.pkg.component.ParsedIntentInfo;
+import com.android.internal.pm.pkg.parsing.ParsingUtils;
 import com.android.internal.util.CollectionUtils;
 import com.android.internal.util.DataClass;
 import com.android.internal.util.Parcelling.BuiltIn.ForInternedString;
-import com.android.server.pm.pkg.parsing.ParsingUtils;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -200,7 +198,7 @@
     // CHECKSTYLE:OFF Generated code
     //
     // To regenerate run:
-    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/parsing/component/ParsedComponentImpl.java
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/com/android/internal/pm/pkg/component/ParsedComponentImpl.java
     //
     // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
     //   Settings > Editor > Code Style > Formatter Control
@@ -306,10 +304,10 @@
     }
 
     @DataClass.Generated(
-            time = 1641414207885L,
+            time = 1701445673589L,
             codegenVersion = "1.0.23",
-            sourceFile = "frameworks/base/core/java/android/content/pm/parsing/component/ParsedComponentImpl.java",
-            inputSignatures = "private @android.annotation.NonNull @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String name\nprivate  int icon\nprivate  int labelRes\nprivate @android.annotation.Nullable java.lang.CharSequence nonLocalizedLabel\nprivate  int logo\nprivate  int banner\nprivate  int descriptionRes\nprivate  int flags\nprivate @android.annotation.NonNull @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String packageName\nprivate @android.annotation.NonNull @com.android.internal.util.DataClass.PluralOf(\"intent\") java.util.List<android.content.pm.parsing.component.ParsedIntentInfoImpl> intents\nprivate @android.annotation.Nullable android.content.ComponentName componentName\nprivate @android.annotation.Nullable android.os.Bundle metaData\nprivate @android.annotation.NonNull java.util.Map<java.lang.String,android.content.pm.PackageManager.Property> mProperties\n  void addIntent(android.content.pm.parsing.component.ParsedIntentInfoImpl)\n  void addProperty(android.content.pm.PackageManager.Property)\npublic  android.content.pm.parsing.component.ParsedComponentImpl setName(java.lang.String)\npublic @android.annotation.CallSuper void setPackageName(java.lang.String)\npublic @java.lang.Override @android.annotation.NonNull android.content.ComponentName getComponentName()\npublic @android.annotation.NonNull @java.lang.Override android.os.Bundle getMetaData()\npublic @android.annotation.NonNull @java.lang.Override java.util.List<android.content.pm.parsing.component.ParsedIntentInfo> getIntents()\npublic @java.lang.Override int describeContents()\npublic @java.lang.Override void writeToParcel(android.os.Parcel,int)\nclass ParsedComponentImpl extends java.lang.Object implements [android.content.pm.parsing.component.ParsedComponent, android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=true, genConstructor=false, genBuilder=false, genParcelable=false)")
+            sourceFile = "frameworks/base/core/java/com/android/internal/pm/pkg/component/ParsedComponentImpl.java",
+            inputSignatures = "private @android.annotation.NonNull @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String name\nprivate  int icon\nprivate  int labelRes\nprivate @android.annotation.Nullable java.lang.CharSequence nonLocalizedLabel\nprivate  int logo\nprivate  int banner\nprivate  int descriptionRes\nprivate  int flags\nprivate @android.annotation.NonNull @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String packageName\nprivate @android.annotation.NonNull @com.android.internal.util.DataClass.PluralOf(\"intent\") java.util.List<com.android.internal.pm.pkg.component.ParsedIntentInfoImpl> intents\nprivate @android.annotation.Nullable android.content.ComponentName componentName\nprivate @android.annotation.Nullable android.os.Bundle metaData\nprivate @android.annotation.NonNull java.util.Map<java.lang.String,android.content.pm.PackageManager.Property> mProperties\npublic  void addIntent(com.android.internal.pm.pkg.component.ParsedIntentInfoImpl)\npublic  void addProperty(android.content.pm.PackageManager.Property)\npublic  com.android.internal.pm.pkg.component.ParsedComponentImpl setName(java.lang.String)\npublic @android.annotation.CallSuper void setPackageName(java.lang.String)\npublic @java.lang.Override @android.annotation.NonNull android.content.ComponentName getComponentName()\npublic @android.annotation.NonNull @java.lang.Override android.os.Bundle getMetaData()\npublic @android.annotation.NonNull @java.lang.Override java.util.List<com.android.internal.pm.pkg.component.ParsedIntentInfo> getIntents()\npublic @java.lang.Override int describeContents()\npublic @java.lang.Override void writeToParcel(android.os.Parcel,int)\nclass ParsedComponentImpl extends java.lang.Object implements [com.android.internal.pm.pkg.component.ParsedComponent, android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=true, genConstructor=false, genBuilder=false, genParcelable=false)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/services/core/java/com/android/server/pm/pkg/component/ParsedComponentUtils.java b/core/java/com/android/internal/pm/pkg/component/ParsedComponentUtils.java
similarity index 94%
rename from services/core/java/com/android/server/pm/pkg/component/ParsedComponentUtils.java
rename to core/java/com/android/internal/pm/pkg/component/ParsedComponentUtils.java
index 9322cf0..9e2548b 100644
--- a/services/core/java/com/android/server/pm/pkg/component/ParsedComponentUtils.java
+++ b/core/java/com/android/internal/pm/pkg/component/ParsedComponentUtils.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.server.pm.pkg.component;
+package com.android.internal.pm.pkg.component;
 
-import static com.android.server.pm.pkg.parsing.ParsingUtils.NOT_SET;
+import static com.android.internal.pm.pkg.parsing.ParsingUtils.NOT_SET;
 
 import android.annotation.NonNull;
 import android.content.pm.PackageManager;
@@ -32,8 +32,8 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.pm.pkg.parsing.ParsingPackage;
-import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
-import com.android.server.pm.pkg.parsing.ParsingUtils;
+import com.android.internal.pm.pkg.parsing.ParsingPackageUtils;
+import com.android.internal.pm.pkg.parsing.ParsingUtils;
 
 /** @hide */
 class ParsedComponentUtils {
diff --git a/services/core/java/com/android/server/pm/pkg/component/ParsedInstrumentationImpl.java b/core/java/com/android/internal/pm/pkg/component/ParsedInstrumentationImpl.java
similarity index 82%
rename from services/core/java/com/android/server/pm/pkg/component/ParsedInstrumentationImpl.java
rename to core/java/com/android/internal/pm/pkg/component/ParsedInstrumentationImpl.java
index 7bfad14..07322e9 100644
--- a/services/core/java/com/android/server/pm/pkg/component/ParsedInstrumentationImpl.java
+++ b/core/java/com/android/internal/pm/pkg/component/ParsedInstrumentationImpl.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.server.pm.pkg.component;
+package com.android.internal.pm.pkg.component;
 
-import static com.android.server.pm.parsing.pkg.PackageImpl.sForInternedString;
+import static com.android.internal.pm.parsing.pkg.PackageImpl.sForInternedString;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -26,7 +26,6 @@
 import android.text.TextUtils;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.pm.pkg.component.ParsedInstrumentation;
 import com.android.internal.util.DataClass;
 import com.android.internal.util.Parcelling.BuiltIn.ForInternedString;
 
@@ -112,7 +111,7 @@
     // CHECKSTYLE:OFF Generated code
     //
     // To regenerate run:
-    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/parsing/component/ParsedInstrumentationImpl.java
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/com/android/internal/pm/pkg/component/ParsedInstrumentationImpl.java
     //
     // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
     //   Settings > Editor > Code Style > Formatter Control
@@ -166,10 +165,10 @@
     }
 
     @DataClass.Generated(
-            time = 1641431951575L,
+            time = 1701445763455L,
             codegenVersion = "1.0.23",
-            sourceFile = "frameworks/base/core/java/android/content/pm/parsing/component/ParsedInstrumentationImpl.java",
-            inputSignatures = "private @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String targetPackage\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String targetProcesses\nprivate  boolean handleProfiling\nprivate  boolean functionalTest\npublic static final @android.annotation.NonNull android.os.Parcelable.Creator<android.content.pm.parsing.component.ParsedInstrumentationImpl> CREATOR\npublic  android.content.pm.parsing.component.ParsedInstrumentationImpl setTargetPackage(java.lang.String)\npublic  android.content.pm.parsing.component.ParsedInstrumentationImpl setTargetProcesses(java.lang.String)\npublic  java.lang.String toString()\npublic @java.lang.Override int describeContents()\npublic @java.lang.Override void writeToParcel(android.os.Parcel,int)\nclass ParsedInstrumentationImpl extends android.content.pm.parsing.component.ParsedComponentImpl implements [android.content.pm.parsing.component.ParsedInstrumentation, android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=true, genBuilder=false, genParcelable=false)")
+            sourceFile = "frameworks/base/core/java/com/android/internal/pm/pkg/component/ParsedInstrumentationImpl.java",
+            inputSignatures = "private @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String targetPackage\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String targetProcesses\nprivate  boolean handleProfiling\nprivate  boolean functionalTest\npublic static final @android.annotation.NonNull android.os.Parcelable.Creator<com.android.internal.pm.pkg.component.ParsedInstrumentationImpl> CREATOR\npublic  com.android.internal.pm.pkg.component.ParsedInstrumentationImpl setTargetPackage(java.lang.String)\npublic  com.android.internal.pm.pkg.component.ParsedInstrumentationImpl setTargetProcesses(java.lang.String)\npublic  java.lang.String toString()\npublic @java.lang.Override int describeContents()\npublic @java.lang.Override void writeToParcel(android.os.Parcel,int)\nclass ParsedInstrumentationImpl extends com.android.internal.pm.pkg.component.ParsedComponentImpl implements [com.android.internal.pm.pkg.component.ParsedInstrumentation, android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=true, genBuilder=false, genParcelable=false)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/services/core/java/com/android/server/pm/pkg/component/ParsedInstrumentationUtils.java b/core/java/com/android/internal/pm/pkg/component/ParsedInstrumentationUtils.java
similarity index 94%
rename from services/core/java/com/android/server/pm/pkg/component/ParsedInstrumentationUtils.java
rename to core/java/com/android/internal/pm/pkg/component/ParsedInstrumentationUtils.java
index a711694..661c8b4 100644
--- a/services/core/java/com/android/server/pm/pkg/component/ParsedInstrumentationUtils.java
+++ b/core/java/com/android/internal/pm/pkg/component/ParsedInstrumentationUtils.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.server.pm.pkg.component;
+package com.android.internal.pm.pkg.component;
 
-import static com.android.server.pm.pkg.parsing.ParsingUtils.NOT_SET;
+import static com.android.internal.pm.pkg.parsing.ParsingUtils.NOT_SET;
 
 import android.annotation.NonNull;
 import android.content.pm.parsing.result.ParseInput;
@@ -26,7 +26,6 @@
 import android.content.res.XmlResourceParser;
 
 import com.android.internal.R;
-import com.android.internal.pm.pkg.component.ParsedInstrumentation;
 import com.android.internal.pm.pkg.parsing.ParsingPackage;
 
 import org.xmlpull.v1.XmlPullParserException;
diff --git a/services/core/java/com/android/server/pm/pkg/component/ParsedIntentInfoImpl.java b/core/java/com/android/internal/pm/pkg/component/ParsedIntentInfoImpl.java
similarity index 89%
rename from services/core/java/com/android/server/pm/pkg/component/ParsedIntentInfoImpl.java
rename to core/java/com/android/internal/pm/pkg/component/ParsedIntentInfoImpl.java
index ab94043..adb49e9 100644
--- a/services/core/java/com/android/server/pm/pkg/component/ParsedIntentInfoImpl.java
+++ b/core/java/com/android/internal/pm/pkg/component/ParsedIntentInfoImpl.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.pm.pkg.component;
+package com.android.internal.pm.pkg.component;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -23,7 +23,6 @@
 import android.os.Parcelable;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.pm.pkg.component.ParsedIntentInfo;
 import com.android.internal.util.DataClass;
 
 /**
@@ -54,7 +53,7 @@
     // CHECKSTYLE:OFF Generated code
     //
     // To regenerate run:
-    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/parsing/component/ParsedIntentInfoImpl.java
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/com/android/internal/pm/pkg/component/ParsedIntentInfoImpl.java
     //
     // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
     //   Settings > Editor > Code Style > Formatter Control
@@ -170,10 +169,10 @@
     };
 
     @DataClass.Generated(
-            time = 1641431952314L,
+            time = 1701445800363L,
             codegenVersion = "1.0.23",
-            sourceFile = "frameworks/base/core/java/android/content/pm/parsing/component/ParsedIntentInfoImpl.java",
-            inputSignatures = "private  boolean mHasDefault\nprivate  int mLabelRes\nprivate @android.annotation.Nullable java.lang.CharSequence mNonLocalizedLabel\nprivate  int mIcon\nprivate @android.annotation.NonNull android.content.IntentFilter mIntentFilter\nclass ParsedIntentInfoImpl extends java.lang.Object implements [android.content.pm.parsing.component.ParsedIntentInfo, android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=true, genParcelable=true, genAidl=false, genBuilder=false, genConstructor=false)")
+            sourceFile = "frameworks/base/core/java/com/android/internal/pm/pkg/component/ParsedIntentInfoImpl.java",
+            inputSignatures = "private  boolean mHasDefault\nprivate  int mLabelRes\nprivate @android.annotation.Nullable java.lang.CharSequence mNonLocalizedLabel\nprivate  int mIcon\nprivate @android.annotation.NonNull android.content.IntentFilter mIntentFilter\nclass ParsedIntentInfoImpl extends java.lang.Object implements [com.android.internal.pm.pkg.component.ParsedIntentInfo, android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=true, genParcelable=true, genAidl=false, genBuilder=false, genConstructor=false)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/services/core/java/com/android/server/pm/pkg/component/ParsedIntentInfoUtils.java b/core/java/com/android/internal/pm/pkg/component/ParsedIntentInfoUtils.java
similarity index 96%
rename from services/core/java/com/android/server/pm/pkg/component/ParsedIntentInfoUtils.java
rename to core/java/com/android/internal/pm/pkg/component/ParsedIntentInfoUtils.java
index e5e214d..c6683cf 100644
--- a/services/core/java/com/android/server/pm/pkg/component/ParsedIntentInfoUtils.java
+++ b/core/java/com/android/internal/pm/pkg/component/ParsedIntentInfoUtils.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.server.pm.pkg.component;
+package com.android.internal.pm.pkg.component;
 
-import static com.android.server.pm.pkg.parsing.ParsingUtils.ANDROID_RES_NAMESPACE;
+import static com.android.internal.pm.pkg.parsing.ParsingUtils.ANDROID_RES_NAMESPACE;
 
 import android.annotation.NonNull;
 import android.content.Intent;
@@ -31,10 +31,9 @@
 import android.util.TypedValue;
 
 import com.android.internal.R;
-import com.android.internal.pm.pkg.component.ParsedIntentInfo;
 import com.android.internal.pm.pkg.parsing.ParsingPackage;
-import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
-import com.android.server.pm.pkg.parsing.ParsingUtils;
+import com.android.internal.pm.pkg.parsing.ParsingPackageUtils;
+import com.android.internal.pm.pkg.parsing.ParsingUtils;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
diff --git a/services/core/java/com/android/server/pm/pkg/component/ParsedMainComponentImpl.java b/core/java/com/android/internal/pm/pkg/component/ParsedMainComponentImpl.java
similarity index 85%
rename from services/core/java/com/android/server/pm/pkg/component/ParsedMainComponentImpl.java
rename to core/java/com/android/internal/pm/pkg/component/ParsedMainComponentImpl.java
index f322eef..bb8f565 100644
--- a/services/core/java/com/android/server/pm/pkg/component/ParsedMainComponentImpl.java
+++ b/core/java/com/android/internal/pm/pkg/component/ParsedMainComponentImpl.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.server.pm.pkg.component;
+package com.android.internal.pm.pkg.component;
 
-import static com.android.server.pm.parsing.pkg.PackageImpl.sForInternedString;
+import static com.android.internal.pm.parsing.pkg.PackageImpl.sForInternedString;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -25,7 +25,6 @@
 import android.text.TextUtils;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.pm.pkg.component.ParsedMainComponent;
 import com.android.internal.util.DataClass;
 import com.android.internal.util.Parcelling.BuiltIn.ForInternedString;
 
@@ -133,7 +132,7 @@
     // CHECKSTYLE:OFF Generated code
     //
     // To regenerate run:
-    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/parsing/component/ParsedMainComponentImpl.java
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/com/android/internal/pm/pkg/component/ParsedMainComponentImpl.java
     //
     // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
     //   Settings > Editor > Code Style > Formatter Control
@@ -227,10 +226,10 @@
     }
 
     @DataClass.Generated(
-            time = 1641414540422L,
+            time = 1701447884766L,
             codegenVersion = "1.0.23",
-            sourceFile = "frameworks/base/core/java/android/content/pm/parsing/component/ParsedMainComponentImpl.java",
-            inputSignatures = "private @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String processName\nprivate  boolean directBootAware\nprivate  boolean enabled\nprivate  boolean exported\nprivate  int order\nprivate @android.annotation.Nullable java.lang.String splitName\nprivate @android.annotation.Nullable java.lang.String[] attributionTags\npublic static final  android.os.Parcelable.Creator<android.content.pm.parsing.component.ParsedMainComponentImpl> CREATOR\npublic  android.content.pm.parsing.component.ParsedMainComponentImpl setProcessName(java.lang.String)\npublic  java.lang.String getClassName()\npublic @android.annotation.NonNull @java.lang.Override java.lang.String[] getAttributionTags()\npublic @java.lang.Override int describeContents()\npublic @java.lang.Override void writeToParcel(android.os.Parcel,int)\nclass ParsedMainComponentImpl extends android.content.pm.parsing.component.ParsedComponentImpl implements [android.content.pm.parsing.component.ParsedMainComponent, android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=true, genBuilder=false, genParcelable=false)")
+            sourceFile = "frameworks/base/core/java/com/android/internal/pm/pkg/component/ParsedMainComponentImpl.java",
+            inputSignatures = "private @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String processName\nprivate  boolean directBootAware\nprivate  boolean enabled\nprivate  boolean exported\nprivate  int order\nprivate @android.annotation.Nullable java.lang.String splitName\nprivate @android.annotation.Nullable java.lang.String[] attributionTags\npublic static final  android.os.Parcelable.Creator<com.android.internal.pm.pkg.component.ParsedMainComponentImpl> CREATOR\npublic  com.android.internal.pm.pkg.component.ParsedMainComponentImpl setProcessName(java.lang.String)\npublic  java.lang.String getClassName()\npublic @android.annotation.NonNull @java.lang.Override java.lang.String[] getAttributionTags()\npublic @java.lang.Override int describeContents()\npublic @java.lang.Override void writeToParcel(android.os.Parcel,int)\nclass ParsedMainComponentImpl extends com.android.internal.pm.pkg.component.ParsedComponentImpl implements [com.android.internal.pm.pkg.component.ParsedMainComponent, android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=true, genBuilder=false, genParcelable=false)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/services/core/java/com/android/server/pm/pkg/component/ParsedMainComponentUtils.java b/core/java/com/android/internal/pm/pkg/component/ParsedMainComponentUtils.java
similarity index 95%
rename from services/core/java/com/android/server/pm/pkg/component/ParsedMainComponentUtils.java
rename to core/java/com/android/internal/pm/pkg/component/ParsedMainComponentUtils.java
index 8268f0f..7e56180 100644
--- a/services/core/java/com/android/server/pm/pkg/component/ParsedMainComponentUtils.java
+++ b/core/java/com/android/internal/pm/pkg/component/ParsedMainComponentUtils.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.server.pm.pkg.component;
+package com.android.internal.pm.pkg.component;
 
-import static com.android.server.pm.pkg.parsing.ParsingUtils.NOT_SET;
+import static com.android.internal.pm.pkg.parsing.ParsingUtils.NOT_SET;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -31,10 +31,8 @@
 import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.pm.pkg.component.ParsedIntentInfo;
-import com.android.internal.pm.pkg.component.ParsedMainComponent;
 import com.android.internal.pm.pkg.parsing.ParsingPackage;
-import com.android.server.pm.pkg.parsing.ParsingUtils;
+import com.android.internal.pm.pkg.parsing.ParsingUtils;
 
 import org.xmlpull.v1.XmlPullParserException;
 
diff --git a/services/core/java/com/android/server/pm/pkg/component/ParsedPermissionGroupImpl.java b/core/java/com/android/internal/pm/pkg/component/ParsedPermissionGroupImpl.java
similarity index 85%
rename from services/core/java/com/android/server/pm/pkg/component/ParsedPermissionGroupImpl.java
rename to core/java/com/android/internal/pm/pkg/component/ParsedPermissionGroupImpl.java
index afe37bc..3622019 100644
--- a/services/core/java/com/android/server/pm/pkg/component/ParsedPermissionGroupImpl.java
+++ b/core/java/com/android/internal/pm/pkg/component/ParsedPermissionGroupImpl.java
@@ -14,14 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.server.pm.pkg.component;
+package com.android.internal.pm.pkg.component;
 
 import android.annotation.NonNull;
 import android.os.Parcel;
 import android.os.Parcelable;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.pm.pkg.component.ParsedPermissionGroup;
 import com.android.internal.util.DataClass;
 
 /**
@@ -75,7 +74,7 @@
     // CHECKSTYLE:OFF Generated code
     //
     // To regenerate run:
-    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/services/core/java/com/android/server/pm/pkg/component/ParsedPermissionGroupImpl.java
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/com/android/internal/pm/pkg/component/ParsedPermissionGroupImpl.java
     //
     // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
     //   Settings > Editor > Code Style > Formatter Control
@@ -172,10 +171,10 @@
     };
 
     @DataClass.Generated(
-            time = 1642132854167L,
+            time = 1701445837884L,
             codegenVersion = "1.0.23",
-            sourceFile = "frameworks/base/services/core/java/com/android/server/pm/pkg/component/ParsedPermissionGroupImpl.java",
-            inputSignatures = "private  int requestDetailRes\nprivate  int backgroundRequestRes\nprivate  int backgroundRequestDetailRes\nprivate  int requestRes\nprivate  int priority\npublic  java.lang.String toString()\npublic @java.lang.Override @com.android.internal.util.DataClass.Generated.Member void writeToParcel(android.os.Parcel,int)\nclass ParsedPermissionGroupImpl extends com.android.server.pm.pkg.component.ParsedComponentImpl implements [com.android.internal.pm.pkg.component.ParsedPermissionGroup, android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=true, genBuilder=false, genParcelable=true, genAidl=false)")
+            sourceFile = "frameworks/base/core/java/com/android/internal/pm/pkg/component/ParsedPermissionGroupImpl.java",
+            inputSignatures = "private  int requestDetailRes\nprivate  int backgroundRequestRes\nprivate  int backgroundRequestDetailRes\nprivate  int requestRes\nprivate  int priority\npublic  java.lang.String toString()\npublic @java.lang.Override void writeToParcel(android.os.Parcel,int)\nclass ParsedPermissionGroupImpl extends com.android.internal.pm.pkg.component.ParsedComponentImpl implements [com.android.internal.pm.pkg.component.ParsedPermissionGroup, android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=true, genBuilder=false, genParcelable=true, genAidl=false)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/services/core/java/com/android/server/pm/pkg/component/ParsedPermissionImpl.java b/core/java/com/android/internal/pm/pkg/component/ParsedPermissionImpl.java
similarity index 77%
rename from services/core/java/com/android/server/pm/pkg/component/ParsedPermissionImpl.java
rename to core/java/com/android/internal/pm/pkg/component/ParsedPermissionImpl.java
index 69e33c8..4dcce131 100644
--- a/services/core/java/com/android/server/pm/pkg/component/ParsedPermissionImpl.java
+++ b/core/java/com/android/internal/pm/pkg/component/ParsedPermissionImpl.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.pm.pkg.component;
+package com.android.internal.pm.pkg.component;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -24,8 +24,6 @@
 import android.util.ArraySet;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.pm.pkg.component.ParsedPermission;
-import com.android.internal.pm.pkg.component.ParsedPermissionGroup;
 import com.android.internal.util.DataClass;
 import com.android.internal.util.Parcelling;
 import com.android.internal.util.Parcelling.BuiltIn.ForInternedString;
@@ -148,7 +146,7 @@
     // CHECKSTYLE:OFF Generated code
     //
     // To regenerate run:
-    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/parsing/component/ParsedPermissionImpl.java
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/com/android/internal/pm/pkg/component/ParsedPermissionImpl.java
     //
     // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
     //   Settings > Editor > Code Style > Formatter Control
@@ -162,7 +160,7 @@
             int requestRes,
             int protectionLevel,
             boolean tree,
-            @Nullable ParsedPermissionGroupImpl parsedPermissionGroup,
+            @Nullable ParsedPermissionGroup parsedPermissionGroup,
             @Nullable Set<String> knownCerts) {
         this.backgroundPermission = backgroundPermission;
         this.group = group;
@@ -237,10 +235,10 @@
     }
 
     @DataClass.Generated(
-            time = 1641414649731L,
+            time = 1701445829812L,
             codegenVersion = "1.0.23",
-            sourceFile = "frameworks/base/core/java/android/content/pm/parsing/component/ParsedPermissionImpl.java",
-            inputSignatures = "private static  com.android.internal.util.Parcelling.BuiltIn.ForStringSet sForStringSet\nprivate @android.annotation.Nullable java.lang.String backgroundPermission\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String group\nprivate  int requestRes\nprivate  int protectionLevel\nprivate  boolean tree\nprivate @android.annotation.Nullable android.content.pm.parsing.component.ParsedPermissionGroupImpl parsedPermissionGroup\nprivate @android.annotation.Nullable java.util.Set<java.lang.String> knownCerts\npublic static final @android.annotation.NonNull android.os.Parcelable.Creator<android.content.pm.parsing.component.ParsedPermissionImpl> CREATOR\npublic  android.content.pm.parsing.component.ParsedPermissionGroup getParsedPermissionGroup()\npublic  android.content.pm.parsing.component.ParsedPermissionImpl setGroup(java.lang.String)\nprotected  void setKnownCert(java.lang.String)\nprotected  void setKnownCerts(java.lang.String[])\npublic @android.annotation.NonNull @java.lang.Override java.util.Set<java.lang.String> getKnownCerts()\npublic  java.lang.String toString()\npublic @java.lang.Override int describeContents()\npublic @java.lang.Override void writeToParcel(android.os.Parcel,int)\nclass ParsedPermissionImpl extends android.content.pm.parsing.component.ParsedComponentImpl implements [android.content.pm.parsing.component.ParsedPermission, android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=true, genBuilder=false, genParcelable=false)")
+            sourceFile = "frameworks/base/core/java/com/android/internal/pm/pkg/component/ParsedPermissionImpl.java",
+            inputSignatures = "private static final  com.android.internal.util.Parcelling.BuiltIn.ForStringSet sForStringSet\nprivate @android.annotation.Nullable java.lang.String backgroundPermission\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String group\nprivate  int requestRes\nprivate  int protectionLevel\nprivate  boolean tree\nprivate @android.annotation.Nullable com.android.internal.pm.pkg.component.ParsedPermissionGroup parsedPermissionGroup\nprivate @android.annotation.Nullable java.util.Set<java.lang.String> knownCerts\npublic static final @android.annotation.NonNull android.os.Parcelable.Creator<com.android.internal.pm.pkg.component.ParsedPermissionImpl> CREATOR\npublic  com.android.internal.pm.pkg.component.ParsedPermissionGroup getParsedPermissionGroup()\npublic  com.android.internal.pm.pkg.component.ParsedPermissionImpl setGroup(java.lang.String)\nprotected  void setKnownCert(java.lang.String)\nprotected  void setKnownCerts(java.lang.String[])\npublic @android.annotation.NonNull @java.lang.Override java.util.Set<java.lang.String> getKnownCerts()\npublic  java.lang.String toString()\npublic @java.lang.Override int describeContents()\npublic @java.lang.Override void writeToParcel(android.os.Parcel,int)\nclass ParsedPermissionImpl extends com.android.internal.pm.pkg.component.ParsedComponentImpl implements [com.android.internal.pm.pkg.component.ParsedPermission, android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=true, genBuilder=false, genParcelable=false)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/services/core/java/com/android/server/pm/pkg/component/ParsedPermissionUtils.java b/core/java/com/android/internal/pm/pkg/component/ParsedPermissionUtils.java
similarity index 97%
rename from services/core/java/com/android/server/pm/pkg/component/ParsedPermissionUtils.java
rename to core/java/com/android/internal/pm/pkg/component/ParsedPermissionUtils.java
index 4b45d37..5651c1c 100644
--- a/services/core/java/com/android/server/pm/pkg/component/ParsedPermissionUtils.java
+++ b/core/java/com/android/internal/pm/pkg/component/ParsedPermissionUtils.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.server.pm.pkg.component;
+package com.android.internal.pm.pkg.component;
 
-import static com.android.server.pm.pkg.parsing.ParsingUtils.NOT_SET;
+import static com.android.internal.pm.pkg.parsing.ParsingUtils.NOT_SET;
 
 import android.annotation.NonNull;
 import android.content.pm.PermissionInfo;
@@ -31,10 +31,8 @@
 import android.util.Slog;
 
 import com.android.internal.R;
-import com.android.internal.pm.pkg.component.ParsedPermission;
-import com.android.internal.pm.pkg.component.ParsedPermissionGroup;
 import com.android.internal.pm.pkg.parsing.ParsingPackage;
-import com.android.server.pm.pkg.parsing.ParsingUtils;
+import com.android.internal.pm.pkg.parsing.ParsingUtils;
 
 import org.xmlpull.v1.XmlPullParserException;
 
diff --git a/services/core/java/com/android/server/pm/pkg/component/ParsedProcessImpl.java b/core/java/com/android/internal/pm/pkg/component/ParsedProcessImpl.java
similarity index 93%
rename from services/core/java/com/android/server/pm/pkg/component/ParsedProcessImpl.java
rename to core/java/com/android/internal/pm/pkg/component/ParsedProcessImpl.java
index 40e3670..212fb86 100644
--- a/services/core/java/com/android/server/pm/pkg/component/ParsedProcessImpl.java
+++ b/core/java/com/android/internal/pm/pkg/component/ParsedProcessImpl.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.pm.pkg.component;
+package com.android.internal.pm.pkg.component;
 
 import static java.util.Collections.emptySet;
 
@@ -25,7 +25,6 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 
-import com.android.internal.pm.pkg.component.ParsedProcess;
 import com.android.internal.util.CollectionUtils;
 import com.android.internal.util.DataClass;
 import com.android.internal.util.Parcelling;
@@ -98,7 +97,7 @@
     // CHECKSTYLE:OFF Generated code
     //
     // To regenerate run:
-    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/parsing/component/ParsedProcessImpl.java
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/com/android/internal/pm/pkg/component/ParsedProcessImpl.java
     //
     // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
     //   Settings > Editor > Code Style > Formatter Control
@@ -304,10 +303,10 @@
     };
 
     @DataClass.Generated(
-            time = 1641431953775L,
+            time = 1701445656489L,
             codegenVersion = "1.0.23",
-            sourceFile = "frameworks/base/core/java/android/content/pm/parsing/component/ParsedProcessImpl.java",
-            inputSignatures = "private @android.annotation.NonNull java.lang.String name\nprivate @android.annotation.NonNull android.util.ArrayMap<java.lang.String,java.lang.String> appClassNamesByPackage\nprivate @android.annotation.NonNull @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedStringSet.class) java.util.Set<java.lang.String> deniedPermissions\nprivate @android.content.pm.ApplicationInfo.GwpAsanMode int gwpAsanMode\nprivate @android.content.pm.ApplicationInfo.MemtagMode int memtagMode\nprivate @android.content.pm.ApplicationInfo.NativeHeapZeroInitialized int nativeHeapZeroInitialized\npublic  void addStateFrom(android.content.pm.parsing.component.ParsedProcess)\npublic  void putAppClassNameForPackage(java.lang.String,java.lang.String)\nclass ParsedProcessImpl extends java.lang.Object implements [android.content.pm.parsing.component.ParsedProcess, android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=true, genParcelable=true, genAidl=false, genBuilder=false)")
+            sourceFile = "frameworks/base/core/java/com/android/internal/pm/pkg/component/ParsedProcessImpl.java",
+            inputSignatures = "private @android.annotation.NonNull java.lang.String name\nprivate @android.annotation.NonNull android.util.ArrayMap<java.lang.String,java.lang.String> appClassNamesByPackage\nprivate @android.annotation.NonNull @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedStringSet.class) java.util.Set<java.lang.String> deniedPermissions\nprivate @android.content.pm.ApplicationInfo.GwpAsanMode int gwpAsanMode\nprivate @android.content.pm.ApplicationInfo.MemtagMode int memtagMode\nprivate @android.content.pm.ApplicationInfo.NativeHeapZeroInitialized int nativeHeapZeroInitialized\npublic  void addStateFrom(com.android.internal.pm.pkg.component.ParsedProcess)\npublic  void putAppClassNameForPackage(java.lang.String,java.lang.String)\nclass ParsedProcessImpl extends java.lang.Object implements [com.android.internal.pm.pkg.component.ParsedProcess, android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=true, genParcelable=true, genAidl=false, genBuilder=false)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/services/core/java/com/android/server/pm/pkg/component/ParsedProcessUtils.java b/core/java/com/android/internal/pm/pkg/component/ParsedProcessUtils.java
similarity index 97%
rename from services/core/java/com/android/server/pm/pkg/component/ParsedProcessUtils.java
rename to core/java/com/android/internal/pm/pkg/component/ParsedProcessUtils.java
index a849549..3b2056e 100644
--- a/services/core/java/com/android/server/pm/pkg/component/ParsedProcessUtils.java
+++ b/core/java/com/android/internal/pm/pkg/component/ParsedProcessUtils.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.pm.pkg.component;
+package com.android.internal.pm.pkg.component;
 
 import android.annotation.NonNull;
 import android.content.pm.ApplicationInfo;
@@ -27,11 +27,10 @@
 import android.util.ArraySet;
 
 import com.android.internal.R;
-import com.android.internal.pm.pkg.component.ParsedProcess;
 import com.android.internal.pm.pkg.parsing.ParsingPackage;
+import com.android.internal.pm.pkg.parsing.ParsingUtils;
 import com.android.internal.util.CollectionUtils;
 import com.android.internal.util.XmlUtils;
-import com.android.server.pm.pkg.parsing.ParsingUtils;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
diff --git a/services/core/java/com/android/server/pm/pkg/component/ParsedProviderImpl.java b/core/java/com/android/internal/pm/pkg/component/ParsedProviderImpl.java
similarity index 90%
rename from services/core/java/com/android/server/pm/pkg/component/ParsedProviderImpl.java
rename to core/java/com/android/internal/pm/pkg/component/ParsedProviderImpl.java
index 81a3c17..987fd41 100644
--- a/services/core/java/com/android/server/pm/pkg/component/ParsedProviderImpl.java
+++ b/core/java/com/android/internal/pm/pkg/component/ParsedProviderImpl.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.server.pm.pkg.component;
+package com.android.internal.pm.pkg.component;
 
-import static com.android.server.pm.parsing.pkg.PackageImpl.sForInternedString;
+import static com.android.internal.pm.parsing.pkg.PackageImpl.sForInternedString;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -28,7 +28,6 @@
 import android.text.TextUtils;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.pm.pkg.component.ParsedProvider;
 import com.android.internal.util.CollectionUtils;
 import com.android.internal.util.DataClass;
 import com.android.internal.util.Parcelling.BuiltIn.ForInternedString;
@@ -302,7 +301,7 @@
             time = 1642560323360L,
             codegenVersion = "1.0.23",
             sourceFile = "frameworks/base/services/core/java/com/android/server/pm/pkg/component/ParsedProviderImpl.java",
-            inputSignatures = "private @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String authority\nprivate  boolean syncable\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String readPermission\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String writePermission\nprivate  boolean grantUriPermissions\nprivate  boolean forceUriPermissions\nprivate  boolean multiProcess\nprivate  int initOrder\nprivate @android.annotation.NonNull java.util.List<android.os.PatternMatcher> uriPermissionPatterns\nprivate @android.annotation.NonNull java.util.List<android.content.pm.PathPermission> pathPermissions\npublic static final @android.annotation.NonNull android.os.Parcelable.Creator<com.android.server.pm.pkg.component.ParsedProviderImpl> CREATOR\npublic  com.android.server.pm.pkg.component.ParsedProviderImpl setReadPermission(java.lang.String)\npublic  com.android.server.pm.pkg.component.ParsedProviderImpl setWritePermission(java.lang.String)\npublic @android.annotation.NonNull com.android.server.pm.pkg.component.ParsedProviderImpl addUriPermissionPattern(android.os.PatternMatcher)\npublic @android.annotation.NonNull com.android.server.pm.pkg.component.ParsedProviderImpl addPathPermission(android.content.pm.PathPermission)\npublic  java.lang.String toString()\npublic @java.lang.Override int describeContents()\npublic @java.lang.Override void writeToParcel(android.os.Parcel,int)\nclass ParsedProviderImpl extends com.android.server.pm.pkg.component.ParsedMainComponentImpl implements [com.android.internal.pm.pkg.component.ParsedProvider, android.os.Parcelable]\n@com.android.internal.util.DataClass(genSetters=true, genGetters=true, genParcelable=false, genBuilder=false)")
+            inputSignatures = "private @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String authority\nprivate  boolean syncable\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String readPermission\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String writePermission\nprivate  boolean grantUriPermissions\nprivate  boolean forceUriPermissions\nprivate  boolean multiProcess\nprivate  int initOrder\nprivate @android.annotation.NonNull java.util.List<android.os.PatternMatcher> uriPermissionPatterns\nprivate @android.annotation.NonNull java.util.List<android.content.pm.PathPermission> pathPermissions\npublic static final @android.annotation.NonNull android.os.Parcelable.Creator<com.android.internal.pm.pkg.component.ParsedProviderImpl> CREATOR\npublic  com.android.internal.pm.pkg.component.ParsedProviderImpl setReadPermission(java.lang.String)\npublic  com.android.internal.pm.pkg.component.ParsedProviderImpl setWritePermission(java.lang.String)\npublic @android.annotation.NonNull com.android.internal.pm.pkg.component.ParsedProviderImpl addUriPermissionPattern(android.os.PatternMatcher)\npublic @android.annotation.NonNull com.android.internal.pm.pkg.component.ParsedProviderImpl addPathPermission(android.content.pm.PathPermission)\npublic  java.lang.String toString()\npublic @java.lang.Override int describeContents()\npublic @java.lang.Override void writeToParcel(android.os.Parcel,int)\nclass ParsedProviderImpl extends com.android.internal.pm.pkg.component.ParsedMainComponentImpl implements [com.android.internal.pm.pkg.component.ParsedProvider, android.os.Parcelable]\n@com.android.internal.util.DataClass(genSetters=true, genGetters=true, genParcelable=false, genBuilder=false)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/services/core/java/com/android/server/pm/pkg/component/ParsedProviderUtils.java b/core/java/com/android/internal/pm/pkg/component/ParsedProviderUtils.java
similarity index 97%
rename from services/core/java/com/android/server/pm/pkg/component/ParsedProviderUtils.java
rename to core/java/com/android/internal/pm/pkg/component/ParsedProviderUtils.java
index 0b28a12..5d82d04 100644
--- a/services/core/java/com/android/server/pm/pkg/component/ParsedProviderUtils.java
+++ b/core/java/com/android/internal/pm/pkg/component/ParsedProviderUtils.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.android.server.pm.pkg.component;
+package com.android.internal.pm.pkg.component;
 
-import static com.android.server.pm.pkg.component.ComponentParseUtils.flag;
-import static com.android.server.pm.pkg.parsing.ParsingPackageUtils.RIGID_PARSER;
+import static com.android.internal.pm.pkg.component.ComponentParseUtils.flag;
+import static com.android.internal.pm.pkg.parsing.ParsingPackageUtils.RIGID_PARSER;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -34,9 +34,8 @@
 import android.util.Slog;
 
 import com.android.internal.R;
-import com.android.internal.pm.pkg.component.ParsedProvider;
 import com.android.internal.pm.pkg.parsing.ParsingPackage;
-import com.android.server.pm.pkg.parsing.ParsingUtils;
+import com.android.internal.pm.pkg.parsing.ParsingUtils;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
diff --git a/services/core/java/com/android/server/pm/pkg/component/ParsedServiceImpl.java b/core/java/com/android/internal/pm/pkg/component/ParsedServiceImpl.java
similarity index 80%
rename from services/core/java/com/android/server/pm/pkg/component/ParsedServiceImpl.java
rename to core/java/com/android/internal/pm/pkg/component/ParsedServiceImpl.java
index ca8c45d..f4662d8 100644
--- a/services/core/java/com/android/server/pm/pkg/component/ParsedServiceImpl.java
+++ b/core/java/com/android/internal/pm/pkg/component/ParsedServiceImpl.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.server.pm.pkg.component;
+package com.android.internal.pm.pkg.component;
 
-import static com.android.server.pm.parsing.pkg.PackageImpl.sForInternedString;
+import static com.android.internal.pm.parsing.pkg.PackageImpl.sForInternedString;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -26,8 +26,6 @@
 import android.text.TextUtils;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.pm.pkg.component.ParsedMainComponent;
-import com.android.internal.pm.pkg.component.ParsedService;
 import com.android.internal.util.DataClass;
 import com.android.internal.util.Parcelling.BuiltIn.ForInternedString;
 
@@ -107,7 +105,7 @@
     // CHECKSTYLE:OFF Generated code
     //
     // To regenerate run:
-    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/parsing/component/ParsedServiceImpl.java
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/com/android/internal/pm/pkg/component/ParsedServiceImpl.java
     //
     // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
     //   Settings > Editor > Code Style > Formatter Control
@@ -141,10 +139,10 @@
     }
 
     @DataClass.Generated(
-            time = 1641431954479L,
+            time = 1701445638370L,
             codegenVersion = "1.0.23",
-            sourceFile = "frameworks/base/core/java/android/content/pm/parsing/component/ParsedServiceImpl.java",
-            inputSignatures = "private  int foregroundServiceType\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String permission\npublic static final @android.annotation.NonNull android.os.Parcelable.Creator<android.content.pm.parsing.component.ParsedServiceImpl> CREATOR\npublic  android.content.pm.parsing.component.ParsedMainComponent setPermission(java.lang.String)\npublic  java.lang.String toString()\npublic @java.lang.Override int describeContents()\npublic @java.lang.Override void writeToParcel(android.os.Parcel,int)\nclass ParsedServiceImpl extends android.content.pm.parsing.component.ParsedMainComponentImpl implements [android.content.pm.parsing.component.ParsedService, android.os.Parcelable]\n@com.android.internal.util.DataClass(genSetters=true, genGetters=true, genParcelable=false, genBuilder=false)")
+            sourceFile = "frameworks/base/core/java/com/android/internal/pm/pkg/component/ParsedServiceImpl.java",
+            inputSignatures = "private  int foregroundServiceType\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String permission\npublic static final @android.annotation.NonNull android.os.Parcelable.Creator<com.android.internal.pm.pkg.component.ParsedServiceImpl> CREATOR\npublic  com.android.internal.pm.pkg.component.ParsedMainComponent setPermission(java.lang.String)\npublic  java.lang.String toString()\npublic @java.lang.Override int describeContents()\npublic @java.lang.Override void writeToParcel(android.os.Parcel,int)\nclass ParsedServiceImpl extends com.android.internal.pm.pkg.component.ParsedMainComponentImpl implements [com.android.internal.pm.pkg.component.ParsedService, android.os.Parcelable]\n@com.android.internal.util.DataClass(genSetters=true, genGetters=true, genParcelable=false, genBuilder=false)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/services/core/java/com/android/server/pm/pkg/component/ParsedServiceUtils.java b/core/java/com/android/internal/pm/pkg/component/ParsedServiceUtils.java
similarity index 96%
rename from services/core/java/com/android/server/pm/pkg/component/ParsedServiceUtils.java
rename to core/java/com/android/internal/pm/pkg/component/ParsedServiceUtils.java
index 171ef59..a1dd19a3 100644
--- a/services/core/java/com/android/server/pm/pkg/component/ParsedServiceUtils.java
+++ b/core/java/com/android/internal/pm/pkg/component/ParsedServiceUtils.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.server.pm.pkg.component;
+package com.android.internal.pm.pkg.component;
 
-import static com.android.server.pm.pkg.component.ComponentParseUtils.flag;
+import static com.android.internal.pm.pkg.component.ComponentParseUtils.flag;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -32,9 +32,8 @@
 import android.os.Build;
 
 import com.android.internal.R;
-import com.android.internal.pm.pkg.component.ParsedService;
 import com.android.internal.pm.pkg.parsing.ParsingPackage;
-import com.android.server.pm.pkg.parsing.ParsingUtils;
+import com.android.internal.pm.pkg.parsing.ParsingUtils;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
diff --git a/services/core/java/com/android/server/pm/pkg/component/ParsedUsesPermissionImpl.java b/core/java/com/android/internal/pm/pkg/component/ParsedUsesPermissionImpl.java
similarity index 87%
rename from services/core/java/com/android/server/pm/pkg/component/ParsedUsesPermissionImpl.java
rename to core/java/com/android/internal/pm/pkg/component/ParsedUsesPermissionImpl.java
index 78377a8..fd131df 100644
--- a/services/core/java/com/android/server/pm/pkg/component/ParsedUsesPermissionImpl.java
+++ b/core/java/com/android/internal/pm/pkg/component/ParsedUsesPermissionImpl.java
@@ -14,14 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.server.pm.pkg.component;
+package com.android.internal.pm.pkg.component;
 
 import android.annotation.NonNull;
 import android.os.Parcel;
 import android.os.Parcelable;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.pm.pkg.component.ParsedUsesPermission;
 import com.android.internal.util.DataClass;
 import com.android.internal.util.Parcelling;
 
@@ -51,7 +50,7 @@
     // CHECKSTYLE:OFF Generated code
     //
     // To regenerate run:
-    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/parsing/component/ParsedUsesPermissionImpl.java
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/com/android/internal/pm/pkg/component/ParsedUsesPermissionImpl.java
     //
     // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
     //   Settings > Editor > Code Style > Formatter Control
@@ -158,10 +157,10 @@
     };
 
     @DataClass.Generated(
-            time = 1641431955242L,
+            time = 1701445626268L,
             codegenVersion = "1.0.23",
-            sourceFile = "frameworks/base/core/java/android/content/pm/parsing/component/ParsedUsesPermissionImpl.java",
-            inputSignatures = "private @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) @android.annotation.NonNull java.lang.String name\nprivate @android.content.pm.parsing.component.ParsedUsesPermission.UsesPermissionFlags int usesPermissionFlags\nclass ParsedUsesPermissionImpl extends java.lang.Object implements [android.content.pm.parsing.component.ParsedUsesPermission, android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=true, genBuilder=false, genParcelable=true, genAidl=false)")
+            sourceFile = "frameworks/base/core/java/com/android/internal/pm/pkg/component/ParsedUsesPermissionImpl.java",
+            inputSignatures = "private @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) @android.annotation.NonNull java.lang.String name\nprivate @com.android.internal.pm.pkg.component.ParsedUsesPermission.UsesPermissionFlags int usesPermissionFlags\nclass ParsedUsesPermissionImpl extends java.lang.Object implements [com.android.internal.pm.pkg.component.ParsedUsesPermission, android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=true, genBuilder=false, genParcelable=true, genAidl=false)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/core/java/com/android/internal/pm/pkg/parsing/ParsingPackage.java b/core/java/com/android/internal/pm/pkg/parsing/ParsingPackage.java
index 4ed361f..6c09b7c 100644
--- a/core/java/com/android/internal/pm/pkg/parsing/ParsingPackage.java
+++ b/core/java/com/android/internal/pm/pkg/parsing/ParsingPackage.java
@@ -112,7 +112,7 @@
     ParsingPackage addUsesOptionalNativeLibrary(String libraryName);
 
     ParsingPackage addUsesSdkLibrary(String libraryName, long versionMajor,
-            String[] certSha256Digests);
+            String[] certSha256Digests, boolean usesSdkLibrariesOptional);
 
     ParsingPackage addUsesStaticLibrary(String libraryName, long version,
             String[] certSha256Digests);
diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java b/core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java
similarity index 96%
rename from services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
rename to core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java
index 722350a..f483597 100644
--- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
+++ b/core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.pm.pkg.parsing;
+package com.android.internal.pm.pkg.parsing;
 
 import static android.content.pm.ActivityInfo.FLAG_SUPPORTS_PICTURE_IN_PICTURE;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
@@ -30,7 +30,7 @@
 import static android.os.Build.VERSION_CODES.O;
 import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
 
-import static com.android.server.pm.pkg.parsing.ParsingUtils.parseKnownActivityEmbeddingCerts;
+import static com.android.internal.pm.pkg.parsing.ParsingUtils.parseKnownActivityEmbeddingCerts;
 
 import android.annotation.AnyRes;
 import android.annotation.CheckResult;
@@ -57,7 +57,6 @@
 import android.content.pm.parsing.result.ParseInput;
 import android.content.pm.parsing.result.ParseInput.DeferredError;
 import android.content.pm.parsing.result.ParseResult;
-import android.content.pm.parsing.result.ParseTypeImpl;
 import android.content.res.ApkAssets;
 import android.content.res.AssetManager;
 import android.content.res.Configuration;
@@ -90,43 +89,40 @@
 import com.android.internal.R;
 import com.android.internal.os.ClassLoaderFactory;
 import com.android.internal.pm.parsing.pkg.ParsedPackage;
+import com.android.internal.pm.permission.CompatibilityPermissionInfo;
+import com.android.internal.pm.pkg.component.ComponentMutateUtils;
+import com.android.internal.pm.pkg.component.ComponentParseUtils;
+import com.android.internal.pm.pkg.component.InstallConstraintsTagParser;
 import com.android.internal.pm.pkg.component.ParsedActivity;
+import com.android.internal.pm.pkg.component.ParsedActivityImpl;
+import com.android.internal.pm.pkg.component.ParsedActivityUtils;
 import com.android.internal.pm.pkg.component.ParsedApexSystemService;
+import com.android.internal.pm.pkg.component.ParsedApexSystemServiceUtils;
 import com.android.internal.pm.pkg.component.ParsedAttribution;
+import com.android.internal.pm.pkg.component.ParsedAttributionUtils;
 import com.android.internal.pm.pkg.component.ParsedComponent;
 import com.android.internal.pm.pkg.component.ParsedInstrumentation;
+import com.android.internal.pm.pkg.component.ParsedInstrumentationUtils;
 import com.android.internal.pm.pkg.component.ParsedIntentInfo;
+import com.android.internal.pm.pkg.component.ParsedIntentInfoImpl;
+import com.android.internal.pm.pkg.component.ParsedIntentInfoUtils;
 import com.android.internal.pm.pkg.component.ParsedMainComponent;
 import com.android.internal.pm.pkg.component.ParsedPermission;
 import com.android.internal.pm.pkg.component.ParsedPermissionGroup;
+import com.android.internal.pm.pkg.component.ParsedPermissionUtils;
 import com.android.internal.pm.pkg.component.ParsedProcess;
+import com.android.internal.pm.pkg.component.ParsedProcessUtils;
 import com.android.internal.pm.pkg.component.ParsedProvider;
+import com.android.internal.pm.pkg.component.ParsedProviderUtils;
 import com.android.internal.pm.pkg.component.ParsedService;
+import com.android.internal.pm.pkg.component.ParsedServiceUtils;
 import com.android.internal.pm.pkg.component.ParsedUsesPermission;
-import com.android.internal.pm.pkg.parsing.ParsingPackage;
+import com.android.internal.pm.pkg.component.ParsedUsesPermissionImpl;
+import com.android.internal.pm.split.DefaultSplitAssetLoader;
+import com.android.internal.pm.split.SplitAssetDependencyLoader;
+import com.android.internal.pm.split.SplitAssetLoader;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.XmlUtils;
-import com.android.server.pm.SharedUidMigration;
-import com.android.server.pm.parsing.pkg.PackageImpl;
-import com.android.server.pm.permission.CompatibilityPermissionInfo;
-import com.android.server.pm.pkg.component.ComponentMutateUtils;
-import com.android.server.pm.pkg.component.ComponentParseUtils;
-import com.android.server.pm.pkg.component.InstallConstraintsTagParser;
-import com.android.server.pm.pkg.component.ParsedActivityImpl;
-import com.android.server.pm.pkg.component.ParsedActivityUtils;
-import com.android.server.pm.pkg.component.ParsedApexSystemServiceUtils;
-import com.android.server.pm.pkg.component.ParsedAttributionUtils;
-import com.android.server.pm.pkg.component.ParsedInstrumentationUtils;
-import com.android.server.pm.pkg.component.ParsedIntentInfoImpl;
-import com.android.server.pm.pkg.component.ParsedIntentInfoUtils;
-import com.android.server.pm.pkg.component.ParsedPermissionUtils;
-import com.android.server.pm.pkg.component.ParsedProcessUtils;
-import com.android.server.pm.pkg.component.ParsedProviderUtils;
-import com.android.server.pm.pkg.component.ParsedServiceUtils;
-import com.android.server.pm.pkg.component.ParsedUsesPermissionImpl;
-import com.android.server.pm.split.DefaultSplitAssetLoader;
-import com.android.server.pm.split.SplitAssetDependencyLoader;
-import com.android.server.pm.split.SplitAssetLoader;
 
 import libcore.io.IoUtils;
 import libcore.util.EmptyArray;
@@ -245,14 +241,6 @@
 
     public static final int PARSE_CHATTY = 1 << 31;
 
-    /** The total maximum number of activities, services, providers and activity-aliases */
-    private static final int MAX_NUM_COMPONENTS = 30000;
-    private static final String MAX_NUM_COMPONENTS_ERR_MSG =
-            "Total number of components has exceeded the maximum number: " + MAX_NUM_COMPONENTS;
-
-    /** The maximum permission name length. */
-    private static final int MAX_PERMISSION_NAME_LENGTH = 512;
-
     @IntDef(flag = true, prefix = { "PARSE_" }, value = {
             PARSE_CHATTY,
             PARSE_COLLECT_CERTIFICATES,
@@ -267,18 +255,6 @@
     public @interface ParseFlags {}
 
     /**
-     * @see #parseDefault(ParseInput, File, int, List, boolean)
-     */
-    @NonNull
-    public static ParseResult<ParsedPackage> parseDefaultOneTime(File file,
-            @ParseFlags int parseFlags,
-            @NonNull List<PermissionManager.SplitPermissionInfo> splitPermissions,
-            boolean collectCertificates) {
-        ParseInput input = ParseTypeImpl.forDefaultParsing().reset();
-        return parseDefault(input, file, parseFlags, splitPermissions, collectCertificates);
-    }
-
-    /**
      * For cases outside of PackageManagerService when an APK needs to be parsed as a one-off
      * request, without caching the input object and without querying the internal system state for
      * feature support.
@@ -287,30 +263,10 @@
     public static ParseResult<ParsedPackage> parseDefault(ParseInput input, File file,
             @ParseFlags int parseFlags,
             @NonNull List<PermissionManager.SplitPermissionInfo> splitPermissions,
-            boolean collectCertificates) {
-        ParseResult<ParsedPackage> result;
+            boolean collectCertificates, Callback callback) {
 
         ParsingPackageUtils parser = new ParsingPackageUtils(null /*separateProcesses*/,
-                null /*displayMetrics*/, splitPermissions, new Callback() {
-            @Override
-            public boolean hasFeature(String feature) {
-                // Assume the device doesn't support anything. This will affect permission
-                // parsing and will force <uses-permission/> declarations to include all
-                // requiredNotFeature permissions and exclude all requiredFeature
-                // permissions. This mirrors the old behavior.
-                return false;
-            }
-
-            @Override
-            public ParsingPackage startParsingPackage(
-                    @NonNull String packageName,
-                    @NonNull String baseApkPath,
-                    @NonNull String path,
-                    @NonNull TypedArray manifestArray, boolean isCoreApp) {
-                return PackageImpl.forParsing(packageName, baseApkPath, path, manifestArray,
-                        isCoreApp);
-            }
-        });
+                null /*displayMetrics*/, splitPermissions, callback);
         var parseResult = parser.parsePackage(input, file, parseFlags);
         if (parseResult.isError()) {
             return input.error(parseResult);
@@ -940,20 +896,11 @@
             if (result.isError()) {
                 return input.error(result);
             }
-
-            if (hasTooManyComponents(pkg)) {
-                return input.error(MAX_NUM_COMPONENTS_ERR_MSG);
-            }
         }
 
         return input.success(pkg);
     }
 
-    private static boolean hasTooManyComponents(ParsingPackage pkg) {
-        return (pkg.getActivities().size() + pkg.getServices().size() + pkg.getProviders().size()
-                + pkg.getReceivers().size()) > MAX_NUM_COMPONENTS;
-    }
-
     /**
      * For parsing non-MainComponents. Main ones have an order and some special handling which is
      * done directly in {@link #parseSplitApplication(ParseInput, ParsingPackage, Resources,
@@ -1146,7 +1093,8 @@
             case TAG_RESTRICT_UPDATE:
                 return parseRestrictUpdateHash(flags, input, pkg, res, parser);
             case TAG_INSTALL_CONSTRAINTS:
-                return parseInstallConstraints(input, pkg, res, parser);
+                return parseInstallConstraints(input, pkg, res, parser,
+                        mCallback.getInstallConstraintsAllowlist());
             case TAG_QUERIES:
                 return parseQueries(input, pkg, res, parser);
             default:
@@ -1172,7 +1120,7 @@
         }
 
         boolean leaving = false;
-        if (!SharedUidMigration.isDisabled()) {
+        if (PackageManager.ENABLE_SHARED_UID_MIGRATION) {
             int max = anInteger(0, R.styleable.AndroidManifest_sharedUserMaxSdkVersion, sa);
             leaving = (max != 0) && (max < Build.VERSION.RESOURCES_SDK_INT);
         }
@@ -1395,11 +1343,6 @@
             // that may change.
             String name = sa.getNonResourceString(
                     R.styleable.AndroidManifestUsesPermission_name);
-            if (TextUtils.length(name) > MAX_PERMISSION_NAME_LENGTH) {
-                return input.error(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                        "The name in the <uses-permission> is greater than "
-                                + MAX_PERMISSION_NAME_LENGTH);
-            }
 
             int minSdkVersion =  parseMinOrMaxSdkVersion(sa,
                     R.styleable.AndroidManifestUsesPermission_minSdkVersion,
@@ -1858,10 +1801,11 @@
         return input.success(pkg);
     }
 
-    private static ParseResult<ParsingPackage> parseInstallConstraints(
-            ParseInput input, ParsingPackage pkg, Resources res, XmlResourceParser parser)
+    private static ParseResult<ParsingPackage> parseInstallConstraints(ParseInput input,
+            ParsingPackage pkg, Resources res, XmlResourceParser parser, Set<String> allowlist)
             throws IOException, XmlPullParserException {
-        return InstallConstraintsTagParser.parseInstallConstraints(input, pkg, res, parser);
+        return InstallConstraintsTagParser.parseInstallConstraints(
+                input, pkg, res, parser, allowlist);
     }
 
     private static ParseResult<ParsingPackage> parseQueries(ParseInput input, ParsingPackage pkg,
@@ -2311,9 +2255,6 @@
             if (result.isError()) {
                 return input.error(result);
             }
-            if (hasTooManyComponents(pkg)) {
-                return input.error(MAX_NUM_COMPONENTS_ERR_MSG);
-            }
         }
 
         if (TextUtils.isEmpty(pkg.getStaticSharedLibraryName()) && TextUtils.isEmpty(
@@ -2598,6 +2539,8 @@
                     R.styleable.AndroidManifestUsesSdkLibrary_versionMajor, -1);
             String certSha256Digest = sa.getNonResourceString(R.styleable
                     .AndroidManifestUsesSdkLibrary_certDigest);
+            boolean optional =
+                    sa.getBoolean(R.styleable.AndroidManifestUsesSdkLibrary_optional, false);
 
             // Since an APK providing a static shared lib can only provide the lib - fail if
             // malformed
@@ -2641,7 +2584,8 @@
             System.arraycopy(additionalCertSha256Digests, 0, certSha256Digests,
                     1, additionalCertSha256Digests.length);
 
-            return input.success(pkg.addUsesSdkLibrary(lname, versionMajor, certSha256Digests));
+            return input.success(
+                    pkg.addUsesSdkLibrary(lname, versionMajor, certSha256Digests, optional));
         } finally {
             sa.recycle();
         }
@@ -3482,5 +3426,9 @@
         ParsingPackage startParsingPackage(@NonNull String packageName,
                 @NonNull String baseApkPath, @NonNull String path,
                 @NonNull TypedArray manifestArray, boolean isCoreApp);
+
+        @NonNull Set<String> getHiddenApiWhitelistedApps();
+
+        @NonNull Set<String> getInstallConstraintsAllowlist();
     }
 }
diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingUtils.java b/core/java/com/android/internal/pm/pkg/parsing/ParsingUtils.java
similarity index 95%
rename from services/core/java/com/android/server/pm/pkg/parsing/ParsingUtils.java
rename to core/java/com/android/internal/pm/pkg/parsing/ParsingUtils.java
index 1d15955..26822c6 100644
--- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingUtils.java
+++ b/core/java/com/android/internal/pm/pkg/parsing/ParsingUtils.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 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.
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.server.pm.pkg.parsing;
+package com.android.internal.pm.pkg.parsing;
 
-import static com.android.server.pm.pkg.parsing.ParsingPackageUtils.RIGID_PARSER;
+import static com.android.internal.pm.pkg.parsing.ParsingPackageUtils.RIGID_PARSER;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -31,10 +31,9 @@
 import android.util.Slog;
 
 import com.android.internal.pm.pkg.component.ParsedIntentInfo;
-import com.android.internal.pm.pkg.parsing.ParsingPackage;
+import com.android.internal.pm.pkg.component.ParsedIntentInfoImpl;
 import com.android.internal.util.Parcelling;
 import com.android.internal.util.XmlUtils;
-import com.android.server.pm.pkg.component.ParsedIntentInfoImpl;
 
 import org.xmlpull.v1.XmlPullParserException;
 
diff --git a/services/core/java/com/android/server/pm/split/DefaultSplitAssetLoader.java b/core/java/com/android/internal/pm/split/DefaultSplitAssetLoader.java
similarity index 94%
rename from services/core/java/com/android/server/pm/split/DefaultSplitAssetLoader.java
rename to core/java/com/android/internal/pm/split/DefaultSplitAssetLoader.java
index 0bb969f..50c6243 100644
--- a/services/core/java/com/android/server/pm/split/DefaultSplitAssetLoader.java
+++ b/core/java/com/android/internal/pm/split/DefaultSplitAssetLoader.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.server.pm.split;
+package com.android.internal.pm.split;
 
 import android.content.pm.parsing.ApkLiteParseUtils;
 import android.content.pm.parsing.PackageLite;
@@ -21,9 +21,9 @@
 import android.content.res.AssetManager;
 import android.os.Build;
 
+import com.android.internal.pm.pkg.parsing.ParsingPackageUtils;
+import com.android.internal.pm.pkg.parsing.ParsingPackageUtils.ParseFlags;
 import com.android.internal.util.ArrayUtils;
-import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
-import com.android.server.pm.pkg.parsing.ParsingPackageUtils.ParseFlags;
 
 import libcore.io.IoUtils;
 
diff --git a/services/core/java/com/android/server/pm/split/SplitAssetDependencyLoader.java b/core/java/com/android/internal/pm/split/SplitAssetDependencyLoader.java
similarity index 96%
rename from services/core/java/com/android/server/pm/split/SplitAssetDependencyLoader.java
rename to core/java/com/android/internal/pm/split/SplitAssetDependencyLoader.java
index 56d92fb..c166cdc 100644
--- a/services/core/java/com/android/server/pm/split/SplitAssetDependencyLoader.java
+++ b/core/java/com/android/internal/pm/split/SplitAssetDependencyLoader.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.server.pm.split;
+package com.android.internal.pm.split;
 
 import android.annotation.NonNull;
 import android.content.pm.parsing.ApkLiteParseUtils;
@@ -24,8 +24,8 @@
 import android.os.Build;
 import android.util.SparseArray;
 
-import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
-import com.android.server.pm.pkg.parsing.ParsingPackageUtils.ParseFlags;
+import com.android.internal.pm.pkg.parsing.ParsingPackageUtils;
+import com.android.internal.pm.pkg.parsing.ParsingPackageUtils.ParseFlags;
 
 import libcore.io.IoUtils;
 
diff --git a/services/core/java/com/android/server/pm/split/SplitAssetLoader.java b/core/java/com/android/internal/pm/split/SplitAssetLoader.java
similarity index 96%
rename from services/core/java/com/android/server/pm/split/SplitAssetLoader.java
rename to core/java/com/android/internal/pm/split/SplitAssetLoader.java
index 8450159..c7c409d 100644
--- a/services/core/java/com/android/server/pm/split/SplitAssetLoader.java
+++ b/core/java/com/android/internal/pm/split/SplitAssetLoader.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.server.pm.split;
+package com.android.internal.pm.split;
 
 import android.content.res.ApkAssets;
 import android.content.res.AssetManager;
diff --git a/core/java/com/android/internal/policy/KeyInterceptionInfo.java b/core/java/com/android/internal/policy/KeyInterceptionInfo.java
index 964be01..b20f6d2 100644
--- a/core/java/com/android/internal/policy/KeyInterceptionInfo.java
+++ b/core/java/com/android/internal/policy/KeyInterceptionInfo.java
@@ -26,10 +26,12 @@
     public final int layoutParamsPrivateFlags;
     // Debug friendly name to help identify the window
     public final String windowTitle;
+    public final int windowOwnerUid;
 
-    public KeyInterceptionInfo(int type, int flags, String title) {
+    public KeyInterceptionInfo(int type, int flags, String title, int uid) {
         layoutParamsType = type;
         layoutParamsPrivateFlags = flags;
         windowTitle = title;
+        windowOwnerUid = uid;
     }
 }
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index dd310dc..201b23c 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -118,6 +118,7 @@
 import android.window.ProxyOnBackInvokedDispatcher;
 
 import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.view.menu.ContextMenuBuilder;
 import com.android.internal.view.menu.IconMenuPresenter;
 import com.android.internal.view.menu.ListMenuPresenter;
@@ -374,7 +375,8 @@
 
     boolean mDecorFitsSystemWindows = true;
 
-    private final boolean mDefaultEdgeToEdge;
+    @VisibleForTesting
+    public final boolean mDefaultEdgeToEdge;
 
     private final ProxyOnBackInvokedDispatcher mProxyOnBackInvokedDispatcher;
 
@@ -2448,6 +2450,7 @@
         // Apply data from current theme.
 
         TypedArray a = getWindowStyle();
+        WindowManager.LayoutParams params = getAttributes();
 
         if (false) {
             System.out.println("From style:");
@@ -2467,8 +2470,11 @@
             setFlags(0, flagsToUpdate);
         } else {
             setFlags(FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR, flagsToUpdate);
-            getAttributes().setFitInsetsSides(0);
-            getAttributes().setFitInsetsTypes(0);
+            params.setFitInsetsSides(0);
+            params.setFitInsetsTypes(0);
+            if (mDefaultEdgeToEdge) {
+                params.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+            }
         }
 
         if (a.getBoolean(R.styleable.Window_windowNoTitle, false)) {
@@ -2586,8 +2592,6 @@
                     R.styleable.Window_enforceNavigationBarContrast, true);
         }
 
-        WindowManager.LayoutParams params = getAttributes();
-
         // Non-floating windows on high end devices must put up decor beneath the system bars and
         // therefore must know about visibility changes of those.
         if (!mIsFloating) {
diff --git a/core/java/com/android/internal/protolog/ProtoLogGroup.java b/core/java/com/android/internal/protolog/ProtoLogGroup.java
index 4bb7c33..8c2a525 100644
--- a/core/java/com/android/internal/protolog/ProtoLogGroup.java
+++ b/core/java/com/android/internal/protolog/ProtoLogGroup.java
@@ -93,6 +93,7 @@
     WM_DEBUG_DREAM(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, true, Consts.TAG_WM),
 
     WM_DEBUG_DIMMER(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false, Consts.TAG_WM),
+    WM_DEBUG_TPL(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false, Consts.TAG_WM),
     TEST_GROUP(true, true, false, "WindowManagerProtoLogTest");
 
     private final boolean mEnabled;
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index 9d0be4b..8f00f79 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -623,6 +623,21 @@
      * Adds value to given array if not already present, providing set-like
      * behavior.
      */
+    public static boolean[] appendBoolean(@Nullable boolean[] cur, boolean val) {
+        if (cur == null) {
+            return new boolean[] { val };
+        }
+        final int N = cur.length;
+        boolean[] ret = new boolean[N + 1];
+        System.arraycopy(cur, 0, ret, 0, N);
+        ret[N] = val;
+        return ret;
+    }
+
+    /**
+     * Adds value to given array if not already present, providing set-like
+     * behavior.
+     */
     public static @NonNull long[] appendLong(@Nullable long[] cur, long val) {
         return appendLong(cur, val, false);
     }
diff --git a/core/java/com/android/internal/util/BitUtils.java b/core/java/com/android/internal/util/BitUtils.java
index 154ea52..d928bbc 100644
--- a/core/java/com/android/internal/util/BitUtils.java
+++ b/core/java/com/android/internal/util/BitUtils.java
@@ -31,6 +31,7 @@
  * sugar methods for {@link ByteBuffer}. Useful for networking and packet manipulations.
  * {@hide}
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public final class BitUtils {
     private BitUtils() {}
 
diff --git a/core/java/com/android/internal/util/BitwiseInputStream.java b/core/java/com/android/internal/util/BitwiseInputStream.java
index ffae3ce..91f89f3 100644
--- a/core/java/com/android/internal/util/BitwiseInputStream.java
+++ b/core/java/com/android/internal/util/BitwiseInputStream.java
@@ -26,6 +26,7 @@
  *
  * NOTE -- This class is not threadsafe.
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class BitwiseInputStream {
 
     // The byte array being read from.
diff --git a/core/java/com/android/internal/util/BitwiseOutputStream.java b/core/java/com/android/internal/util/BitwiseOutputStream.java
index 9f41508..9b7568b 100644
--- a/core/java/com/android/internal/util/BitwiseOutputStream.java
+++ b/core/java/com/android/internal/util/BitwiseOutputStream.java
@@ -26,6 +26,7 @@
  *
  * NOTE -- This class is not threadsafe.
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class BitwiseOutputStream {
 
     // The byte array being written to, which will be grown as needed.
diff --git a/core/java/com/android/internal/util/CallbackRegistry.java b/core/java/com/android/internal/util/CallbackRegistry.java
index 0f228d4..0ae8e1d 100644
--- a/core/java/com/android/internal/util/CallbackRegistry.java
+++ b/core/java/com/android/internal/util/CallbackRegistry.java
@@ -39,6 +39,7 @@
  * @param <T> The notification sender type. Typically this is the containing class.
  * @param <A> Opaque argument used to pass additional data beyond an int.
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class CallbackRegistry<C, T, A> implements Cloneable {
     private static final String TAG = "CallbackRegistry";
 
diff --git a/core/java/com/android/internal/util/DumpUtils.java b/core/java/com/android/internal/util/DumpUtils.java
index 8fe2b9c..d1ff034 100644
--- a/core/java/com/android/internal/util/DumpUtils.java
+++ b/core/java/com/android/internal/util/DumpUtils.java
@@ -37,6 +37,7 @@
  * Test:
  atest FrameworksCoreTests:DumpUtilsTest
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public final class DumpUtils {
 
     /**
@@ -92,6 +93,8 @@
      * @return true if access should be granted.
      * @hide
      */
+    @android.ravenwood.annotation.RavenwoodThrow(
+            blockedBy = android.permission.PermissionManager.class)
     public static boolean checkDumpPermission(Context context, String tag, PrintWriter pw) {
         if (context.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
                 != PackageManager.PERMISSION_GRANTED) {
@@ -112,6 +115,8 @@
      * @return true if access should be granted.
      * @hide
      */
+    @android.ravenwood.annotation.RavenwoodThrow(
+            blockedBy = android.permission.PermissionManager.class)
     public static boolean checkUsageStatsPermission(Context context, String tag, PrintWriter pw) {
         // System internals always get access
         final int uid = Binder.getCallingUid();
@@ -166,6 +171,8 @@
      * @return true if access should be granted.
      * @hide
      */
+    @android.ravenwood.annotation.RavenwoodThrow(
+            blockedBy = android.permission.PermissionManager.class)
     public static boolean checkDumpAndUsageStatsPermission(Context context, String tag,
             PrintWriter pw) {
         return checkDumpPermission(context, tag, pw) && checkUsageStatsPermission(context, tag, pw);
diff --git a/core/java/com/android/internal/util/FastMath.java b/core/java/com/android/internal/util/FastMath.java
index b7dbee5..6e8fef28 100644
--- a/core/java/com/android/internal/util/FastMath.java
+++ b/core/java/com/android/internal/util/FastMath.java
@@ -21,6 +21,7 @@
 /**
  * Fast and loose math routines.
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class FastMath {
 
     /**
diff --git a/core/java/com/android/internal/util/FastPrintWriter.java b/core/java/com/android/internal/util/FastPrintWriter.java
index 63124de..fcd6df0 100644
--- a/core/java/com/android/internal/util/FastPrintWriter.java
+++ b/core/java/com/android/internal/util/FastPrintWriter.java
@@ -32,6 +32,7 @@
 import java.nio.charset.CoderResult;
 import java.nio.charset.CodingErrorAction;
 
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class FastPrintWriter extends PrintWriter {
     private static class DummyWriter extends Writer {
         @Override
diff --git a/core/java/com/android/internal/util/GrowingArrayUtils.java b/core/java/com/android/internal/util/GrowingArrayUtils.java
index 8c12e36..83d06d1 100644
--- a/core/java/com/android/internal/util/GrowingArrayUtils.java
+++ b/core/java/com/android/internal/util/GrowingArrayUtils.java
@@ -29,6 +29,7 @@
  *
  * @hide
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public final class GrowingArrayUtils {
 
     /**
diff --git a/core/java/com/android/internal/util/HeavyHitterSketch.java b/core/java/com/android/internal/util/HeavyHitterSketch.java
index e18acaf..2973d30 100644
--- a/core/java/com/android/internal/util/HeavyHitterSketch.java
+++ b/core/java/com/android/internal/util/HeavyHitterSketch.java
@@ -35,6 +35,7 @@
  * <p>
  * {@hide}
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public interface HeavyHitterSketch<T> {
     /**
      * Return the default implementation.
diff --git a/core/java/com/android/internal/util/LineBreakBufferedWriter.java b/core/java/com/android/internal/util/LineBreakBufferedWriter.java
index 552a93f..8393b22 100644
--- a/core/java/com/android/internal/util/LineBreakBufferedWriter.java
+++ b/core/java/com/android/internal/util/LineBreakBufferedWriter.java
@@ -27,6 +27,7 @@
  *
  * Note: this class is not thread-safe.
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class LineBreakBufferedWriter extends PrintWriter {
 
     /**
diff --git a/core/java/com/android/internal/util/ObjectUtils.java b/core/java/com/android/internal/util/ObjectUtils.java
index 0e7b93d..292ee14 100644
--- a/core/java/com/android/internal/util/ObjectUtils.java
+++ b/core/java/com/android/internal/util/ObjectUtils.java
@@ -22,6 +22,7 @@
 import java.util.Objects;
 
 /** @hide */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class ObjectUtils {
     private ObjectUtils() {}
 
diff --git a/core/java/com/android/internal/util/Parcelling.java b/core/java/com/android/internal/util/Parcelling.java
index 3147c34..70c3869 100644
--- a/core/java/com/android/internal/util/Parcelling.java
+++ b/core/java/com/android/internal/util/Parcelling.java
@@ -38,6 +38,7 @@
  *
  * @param <T> the type being [un]parcelled
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public interface Parcelling<T> {
 
     /**
diff --git a/core/java/com/android/internal/util/ParseUtils.java b/core/java/com/android/internal/util/ParseUtils.java
index a591f4a..a16ce2b 100644
--- a/core/java/com/android/internal/util/ParseUtils.java
+++ b/core/java/com/android/internal/util/ParseUtils.java
@@ -23,6 +23,7 @@
  * Test:
  atest /android/pi-dev/frameworks/base/core/tests/coretests/src/com/android/internal/util/ParseUtilsTest.java
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public final class ParseUtils {
     private ParseUtils() {
     }
diff --git a/core/java/com/android/internal/util/ProcFileReader.java b/core/java/com/android/internal/util/ProcFileReader.java
index b726d5d..6cf241e 100644
--- a/core/java/com/android/internal/util/ProcFileReader.java
+++ b/core/java/com/android/internal/util/ProcFileReader.java
@@ -32,6 +32,7 @@
  * Currently doesn't support formats based on {@code \0}, tabs.
  * Consecutive spaces are treated as a single delimiter.
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class ProcFileReader implements Closeable {
     private final InputStream mStream;
     private final byte[] mBuffer;
diff --git a/core/java/com/android/internal/util/ProgressReporter.java b/core/java/com/android/internal/util/ProgressReporter.java
index 7a8efba..5640d8f 100644
--- a/core/java/com/android/internal/util/ProgressReporter.java
+++ b/core/java/com/android/internal/util/ProgressReporter.java
@@ -25,6 +25,7 @@
 import android.util.MathUtils;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 
 /**
  * Tracks and reports progress of a single task to a {@link IProgressListener}.
@@ -175,7 +176,8 @@
         }
     }
 
-    int getProgress() {
+    @VisibleForTesting
+    public int getProgress() {
         return mProgress;
     }
 
diff --git a/core/java/com/android/internal/util/QuickSelect.java b/core/java/com/android/internal/util/QuickSelect.java
index 17739c9..052efed 100644
--- a/core/java/com/android/internal/util/QuickSelect.java
+++ b/core/java/com/android/internal/util/QuickSelect.java
@@ -28,6 +28,7 @@
  *
  * @hide
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public final class QuickSelect {
     private static <T> int selectImpl(@NonNull List<T> list, int left, int right, int k,
             @NonNull Comparator<? super T> comparator) {
diff --git a/core/java/com/android/internal/util/RingBuffer.java b/core/java/com/android/internal/util/RingBuffer.java
index 8fc4c30..0488659 100644
--- a/core/java/com/android/internal/util/RingBuffer.java
+++ b/core/java/com/android/internal/util/RingBuffer.java
@@ -27,6 +27,7 @@
  * full, oldest events are dropped when new events are added.
  * {@hide}
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class RingBuffer<T> {
 
     // Array for storing events.
diff --git a/core/java/com/android/internal/util/StringPool.java b/core/java/com/android/internal/util/StringPool.java
index c5180a3..94f6ec9 100644
--- a/core/java/com/android/internal/util/StringPool.java
+++ b/core/java/com/android/internal/util/StringPool.java
@@ -23,6 +23,7 @@
  *
  * @hide
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public final class StringPool {
 
     private final String[] mPool = new String[512];
diff --git a/core/java/com/android/internal/util/dump/DumpableContainerImpl.java b/core/java/com/android/internal/util/dump/DumpableContainerImpl.java
index ccec6c6..bb5224f 100644
--- a/core/java/com/android/internal/util/dump/DumpableContainerImpl.java
+++ b/core/java/com/android/internal/util/dump/DumpableContainerImpl.java
@@ -32,6 +32,7 @@
  *
  * @hide
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public final class DumpableContainerImpl implements DumpableContainer {
 
     private static final String TAG = DumpableContainerImpl.class.getSimpleName();
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 28fd2b4..bf8e613 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -897,13 +897,26 @@
     }
 
     /**
-     * Returns true if {@code userHandle} is a managed profile with separate challenge.
+     * Returns true if {@code userHandle} is a profile with separate challenge.
+     * <p>
+     * Returns false if {@code userHandle} is a profile with unified challenge, a profile whose
+     * credential is not shareable with its parent, or a non-profile user.
      */
     public boolean isSeparateProfileChallengeEnabled(int userHandle) {
         return isCredentialSharableWithParent(userHandle) && hasSeparateChallenge(userHandle);
     }
 
     /**
+     * Returns true if {@code userHandle} is a profile with unified challenge.
+     * <p>
+     * Returns false if {@code userHandle} is a profile with separate challenge, a profile whose
+     * credential is not shareable with its parent, or a non-profile user.
+     */
+    public boolean isProfileWithUnifiedChallenge(int userHandle) {
+        return isCredentialSharableWithParent(userHandle) && !hasSeparateChallenge(userHandle);
+    }
+
+    /**
      * Returns true if {@code userHandle} is a managed profile with unified challenge.
      */
     public boolean isManagedProfileWithUnifiedChallenge(int userHandle) {
diff --git a/core/java/com/android/internal/widget/LockscreenCredential.java b/core/java/com/android/internal/widget/LockscreenCredential.java
index c88763c..18d5f6d 100644
--- a/core/java/com/android/internal/widget/LockscreenCredential.java
+++ b/core/java/com/android/internal/widget/LockscreenCredential.java
@@ -134,12 +134,12 @@
     }
 
     /**
-     * Creates a LockscreenCredential object representing a managed password for profile with
-     * unified challenge. This credentiall will have type {@code CREDENTIAL_TYPE_PASSWORD} for now.
-     * TODO: consider add a new credential type for this. This can then supersede the
-     * isLockTiedToParent argument in various places in LSS.
+     * Creates a LockscreenCredential object representing the system-generated, system-managed
+     * password for a profile with unified challenge. This credential has type {@code
+     * CREDENTIAL_TYPE_PASSWORD} for now. TODO: consider add a new credential type for this. This
+     * can then supersede the isLockTiedToParent argument in various places in LSS.
      */
-    public static LockscreenCredential createManagedPassword(@NonNull byte[] password) {
+    public static LockscreenCredential createUnifiedProfilePassword(@NonNull byte[] password) {
         return new LockscreenCredential(CREDENTIAL_TYPE_PASSWORD,
                 Arrays.copyOf(password, password.length), /* hasInvalidChars= */ false);
     }
diff --git a/core/java/com/android/server/pm/pkg/AndroidPackage.java b/core/java/com/android/server/pm/pkg/AndroidPackage.java
index 4e4f26c..adb0c69 100644
--- a/core/java/com/android/server/pm/pkg/AndroidPackage.java
+++ b/core/java/com/android/server/pm/pkg/AndroidPackage.java
@@ -58,6 +58,7 @@
 import com.android.internal.pm.pkg.component.ParsedProvider;
 import com.android.internal.pm.pkg.component.ParsedService;
 import com.android.internal.pm.pkg.component.ParsedUsesPermission;
+import com.android.internal.pm.pkg.parsing.ParsingPackageUtils;
 
 import java.security.PublicKey;
 import java.util.List;
@@ -690,7 +691,7 @@
 
     /**
      * The names of packages to adopt ownership of permissions from, parsed under {@link
-     * com.android.server.pm.pkg.parsing.ParsingPackageUtils#TAG_ADOPT_PERMISSIONS}.
+     * ParsingPackageUtils#TAG_ADOPT_PERMISSIONS}.
      *
      * @see R.styleable#AndroidManifestOriginalPackage_name
      * @hide
@@ -795,7 +796,7 @@
 
     /**
      * For use with {@link com.android.server.pm.KeySetManagerService}. Parsed in {@link
-     * com.android.server.pm.pkg.parsing.ParsingPackageUtils#TAG_KEY_SETS}.
+     * ParsingPackageUtils#TAG_KEY_SETS}.
      *
      * @see R.styleable#AndroidManifestKeySet
      * @see R.styleable#AndroidManifestPublicKey
@@ -1266,7 +1267,7 @@
 
     /**
      * For use with {@link com.android.server.pm.KeySetManagerService}. Parsed in {@link
-     * com.android.server.pm.pkg.parsing.ParsingPackageUtils#TAG_KEY_SETS}.
+     * ParsingPackageUtils#TAG_KEY_SETS}.
      *
      * @see R.styleable#AndroidManifestUpgradeKeySet
      * @hide
@@ -1340,6 +1341,15 @@
     @Nullable
     long[] getUsesSdkLibrariesVersionsMajor();
 
+
+    /**
+     * @see R.styleable#AndroidManifestUsesSdkLibrary_optional
+     * @hide
+     */
+    @Immutable.Ignore
+    @Nullable
+    boolean[] getUsesSdkLibrariesOptional();
+
     /**
      * TODO(b/135203078): Move static library stuff to an inner data class
      *
diff --git a/core/java/com/google/android/collect/Lists.java b/core/java/com/google/android/collect/Lists.java
index 585847d..392b87e 100644
--- a/core/java/com/google/android/collect/Lists.java
+++ b/core/java/com/google/android/collect/Lists.java
@@ -25,6 +25,7 @@
  * Provides static methods for creating {@code List} instances easily, and other
  * utility methods for working with lists. 
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class Lists {
 
     /**
diff --git a/core/java/com/google/android/collect/Maps.java b/core/java/com/google/android/collect/Maps.java
index cd4c128..6492b03 100644
--- a/core/java/com/google/android/collect/Maps.java
+++ b/core/java/com/google/android/collect/Maps.java
@@ -24,6 +24,7 @@
 /**
  * Provides static methods for creating mutable {@code Maps} instances easily.
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class Maps {
     /**
      * Creates a {@code HashMap} instance.
diff --git a/core/java/com/google/android/collect/Sets.java b/core/java/com/google/android/collect/Sets.java
index e242915..76eaf21 100644
--- a/core/java/com/google/android/collect/Sets.java
+++ b/core/java/com/google/android/collect/Sets.java
@@ -31,6 +31,7 @@
  * other static methods for working with Sets.
  *
  */
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
 public class Sets {
     
     /**
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index f365dbb..2a744e3 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -49,8 +49,6 @@
         "-Wno-unused-parameter",
         "-Wunused",
         "-Wunreachable-code",
-
-        "-DNAMESPACE_FOR_HASH_FUNCTIONS=farmhash",
     ],
 
     cppflags: ["-Wno-conversion-null"],
@@ -284,8 +282,6 @@
                 "libscrypt_static",
                 "libstatssocket_lazy",
                 "libskia",
-                "libtextclassifier_hash_static",
-                "libexpresslog_jni",
             ],
 
             shared_libs: [
@@ -372,7 +368,6 @@
                 "bionic_libc_platform_headers",
                 "dnsproxyd_protocol_headers",
                 "flatbuffer_headers",
-                "libtextclassifier_hash_headers",
                 "tensorflow_headers",
             ],
             runtime_libs: [
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 50253cf..c24d21d 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -201,7 +201,6 @@
 extern int register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env);
 extern int register_com_android_internal_content_om_OverlayConfig(JNIEnv *env);
 extern int register_com_android_internal_content_om_OverlayManagerImpl(JNIEnv* env);
-extern int register_com_android_modules_expresslog_Utils(JNIEnv* env);
 extern int register_com_android_internal_net_NetworkUtilsInternal(JNIEnv* env);
 extern int register_com_android_internal_os_ClassLoaderFactory(JNIEnv* env);
 extern int register_com_android_internal_os_FuseAppLoop(JNIEnv* env);
@@ -1590,7 +1589,6 @@
         REG_JNI(register_android_os_incremental_IncrementalManager),
         REG_JNI(register_com_android_internal_content_om_OverlayConfig),
         REG_JNI(register_com_android_internal_content_om_OverlayManagerImpl),
-        REG_JNI(register_com_android_modules_expresslog_Utils),
         REG_JNI(register_com_android_internal_net_NetworkUtilsInternal),
         REG_JNI(register_com_android_internal_os_ClassLoaderFactory),
         REG_JNI(register_com_android_internal_os_LongArrayMultiStateCounter),
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index e0bcef6..de1ce4e 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -1014,6 +1014,10 @@
     return cfg_state == CONFIG_SET;
 }
 
+static jboolean android_os_Debug_logAllocatorStats(JNIEnv*, jobject) {
+    return mallopt(M_LOG_STATS, 0) == 1 ? JNI_TRUE : JNI_FALSE;
+}
+
 /*
  * JNI registration.
  */
@@ -1056,6 +1060,7 @@
         {"getDmabufHeapPoolsSizeKb", "()J", (void*)android_os_Debug_getDmabufHeapPoolsSizeKb},
         {"getGpuTotalUsageKb", "()J", (void*)android_os_Debug_getGpuTotalUsageKb},
         {"isVmapStack", "()Z", (void*)android_os_Debug_isVmapStack},
+        {"logAllocatorStats", "()Z", (void*)android_os_Debug_logAllocatorStats},
 };
 
 int register_android_os_Debug(JNIEnv *env)
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 91dfc60..7af69f2 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -282,6 +282,11 @@
 void android_os_Process_setProcessFrozen(
         JNIEnv *env, jobject clazz, jint pid, jint uid, jboolean freeze)
 {
+    if (uid < 0) {
+        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", "uid is negative: %d", uid);
+        return;
+    }
+
     bool success = true;
 
     if (freeze) {
@@ -305,6 +310,11 @@
 }
 
 jint android_os_Process_createProcessGroup(JNIEnv* env, jobject clazz, jint uid, jint pid) {
+    if (uid < 0) {
+        return jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
+                                    "uid is negative: %d", uid);
+    }
+
     return createProcessGroup(uid, pid);
 }
 
@@ -590,12 +600,21 @@
 
 jint android_os_Process_setUid(JNIEnv* env, jobject clazz, jint uid)
 {
+    if (uid < 0) {
+        return jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
+                                    "uid is negative: %d", uid);
+    }
+
     return setuid(uid) == 0 ? 0 : errno;
 }
 
-jint android_os_Process_setGid(JNIEnv* env, jobject clazz, jint uid)
-{
-    return setgid(uid) == 0 ? 0 : errno;
+jint android_os_Process_setGid(JNIEnv* env, jobject clazz, jint gid) {
+    if (gid < 0) {
+        return jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
+                                    "gid is negative: %d", gid);
+    }
+
+    return setgid(gid) == 0 ? 0 : errno;
 }
 
 static int pid_compare(const void* v1, const void* v2)
@@ -1235,11 +1254,21 @@
 
 jint android_os_Process_killProcessGroup(JNIEnv* env, jobject clazz, jint uid, jint pid)
 {
+    if (uid < 0) {
+        return jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
+                                    "uid is negative: %d", uid);
+    }
+
     return killProcessGroup(uid, pid, SIGKILL);
 }
 
-jint android_os_Process_sendSignalToProcessGroup(JNIEnv* env, jobject clazz, jint uid, jint pid,
+jboolean android_os_Process_sendSignalToProcessGroup(JNIEnv* env, jobject clazz, jint uid, jint pid,
                                                  jint signal) {
+    if (uid < 0) {
+        return jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
+                                    "uid is negative: %d", uid);
+    }
+
     return sendSignalToProcessGroup(uid, pid, signal);
 }
 
@@ -1258,6 +1287,11 @@
 }
 
 void android_os_Process_freezeCgroupUID(JNIEnv* env, jobject clazz, jint uid, jboolean freeze) {
+    if (uid < 0) {
+        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", "uid is negative: %d", uid);
+        return;
+    }
+
     bool success = true;
 
     if (freeze) {
@@ -1310,7 +1344,7 @@
         //{"setApplicationObject", "(Landroid/os/IBinder;)V",
         //(void*)android_os_Process_setApplicationObject},
         {"killProcessGroup", "(II)I", (void*)android_os_Process_killProcessGroup},
-        {"sendSignalToProcessGroup", "(III)I", (void*)android_os_Process_sendSignalToProcessGroup},
+        {"sendSignalToProcessGroup", "(III)Z", (void*)android_os_Process_sendSignalToProcessGroup},
         {"removeAllProcessGroups", "()V", (void*)android_os_Process_removeAllProcessGroups},
         {"nativePidFdOpen", "(II)I", (void*)android_os_Process_nativePidFdOpen},
         {"freezeCgroupUid", "(IZ)V", (void*)android_os_Process_freezeCgroupUID},
diff --git a/core/jni/com_android_internal_os_LongArrayMultiStateCounter.cpp b/core/jni/com_android_internal_os_LongArrayMultiStateCounter.cpp
index dab47e9..76b05ea 100644
--- a/core/jni/com_android_internal_os_LongArrayMultiStateCounter.cpp
+++ b/core/jni/com_android_internal_os_LongArrayMultiStateCounter.cpp
@@ -107,7 +107,7 @@
     *vector = counter->getCount(state);
 }
 
-static jobject native_toString(JNIEnv *env, jobject self, jlong nativePtr) {
+static jobject native_toString(JNIEnv *env, jclass, jlong nativePtr) {
     battery::LongArrayMultiStateCounter *counter =
             reinterpret_cast<battery::LongArrayMultiStateCounter *>(nativePtr);
     return env->NewStringUTF(counter->toString().c_str());
@@ -127,7 +127,7 @@
         }                                     \
     }
 
-static void native_writeToParcel(JNIEnv *env, jobject self, jlong nativePtr, jobject jParcel,
+static void native_writeToParcel(JNIEnv *env, jclass, jlong nativePtr, jobject jParcel,
                                  jint flags) {
     battery::LongArrayMultiStateCounter *counter =
             reinterpret_cast<battery::LongArrayMultiStateCounter *>(nativePtr);
@@ -161,7 +161,7 @@
         }                                    \
     }
 
-static jlong native_initFromParcel(JNIEnv *env, jclass theClass, jobject jParcel) {
+static jlong native_initFromParcel(JNIEnv *env, jclass, jobject jParcel) {
     ndk::ScopedAParcel parcel(AParcel_fromJavaParcel(env, jParcel));
 
     int32_t stateCount;
@@ -253,7 +253,7 @@
     return reinterpret_cast<jlong>(native_dispose_LongArrayContainer);
 }
 
-static void native_setValues_LongArrayContainer(JNIEnv *env, jobject self, jlong nativePtr,
+static void native_setValues_LongArrayContainer(JNIEnv *env, jclass, jlong nativePtr,
                                                 jlongArray jarray) {
     std::vector<uint64_t> *vector = reinterpret_cast<std::vector<uint64_t> *>(nativePtr);
     ScopedLongArrayRO scopedArray(env, jarray);
@@ -264,7 +264,7 @@
     std::copy(array, array + size, vector->data());
 }
 
-static void native_getValues_LongArrayContainer(JNIEnv *env, jobject self, jlong nativePtr,
+static void native_getValues_LongArrayContainer(JNIEnv *env, jclass, jlong nativePtr,
                                                 jlongArray jarray) {
     std::vector<uint64_t> *vector = reinterpret_cast<std::vector<uint64_t> *>(nativePtr);
     ScopedLongArrayRW scopedArray(env, jarray);
@@ -273,7 +273,7 @@
     std::copy(vector->data(), vector->data() + vector->size(), scopedArray.get());
 }
 
-static jboolean native_combineValues_LongArrayContainer(JNIEnv *env, jobject self, jlong nativePtr,
+static jboolean native_combineValues_LongArrayContainer(JNIEnv *env, jclass, jlong nativePtr,
                                                         jlongArray jarray, jintArray jindexMap) {
     std::vector<uint64_t> *vector = reinterpret_cast<std::vector<uint64_t> *>(nativePtr);
     ScopedLongArrayRW scopedArray(env, jarray);
diff --git a/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp b/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
index 87ab496..54c4cd5 100644
--- a/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
+++ b/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp
@@ -63,6 +63,7 @@
   std::optional<std::pair<char*, char*>> readLine(FailFn fail_fn) {
     char* result = mBuffer + mNext;
     while (true) {
+      // We have scanned up to, but not including mNext for this line's newline.
       if (mNext == mEnd) {
         if (mEnd == MAX_COMMAND_BYTES) {
           return {};
@@ -89,7 +90,7 @@
       } else {
         mNext = nl - mBuffer + 1;
         if (--mLinesLeft < 0) {
-          fail_fn("ZygoteCommandBuffer.readLine attempted to read past mEnd of command");
+          fail_fn("ZygoteCommandBuffer.readLine attempted to read past end of command");
         }
         return std::make_pair(result, nl);
       }
@@ -125,8 +126,8 @@
     mEnd += lineLen + 1;
   }
 
-  // Clear mBuffer, start reading new command, return the number of arguments, leaving mBuffer
-  // positioned at the beginning of first argument. Return 0 on EOF.
+  // Start reading new command, return the number of arguments, leaving mBuffer positioned at the
+  // beginning of first argument. Return 0 on EOF.
   template<class FailFn>
   int getCount(FailFn fail_fn) {
     mLinesLeft = 1;
@@ -451,11 +452,14 @@
             (CREATE_ERROR("Write unexpectedly returned short: %d < 5", res));
       }
     }
-    // Clear buffer and get count from next command.
-    n_buffer->clear();
     for (;;) {
+      // Clear buffer and get count from next command.
+      n_buffer->clear();
       // Poll isn't strictly necessary for now. But without it, disconnect is hard to detect.
       int poll_res = TEMP_FAILURE_RETRY(poll(fd_structs, 2, -1 /* infinite timeout */));
+      if (poll_res < 0) {
+        fail_fn_z(CREATE_ERROR("Poll failed: %d: %s", errno, strerror(errno)));
+      }
       if ((fd_structs[SESSION_IDX].revents & POLLIN) != 0) {
         if (n_buffer->getCount(fail_fn_z) != 0) {
           break;
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index 3887dd7..9ca1849 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -99,6 +99,7 @@
         optional SettingProto accessibility_font_scaling_has_been_changed = 51 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto accessibility_force_invert_color_enabled = 52 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto accessibility_magnification_two_finger_triple_tap_enabled = 53 [ (android.privacy).dest = DEST_AUTOMATIC ];
+        optional SettingProto qs_targets = 54 [ (android.privacy).dest = DEST_AUTOMATIC ];
 
     }
     optional Accessibility accessibility = 2;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index c55b808..454eaee 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4806,6 +4806,13 @@
     <permission android:name="android.permission.CHANGE_ACCESSIBILITY_VOLUME"
                 android:protectionLevel="signature" />
 
+    <!-- @FlaggedApi("com.android.server.accessibility.motion_event_observing")
+    @hide
+    @TestApi
+    Allows an accessibility service to observe motion events without consuming them. -->
+    <permission android:name="android.permission.ACCESSIBILITY_MOTION_EVENT_OBSERVING"
+                android:protectionLevel="signature" />
+
     <!-- @hide Allows an application to collect frame statistics -->
     <permission android:name="android.permission.FRAME_STATS"
          android:protectionLevel="signature" />
@@ -5695,11 +5702,10 @@
                 android:protectionLevel="normal" />
 
     <!-- @hide @FlaggedApi("android.companion.flags.companion_transport_apis")
-         @SystemApi(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES)
          Allows an application to send and receive messages via CDM transports.
     -->
     <permission android:name="android.permission.USE_COMPANION_TRANSPORTS"
-        android:protectionLevel="signature|module" />
+        android:protectionLevel="signature" />
 
     <!-- Allows an application to create new companion device associations.
          @SystemApi
@@ -7832,6 +7838,33 @@
     <permission android:name="android.permission.PREPARE_FACTORY_RESET"
         android:protectionLevel="signature|privileged" />
 
+    <!-- @SystemApi Allows focused window to override the default behavior of supported system keys.
+        The following keycodes are supported:
+        <p> KEYCODE_STEM_PRIMARY
+        <p>If an app is granted this permission and has a focused window, it will be allowed to
+           receive supported key events that are otherwise handled by the system. The app can choose
+           to consume the key events and trigger its own behavior, in which case the default key
+           behavior will be skipped.
+        <p>For example, KEYCODE_STEM_PRIMARY by default opens recent app launcher. If the foreground
+           fitness app is granted this permission, it can repurpose the KEYCODE_STEM_PRIMARY button
+           to pause/resume the current fitness session.
+        <p>Protection level: signature|privileged
+        @FlaggedApi("com.android.input.flags.override_key_behavior_permission_apis")
+        @hide -->
+    <permission android:name="android.permission.OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW"
+        android:protectionLevel="signature|privileged" />
+
+    <!-- @hide @SystemApi
+        @FlaggedApi("com.android.server.notification.flags.redact_otp_notifications_from_untrusted_listeners")
+        Allows apps with a NotificationListenerService to receive notifications with sensitive
+        information
+        <p>Apps with a NotificationListenerService without this permission will not be able
+        to view certain types of sensitive information contained in notifications
+        <p>Protection level: signature|role
+    -->
+    <permission android:name="android.permission.RECEIVE_SENSITIVE_NOTIFICATIONS"
+        android:protectionLevel="signature|role" />
+
     <!-- Attribution for Geofencing service. -->
     <attribution android:tag="GeofencingService" android:label="@string/geofencing_service"/>
     <!-- Attribution for Country Detector. -->
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 625b1413..8e89075 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Naweek"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Geleentheid"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Slaap"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Aan"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Af"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> demp sekere klanke"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Kan nie na skerm weerspieël nie"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Gebruik ’n ander kabel en probeer weer"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Jou toestel is te warm en kan nie na die skerm weerspieël totdat dit afgekoel het nie"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kabel steun dalk nie skerms nie"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Jou USB-C-kabel koppel dalk nie behoorlik aan skerms nie"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen is aan"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> gebruik tans albei skerms om inhoud te wys"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Sleutelborduitleg is gestel op <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g> … Tik om dit te verander."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Fisieke sleutelborde is opgestel"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Tik om sleutelborde te bekyk"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Privaat"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Kloon"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Werk"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Werk 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Werk 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Toets"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Gemeenskaplik"</string>
 </resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 1ec3ffd..b38257c 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"የሳምንት እረፍት ቀናት"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"ክስተት"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"መተኛት"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"በርቷል"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"ጠፍቷል"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> አንዳንድ ድምጾችን እየዘጋ ነው"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"ወደ ማሳያ ማንጸባረቅ አልተቻለም"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"የተለየ ገመድ ይጠቀሙ እና እንደገና ይሞክሩ"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"መሳሪያዎ በጣም ሞቃት ነው እና እስኪቀዘቅዝ ድረስ ማሳያውን ማንጸባረቅ አይችልም"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"ገመድ ማሳያዎችን ላይደግፍ ይችላል"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"የእርስዎ USB-C ገመድ ከማሳያዎች ጋር በትክክል ላይገናኝ ይችላል"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual screen ገፅ በርቷል"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> ይዘትን ለማሳየት ሁለቱንም ማሳያዎች እየተጠቀመ ነው"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 04fb300..a77fc65 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1910,6 +1910,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"نهاية الأسبوع"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"حدث"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"النوم"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"مفعَّل"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"غير مفعَّل"</string>
     <string name="muted_by" msgid="91464083490094950">"يعمل <xliff:g id="THIRD_PARTY">%1$s</xliff:g> على كتم بعض الأصوات."</string>
@@ -2345,8 +2347,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"يتعذّر إجراء نسخ مطابق لمحتوى جهازك إلى الشاشة"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"يُرجى استخدام كابل آخر وإعادة المحاولة."</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"جهازك ساخن للغاية ولا يمكنه إجراء نسخ مطابق للمحتوى إلى الشاشة إلى أن تنخفض حرارته."</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"قد لا يتوافق الكابل مع الشاشات"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"‏قد لا يتم توصيل الكابل المزوَّد بمنفذ USB-C بالشاشات بشكل صحيح."</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"‏ميزة Dual Screen مفعّلة"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"يستخدم \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" كلتا الشاشتين لعرض المحتوى."</string>
@@ -2363,18 +2363,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"تم ضبط تنسيق لوحة المفاتيح على <xliff:g id="LAYOUT_1">%1$s</xliff:g> و<xliff:g id="LAYOUT_2">%2$s</xliff:g> و<xliff:g id="LAYOUT_3">%3$s</xliff:g>… انقر لتغييره."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"تم إعداد لوحات المفاتيح الخارجية"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"انقر لعرض لوحات المفاتيح."</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"ملف شخصي خاص"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"نسخة طبق الأصل"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"ملف العمل"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"ملف العمل 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"ملف العمل 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"ملف شخصي تجريبي"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"ملف شخصي مشترك"</string>
 </resources>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 826844f..f85f61c 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"সপ্তাহ অন্ত"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"কার্যক্ৰম"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"নিদ্ৰাৰত"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"অন আছে"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"অফ আছে"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g>এ কিছুমান ধ্বনি মিউট কৰি আছে"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"সংযুক্ত ডিছপ্লে’ উপলব্ধ নহয়"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"অন্য এডাল কে’বল ব্যৱহাৰ কৰি পুনৰ চেষ্টা কৰক"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"আপোনাৰ ডিভাইচটো অত্যধিক গৰম হৈছে আৰু এইটো ঠাণ্ডা নোহোৱালৈকে ডিছপ্লে’ত প্ৰতিবিম্বকৰণ কৰিব নোৱাৰি"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"কে’বলে ডিছপ্লে’ সমৰ্থন নকৰিবও পাৰে"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"আপোনাৰ USB-C কে’বল ডিছপ্লে’ৰ সৈতে সঠিকভাৱে সংযোগ নহ’বও পাৰে"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen অন আছে"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ সমল দেখুৱাবলৈ দুয়োখন ডিছপ্লে’ ব্যৱহাৰ কৰি আছে"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"কীব’ৰ্ডৰ লে’আউট <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g> হিচাপে ছেট কৰা হৈছে… সলনি কৰিবলৈ টিপক।"</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"ভৌতিক কীব’ৰ্ড কনফিগাৰ কৰা হৈছে"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"কীব’ৰ্ড চাবলৈ টিপক"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"ব্যক্তিগত"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"ক্ল’ন"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"কৰ্মস্থান"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"কৰ্মস্থান ২"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"কৰ্মস্থান ৩"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"পৰীক্ষা"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"শ্বেয়াৰ কৰা"</string>
 </resources>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 66a5670..ed1e340 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Həftə sonu"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Tədbir"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Yuxu vaxtı"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Aktiv"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Deaktiv"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> bəzi səsləri səssiz rejimə salır"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Displeydə əks etdirmək olmur"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Başqa kabel istifadə edin və yenidən cəhd edin"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Cihaz çox isinib və soyuyana qədər displeydə əks etdirmək olmur"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kabel displeyləri dəstəkləməyə bilər"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"USB-C kabeli displeylərə düzgün qoşulmaya bilər"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"İkili ekran"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"İkili ekran aktivdir"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> məzmunu göstərmək üçün hər iki displeydən istifadə edir"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Klaviatura düzəni <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g> kimi ayarlanıb… Dəyişmək üçün toxunun."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Fiziki klaviaturalar konfiqurasiya edilib"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Klaviaturalara baxmaq üçün toxunun"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Şəxsi"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Klon"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"İş"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"İş 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"İş 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Kommunal"</string>
 </resources>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index b6121ed..ea15cee 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -1907,6 +1907,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Vikend"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Događaj"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Spavanje"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Uključeno"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Isključeno"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> isključuje neke zvuke"</string>
@@ -2342,8 +2344,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Preslikavanje na ekran nije moguće"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Upotrebite drugi kabl i probajte ponovo"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Uređaj je previše zagrejan, pa ne može da se preslikava na ekran dok se ne ohladi"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kabl ne podržava ekrane"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"USB-C kabl se ne povezuje pravilno sa ekranima"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen je uključen"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> koristi oba ekrana za prikazivanje sadržaja"</string>
@@ -2360,18 +2360,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Raspored tastature je podešen na <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Dodirnite da biste promenili."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Fizičke tastature su konfigurisane"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Dodirnite da biste videli tastature"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Privatno"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Klonirano"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Posao"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Posao 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Posao 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Zajedničko"</string>
 </resources>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 3c01f1b..8da0d1a 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -1908,6 +1908,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Выхадныя"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Падзея"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Рэжым сну"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Уключана"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Выключана"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> выключае некаторыя гукі"</string>
@@ -2343,8 +2345,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Не ўдалося прадубліраваць змесціва на дысплэі"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Паспрабуйце скарыстаць іншы кабель"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Прылада занадта моцна нагрэлася і таму не можа дубліраваць змесціва на дысплэі, пакуль не астыне"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Магчыма, кабель несумяшчальны з дысплэямі"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Магчыма, кабель USB-C не падыходзіць да дысплэяў"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Уключана функцыя Dual Screen"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"Праграма \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" выкарыстоўвае абодва экраны для паказу змесціва"</string>
@@ -2361,18 +2361,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Раскладка клавіятуры наладжана для наступных моў: <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Націсніце, каб змяніць."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Фізічныя клавіятуры наладжаны"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Націсніце, каб праглядзець клавіятуры"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Прыватны"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Клон"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Працоўны"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Працоўны 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Працоўны 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Тэставы"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Супольны"</string>
 </resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 3b1ff9e..e97d9dc 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Събота и неделя"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Събитие"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Време за сън"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Вкл."</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Изкл."</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> заглушава някои звуци"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Не може да се копира огледално на дисплея"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Използвайте друг кабел и опитайте отново"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Устройството ви е твърде топло и няма да може да дублира на екрана, преди да се охлади"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Кабелът не поддържа дисплеи"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"USB-C кабелът ви може да не се свързва правилно с дисплеи"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Функцията Dual Screen е включена"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> използва и двата екрана, за да показва съдържание"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"За клавиатурната подредба са зададени <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g> и <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Докоснете за промяна."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Физическите клавиатури са конфигурирани"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Докоснете за преглед на клавиатурите"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Частни"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Клониране"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Служебни"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Служебни 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Служебни 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Тестване"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Общи"</string>
 </resources>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 58dd7c2..fa2c283 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"সপ্তাহান্ত"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"ইভেন্ট"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"ঘুমানোর সময়"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"চালু আছে"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"বন্ধ আছে"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> কিছু সাউন্ডকে মিউট করে দিচ্ছে"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"ডিসপ্লে মিরর করা যাচ্ছে না"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"অন্য কোনও কেবল ব্যবহার করে আবার চেষ্টা করুন"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"আপনার ডিভাইস খুব গরম হয়ে আছে এবং সেটি ঠাণ্ডা না হওয়া পর্যন্ত ডিসপ্লে মিরর করা যাবে না"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"কেবল, ডিসপ্লের সাথে কাজ নাও করতে পারে"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"আপনার USB-C কেবল, ডিসপ্লেতে সঠিকভাবে কানেক্ট নাও হতে পারে"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen চালু করা আছে"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"কন্টেন্ট দেখানোর জন্য <xliff:g id="APP_NAME">%1$s</xliff:g> দুটি ডিসপ্লে ব্যবহার করছে"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"কীবোর্ড লেআউট <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>-এ সেট করা আছে… পালটাতে ট্যাপ করুন।"</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"ফিজিক্যাল কীবোর্ড কনফিগার করা হয়েছে"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"কীবোর্ড দেখতে ট্যাপ করুন"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"ব্যক্তিগত"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"ক্লোন করুন"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"অফিস"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"২য় অফিস"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"৩য় অফিস"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"পরীক্ষা"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"কমিউনাল"</string>
 </resources>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index aa66e02..cd941ce 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -1724,7 +1724,7 @@
     <string name="color_inversion_feature_name" msgid="2672824491933264951">"Inverzija boja"</string>
     <string name="color_correction_feature_name" msgid="7975133554160979214">"Ispravka boja"</string>
     <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Način rada jednom rukom"</string>
-    <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Dodatno zatamnjeno"</string>
+    <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Dodatno zatamnjenje"</string>
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Slušni aparati"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Držali ste tipke za jačinu zvuka. Usluga <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je uključena."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Držali ste tipke za jačinu zvuka. Usluga <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je isključena."</string>
@@ -1907,6 +1907,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Vikend"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Događaj"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Spavanje"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Uključeno"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Isključeno"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> isključuje neke zvukove"</string>
@@ -2342,8 +2344,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Nije moguće preslikati na ekran"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Upotrijebite drugi kabl i pokušajte ponovo"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Uređaj je pregrijan i ne može preslikavati na ekran dok se ne ohladi"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kabl možda neće podržavati ekrane"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"USB-C kabl se možda neće pravilno povezati s ekranima"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen je uključen"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> koristi oba ekrana za prikazivanje sadržaja"</string>
@@ -2360,18 +2360,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Raspored tastature je postavljen na <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Dodirnite da promijenite."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Fizičke tastature su konfigurirane"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Dodirnite da pregledate tastature"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Privatno"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Klon"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Poslovno"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"2. poslovno"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"3. poslovno"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Testno"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Opće"</string>
 </resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index be8654d..fbdcf56 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1907,6 +1907,8 @@
     <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>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Activat"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Desactivat"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> està silenciant alguns sons"</string>
@@ -2342,8 +2344,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"No es pot projectar a la pantalla"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Utilitza un altre cable i torna-ho a provar"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"El dispositiu està massa calent i no pot projectar a la pantalla fins que es refredi"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"És possible que el cable no sigui compatible amb pantalles"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"És possible que el teu cable USB-C no es connecti correctament a les pantalles"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Pantalla dual"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"La pantalla dual està activada"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> està utilitzant les dues pantalles per mostrar contingut"</string>
@@ -2360,18 +2360,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Disseny del teclat definit en <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Toca per canviar-ho."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Teclats físic configurats"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Toca per veure els teclats"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Privat"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Clon"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Treball"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Treball 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Treball 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Prova"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Compartit"</string>
 </resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index ed2f93a..156f18d 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -485,7 +485,7 @@
     <string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"přístup k poloze na pozadí"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="8264885066095638105">"Tato aplikace má kdykoliv přístup k poloze (i když ji zrovna nepoužíváte)."</string>
     <string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"změna nastavení zvuku"</string>
-    <string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Umožňuje aplikaci změnit globální nastavení zvuku, například hlasitost či reproduktor pro výstup zvuku."</string>
+    <string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Umožňuje aplikaci změnit globální nastavení zvuku, například hlasitost či reproduktor pro zvukový výstup."</string>
     <string name="permlab_recordAudio" msgid="1208457423054219147">"nahrávání zvuku"</string>
     <string name="permdesc_recordAudio" msgid="5857246765327514062">"Tato aplikace může pomocí mikrofonu během svého používání zaznamenat zvuk."</string>
     <string name="permlab_recordBackgroundAudio" msgid="5891032812308878254">"zaznamenávat zvuk na pozadí"</string>
@@ -1908,6 +1908,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Víkend"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Událost"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Spánek"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Zapnuto"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Vypnuto"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> vypíná určité zvuky"</string>
@@ -2343,8 +2345,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Nelze zrcadlit na displej"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Použijte jiný kabel a zkuste to znovu"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Zařízení je moc zahřáté, a dokud se nezchladí, nemůže zrcadlit displej"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kabel možná nepodporuje displeje"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Váš kabel USB-C se možná nedokáže správně připojit k displejům"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Je zapnutá funkce Dual Screen"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> používá k zobrazení obsahu oba displeje"</string>
diff --git a/core/res/res/values-da-watch/strings.xml b/core/res/res/values-da-watch/strings.xml
index 099939a..09b17c0 100644
--- a/core/res/res/values-da-watch/strings.xml
+++ b/core/res/res/values-da-watch/strings.xml
@@ -21,7 +21,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="permgrouplab_sensors" msgid="2439544173324807471">"Sensorer"</string>
-    <string name="global_action_emergency" msgid="2097576936362874627">"Alarm-SOS"</string>
+    <string name="global_action_emergency" msgid="2097576936362874627">"Nødkald"</string>
     <string name="reboot_to_update_prepare" msgid="4129802024411268230">"Forbereder opdatering"</string>
     <string name="reboot_to_update_title" msgid="8043761242418682803">"Wear OS-systemopdatering"</string>
     <string name="select_input_method" msgid="1285150113084396451">"Vælg indtastningsmetode"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 35def43..9f89293 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Weekend"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Begivenhed"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Sover"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Til"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Fra"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> slår nogle lyde fra"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Det er ikke muligt at spejle til skærmen"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Brug et andet kabel, og prøv igen"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Din enhed er for varm og kan ikke spejle til skærmen, før den er kølet af"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kablet understøtter muligvis ikke skærme"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Dit USB-C-kabel kan muligvis ikke sluttes korrekt til skærmene"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen er aktiveret"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> bruger begge skærme til at vise indhold"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Tastaturlayoutet er angivet som <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Tryk for at ændre dette."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Fysiske tastaturer er konfigureret"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Tryk for at se tastaturer"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Privat"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Klon"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Arbejde"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Arbejde 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Arbejde 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Fælles"</string>
 </resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 50501c6..182b974 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1257,7 +1257,7 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android wird gestartet…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"Tablet wird gestartet…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"Gerät wird gestartet…"</string>
-    <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Systemupdate wird beendet…"</string>
+    <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"Systemupdate wird abgeschlossen…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"Für <xliff:g id="APPLICATION">%1$s</xliff:g> wird gerade ein Upgrade ausgeführt…"</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> wird vorbereitet"</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Apps werden gestartet..."</string>
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Wochenende"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Termin"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Schlafen"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"An"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Aus"</string>
     <string name="muted_by" msgid="91464083490094950">"Einige Töne werden von <xliff:g id="THIRD_PARTY">%1$s</xliff:g> stummgeschaltet"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Kann nicht auf das Display gespiegelt werden"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Verwende ein anderes Kabel und versuch es noch einmal"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Dein Gerät ist zu heiß und kann den Bildschirm erst spiegeln, wenn es abgekühlt ist"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kabel unterstützt eventuell keine Bildschirme"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Dein USB-C-Kabel ist möglicherweise nicht zum Verbinden von Bildschirmen geeignet"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen ist aktiviert"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> nutzt zum Anzeigen von Inhalten beide Displays"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index dc73c21..d33a2f3 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Σαββατοκύριακο"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Συμβάν"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Ύπνος"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Ενεργός"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Ανενεργός"</string>
     <string name="muted_by" msgid="91464083490094950">"Το τρίτο μέρος <xliff:g id="THIRD_PARTY">%1$s</xliff:g> θέτει ορισμένους ήχους σε σίγαση"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Δεν είναι δυνατός ο κατοπτρισμός στην οθόνη"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Χρησιμοποιήστε άλλο καλώδιο και δοκιμάστε ξανά"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Η θερμοκρασία της συσκευής σας είναι πολύ υψηλή και δεν είναι δυνατός ο κατοπτρισμός στην οθόνη μέχρι να μειωθεί"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Το καλώδιο μπορεί να μην υποστηρίζει οθόνες"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Το καλώδιο USB-C που έχετε ίσως να μην μπορεί να συνδεθεί σωστά σε οθόνες"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Διπλή οθόνη"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Η λειτουργία διπλής οθόνης είναι ενεργή"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"Η εφαρμ. <xliff:g id="APP_NAME">%1$s</xliff:g> χρησιμοποιεί και τις 2 οθόνες για εμφάνιση περιεχ."</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 179bdb4..a8d807e 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Weekend"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Event"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Sleeping"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"On"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Off"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> is muting some sounds"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Can\'t mirror to display"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Please use a different cable and try again"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Your device is too warm and can\'t mirror to the display until it cools down"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Cable may not support displays"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Your USB-C cable may not connect to displays properly"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen is on"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> is using both displays to show content"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Keyboard layout set to <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Tap to change."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Physical keyboards configured"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Tap to view keyboards"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Private"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Clone"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Work"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Work 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Work 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Communal"</string>
 </resources>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 5fb0e5a..2885e4d 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Weekend"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Event"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Sleeping"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"On"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Off"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> is muting some sounds"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Can\'t mirror to display"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Use a different cable and try again"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Your device is too warm and can\'t mirror to the display until it cools down"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Cable may not support displays"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Your USB-C cable may not connect to displays properly"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual screen is on"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> is using both displays to show content"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 2a4f88e..ed4e953 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Weekend"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Event"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Sleeping"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"On"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Off"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> is muting some sounds"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Can\'t mirror to display"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Please use a different cable and try again"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Your device is too warm and can\'t mirror to the display until it cools down"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Cable may not support displays"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Your USB-C cable may not connect to displays properly"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen is on"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> is using both displays to show content"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Keyboard layout set to <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Tap to change."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Physical keyboards configured"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Tap to view keyboards"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Private"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Clone"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Work"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Work 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Work 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Communal"</string>
 </resources>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 0f08d2f..c7e4252 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Weekend"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Event"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Sleeping"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"On"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Off"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> is muting some sounds"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Can\'t mirror to display"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Please use a different cable and try again"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Your device is too warm and can\'t mirror to the display until it cools down"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Cable may not support displays"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Your USB-C cable may not connect to displays properly"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen is on"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> is using both displays to show content"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Keyboard layout set to <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Tap to change."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Physical keyboards configured"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Tap to view keyboards"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Private"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Clone"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Work"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Work 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Work 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Communal"</string>
 </resources>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 0bdd2974..8efab74 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‏‎‏‎‎‏‏‎‏‎‏‎‏‎‏‏‎‏‏‎‏‎‏‎‏‎‎‏‏‎‏‎‏‏‏‎‏‏‎‏‏‎‏‏‏‏‏‏‎‎‎‏‎‏‎‎Weekend‎‏‎‎‏‎"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‎‏‎‎‏‏‏‎‏‎‎‎‏‎‎‎‏‏‎‎‏‎‎‏‏‏‎‏‏‏‏‏‏‎‎‎‏‎‎‎‏‎‎‎‎‎‎‎‏‎Event‎‏‎‎‏‎"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‎‏‎‏‏‏‏‎‏‎‎‎‏‏‎‎‏‏‎‎‎‏‏‎‎‏‎‏‏‏‎‏‏‏‎‎‏‎‎‏‏‎‏‏‏‏‎‎‏‏‏‎‏‏‏‏‎Sleeping‎‏‎‎‏‎"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‏‎‎‎‏‏‏‎‏‏‎‏‏‏‎‎‏‏‎‏‏‏‏‎‏‎‎‏‏‏‏‏‏‎‎‏‎‏‏‏‎‏‏‏‎‏‏‎‏‏‏‎‎‎‏‎‎On‎‏‎‎‏‎"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‎‎‏‏‏‎‎‎‏‎‏‏‏‏‎‎‎‎‎‏‎‏‎‎‎‏‏‏‎‏‏‏‎‎‏‏‎‎‏‏‏‎‏‎‏‎‏‏‎‏‏‎‎Off‎‏‎‎‏‎"</string>
     <string name="muted_by" msgid="91464083490094950">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‎‏‎‎‎‏‎‎‏‏‏‏‎‎‏‎‎‎‎‏‏‎‎‏‎‏‏‎‏‏‏‎‎‎‏‎‎‎‏‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="THIRD_PARTY">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is muting some sounds‎‏‎‎‏‎"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‎‎‏‎‎‏‎‎‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‏‎‎‏‏‎‎‏‏‎‎‏‎‏‎‏‏‎‏‎‏‏‎‎‏‏‎‏‎‏‎‎‎Can\'t mirror to display‎‏‎‎‏‎"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‎‏‎‏‏‏‏‏‎‏‏‎‎‏‎‎‏‎‏‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‎‏‏‏‎‎‏‎‏‎‏‎‏‏‎‏‏‎‎‎Use a different cable and try again‎‏‎‎‏‎"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‏‏‎‏‏‎‎‎‏‎‎‏‏‏‎‏‏‏‎‎‏‎‏‏‏‎‎‎‎‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‎‏‎Your device is too warm and can\'t mirror to the display until it cools down‎‏‎‎‏‎"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‏‎‏‎‎‎‎‎‎‎‏‏‎‏‏‏‏‎‎‏‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‏‏‏‎‏‎‎‏‏‎‏‎‎‎‏‎Cable may not support displays‎‏‎‎‏‎"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‏‎‏‏‎‎‏‎‏‏‎‏‏‏‎‏‎‎‎‏‏‏‎‎‏‎‏‎‏‏‏‎‎‎‎‎‎‎‎‏‎‏‎‎‎‏‎‏‎Your USB-C cable may not connect to displays properly‎‏‎‎‏‎"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‎‎‏‏‎‎‎‎‏‎‏‎‏‏‎‏‏‎‏‏‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‏‏‏‎‏‏‏‎‎‎‏‏‎‏‏‎‏‏‎Dual screen‎‏‎‎‏‎"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‎‎‎‏‏‏‎‏‎‏‏‎‎‎‏‎‏‎‎‏‎‏‏‎‎‎‏‎‏‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‎‏‎Dual screen is on‎‏‎‎‏‎"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‏‏‏‎‏‏‎‎‏‏‎‎‎‏‏‎‎‏‏‎‎‏‏‎‏‎‎‏‏‎‏‎‎‎‎‏‎‏‏‏‎‏‎‏‎‎‎‎‏‏‎‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is using both displays to show content‎‏‎‎‏‎"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index bef851d..9cea763 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1907,6 +1907,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Fin de semana"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Evento"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Dormir"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Activado"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Desactivado"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> silencia algunos sonidos"</string>
@@ -2342,8 +2344,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"No se puede duplicar la pantalla"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Usa un cable diferente y vuelve a intentarlo"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"La temperatura del dispositivo es demasiado alta y no se puede duplicar la pantalla hasta que se enfríe"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Es posible que el cable no admita pantallas"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Es posible que el cable USB-C no se conecte a las pantallas de manera adecuada"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"La función Dual Screen está activada"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> está usando ambas pantallas para mostrar contenido"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 29f0f8f..3acb71f 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1907,6 +1907,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Fin de semana"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Evento"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Durmiendo"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Activado"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Desactivado"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> silencia algunos sonidos"</string>
@@ -2342,8 +2344,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"No se puede proyectar a la pantalla"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Usa otro cable y vuelve a intentarlo"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Tu dispositivo está demasiado caliente y no puede proyectar a la pantalla hasta que se enfríe"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"El cable puede no ser compatible con pantallas"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Puede que tu cable USB‑C no sea adecuado para conectarse a pantallas"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"La función Dual Screen está activada"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> está usando ambas pantallas para mostrar contenido"</string>
@@ -2360,18 +2360,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Diseño del teclado definido como <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Toca para cambiarlo."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Teclados físicos configurados"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Toca para ver los teclados"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Privado"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Clon"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Trabajo"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Trabajo 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Trabajo 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Prueba"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Común"</string>
 </resources>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 4a42b00..5a18823 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Nädalavahetus"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Sündmus"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Magamine"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Sees"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Väljas"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> vaigistab teatud helid"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Ei saa ekraanile peegeldada"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Kasutage teist kaablit ja proovige uuesti"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Teie seade on liiga kuum ja ei saa ekraanile peegeldada enne, kui see jahtub"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kaabel ei pruugi ekraane toetada"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Teie USB-C-kaabel ei pruugi ekraanidega õigesti ühendust luua"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screeni režiim on sisse lülitatud"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> kasutab sisu kuvamiseks mõlemat ekraani"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Klaviatuuripaigutuseks on määratud <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g> … puudutage muutmiseks."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Füüsilised klaviatuurid on seadistatud"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Puudutage klaviatuuride vaatamiseks"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Privaatne"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Kloon"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Töö"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Töö 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Töö 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Jagatud"</string>
 </resources>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 3b76e88..625bb00 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Asteburua"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Gertaera"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Lo egiteko"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Aktibatuta"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Desaktibatuta"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> soinu batzuk isilarazten ari da"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Ezin da islatu pantailan"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Erabili beste kable bat eta saiatu berriro"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Gailua beroegi dago eta ezingo da pantailan islatu hoztu arte"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Baliteke kablea pantailekin bateragarria ez izatea"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Baliteke USB-C kablea behar bezala ez konektatzea pantailetara"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen aktibatuta dago"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> bi pantailak erabiltzen ari da edukia erakusteko"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Ezarri da <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g> eta <xliff:g id="LAYOUT_3">%3$s</xliff:g> gisa teklatuaren diseinua… Diseinu hori aldatzeko, sakatu hau."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Konfiguratu dira teklatu fisikoak"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Sakatu hau teklatuak ikusteko"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Pribatua"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Klona"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Lanekoa"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Lanekoa 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Lanekoa 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Probakoa"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Partekatua"</string>
 </resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 71dbc43..be9c114 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"آخر هفته"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"رویداد"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"خوابیدن"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"روشن"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"خاموش"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> درحال قطع کردن بعضی از صداهاست"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"بازتاب دادن به نمایشگر ممکن نبود"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"از کابل دیگری استفاده کنید و دوباره امتحان کنید"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"دستگاه بسیار گرم است و تا زمانی‌که خنک نشود نمی‌تواند محتوا را در نمایشگر بازتاب دهد."</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"شاید کابل از نمایشگر پشتیبانی نکند"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"‏کابل USB-C شما ممکن است به‌درستی به نمایشگرها وصل نشود"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"‫Dual screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"‏‫Dual Screen روشن است"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"‫<xliff:g id="APP_NAME">%1$s</xliff:g> از هر دو نمایشگر برای نمایش محتوا استفاده می‌کند"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"جانمایی صفحه‌کلید چنین تنظیم شد: <xliff:g id="LAYOUT_1">%1$s</xliff:g>، <xliff:g id="LAYOUT_2">%2$s</xliff:g>، <xliff:g id="LAYOUT_3">%3$s</xliff:g>… برای تغییر ضربه بزنید"</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"صفحه‌کلیدهای فیزیکی پیکربندی شدند"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"برای مشاهده صفحه‌کلیدها ضربه بزنید"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"خصوصی"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"مشابه‌سازی"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"کار"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"کار ۲"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"کار ۳"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"آزمایش"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"عمومی"</string>
 </resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index c69bafe..d34817e 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Viikonloppuna"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Tapahtuma"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Nukkuminen"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Päällä"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Pois päältä"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> mykistää joitakin ääniä"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Näytön peilaaminen ei onnistu"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Käytä eri johtoa ja yritä uudelleen"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Laite on liian kuuma eikä voi peilata näyttöön, kunnes se viilenee"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Johto ei ehkä tue näyttöjä"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"USB-C-johtosi ei ehkä yhdisty näyttöihin kunnolla"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Kaksoisnäyttö"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Kaksoisnäyttö on päällä"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> käyttää molempia näyttöjä sisällön näyttämiseen"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Näppäimistöasetteluksi valittu <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Muuta asetuksia napauttamalla."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Fyysiset näppäimistöt määritetty"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Katso näppäimistöt napauttamalla"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Yksityinen"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Kloonaus"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Työ"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Työ 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Työ 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Testi"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Jaettu"</string>
 </resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 6c88f45..ba7fd52 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1907,6 +1907,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Fin de semaine"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Événement"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Sommeil"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Activé"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Désactivé"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> désactive certains sons"</string>
@@ -2342,8 +2344,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Impossible de dupliquer l\'écran"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Utilisez un câble différent et réessayez"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Votre appareil est trop chaud et doit refroidir pour pouvoir dupliquer l\'écran"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Le câble peut ne pas être compatible avec les écrans"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Votre câble USB-C peut ne pas se connecter correctement aux écrans"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen activé"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> utilise les deux écrans pour afficher le contenu"</string>
@@ -2360,18 +2360,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Disposition du clavier définie à <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Touchez pour modifier."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Claviers physiques configurés"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Touchez pour afficher les claviers"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Privé"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Clone"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Professionnel"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Professionnel 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Professionnel 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Commun"</string>
 </resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index e0345dd..06b9ec8 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1907,6 +1907,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Week-end"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Événement"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Sommeil"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Activé"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Désactivé"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> coupe certains sons"</string>
@@ -2342,8 +2344,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Duplication impossible"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Utilisez un autre câble et réessayez"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Votre appareil est trop chaud et ne peut pas se dupliquer sur l\'écran tant qu\'il n\'a pas refroidi."</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Le câble n\'est peut-être pas compatible avec les écrans"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Votre câble USB-C n\'est peut-être pas connecté correctement à l\'écran"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen activé"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> utilise les deux écrans pour afficher du contenu"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index c1e2bbf..f599631 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Fin de semana"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Evento"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Durmindo"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Activada"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Desactivada"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> está silenciando algúns sons"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Non se pode proxectar contido na pantalla"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Cambia de cable e téntao de novo"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"O teu dispositivo está demasiado quente; mentres non arrefríe, non se poderá proxectar contido na pantalla"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Pode que o cable non sexa compatible con pantallas"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"O teu cable USB-C pode que non se conecte ás pantallas de maneira adecuada"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen está activada"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> está usando ambas as pantallas para mostrar contido"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"O deseño do teclado estableceuse en <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Toca para cambialo."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Configuráronse varios teclados físicos"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Toca para ver os teclados"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Privado"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Clonado"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Traballo"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Traballo 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Traballo 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Proba"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Compartido"</string>
 </resources>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index da75282..5e12c7d 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"સપ્તાહાંત"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"ઇવેન્ટ"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"નિષ્ક્રિય"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"ચાલુ છે"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"બંધ છે"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> અમુક અવાજોને મ્યૂટ કરે છે"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"ડિસ્પ્લે પર મિરર કરી શકાતું નથી"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"બીજા કોઈ કેબલનો ઉપયોગ કરો અને ફરી પ્રયાસ કરો"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"તમારું ડિવાઇસ ખૂબ જ ગરમ છે અને જ્યાં સુધી તે ઠંડું ન પડે ત્યાં સુધી મિરર કરી શકશે નહીં"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"શક્ય છે કે કેબલ કદાચ ડિસ્પ્લેને સપોર્ટ ન આપતો હોય"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"તમારો USB-C કેબલ કદાચ ડિસ્પ્લે સાથે યોગ્ય રીતે કનેક્ટ ન થાય"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual screen ચાલુ છે"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"કન્ટેન્ટ બતાવવા માટે <xliff:g id="APP_NAME">%1$s</xliff:g> બન્ને ડિસ્પ્લેનો ઉપયોગ કરી રહી છે"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"કીબોર્ડનું લેઆઉટ <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g> પર સેટ કરવામાં આવ્યું છે… બદલવા માટે ટૅપ કરો."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"ભૌતિક કીબોર્ડની ગોઠવણી કરવામાં આવી છે"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"કીબોર્ડ જોવા માટે ટૅપ કરો"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"ખાનગી"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"ક્લોન કરો"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"ઑફિસ"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"ઑફિસ 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"ઑફિસ 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"પરીક્ષણ કરો"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"કૉમ્યુનલ"</string>
 </resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index d448b51..a6d70dd 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"सप्ताहांत"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"इवेंट"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"सोते समय"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"चालू है"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"बंद है"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> कुछ आवाज़ें म्‍यूट कर रहा है"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"डिसप्ले का कॉन्टेंट नहीं दिखाया जा सकता"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"कोई दूसरा केबल इस्तेमाल करके फिर से कोशिश करें"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"आपका डिवाइस बहुत गर्म है. इसलिए, इसके ठंडा होने तक दूसरे डिसप्ले पर इसकी स्क्रीन शेयर नहीं की जा सकती"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"ऐसा हो सकता है कि केबल, डिसप्ले के साथ ठीक से काम न करे"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"ऐसा हो सकता है कि यूएसबी-सी केबल, डिसप्ले के साथ ठीक से कनेक्ट न हो पाए"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual screen की सुविधा चालू है"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g>, कॉन्टेंट दिखाने के लिए दोनों स्क्रीन का इस्तेमाल कर रहा है"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"कीबोर्ड का लेआउट <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… पर सेट कर दिया गया है. इसे बदलने के लिए टैप करें."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"फ़िज़िकल कीबोर्ड कॉन्फ़िगर किए गए"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"कीबोर्ड देखने के लिए टैप करें"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"निजी"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"क्लोन"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"ऑफ़िस"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"ऑफ़िस 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"ऑफ़िस 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"टेस्ट"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"कम्यूनिटी"</string>
 </resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 5ee1527..e574b9a 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1907,6 +1907,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Vikend"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Događaj"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Spavanje"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Uključeno"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Isključeno"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> isključuje neke zvukove"</string>
@@ -2342,8 +2344,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Zrcaljenje na zaslon nije moguće"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Upotrijebite drugi kabel i pokušajte ponovno"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Uređaj je previše zagrijan i ne može se zrcaliti na zaslon dok se ne ohladi"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kabel možda ne podržava zaslone"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Vaš USB-C kabel možda nije ispravno povezan sa zaslonima"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dvostruki zaslon"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Uključen je dvostruki zaslon"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> upotrebljava oba zaslona za prikazivanje sadržaja"</string>
@@ -2360,18 +2360,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Raspored tipkovnice postavljen je na <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Dodirnite da biste ga promijenili."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Fizičke su tipkovnice konfigurirane"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Dodirnite da bi se prikazale tipkovnice"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Privatno"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Kloniranje"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Posao"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Posao 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Posao 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Zajedničko"</string>
 </resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 2c4c77e..a7e67f6 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Hétvége"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Esemény"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Alvás"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Bekapcsolva"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Kikapcsolva"</string>
     <string name="muted_by" msgid="91464083490094950">"A(z) <xliff:g id="THIRD_PARTY">%1$s</xliff:g> lenémít néhány hangot"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Nem lehet tükrözni a kijelzőre"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Használjon másik kábelt, és próbálja újra"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Az eszköz túl meleg – csak a lehűlése után tud tükrözni a kijelzőre."</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Előfordulhat, hogy a kábel nem támogatja a kijelzőket"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Előfordulhat, hogy az USB-C kábellel nem csatlakoztathatók megfelelően a kijelzők"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"A Dual Screen funkció be van kapcsolva"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> mindkét kijelzőt használja a tartalmak megjelenítésére"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"A billentyűzetkiosztás a következőkre van beállítva: <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… A módosításhoz koppintson."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Fizikai billentyűzetek beállítva"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Koppintson a billentyűzetek megtekintéséhez"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Privát"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Klón"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Munkahelyi"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"2. munkahelyi"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"3. munkahelyi"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Teszt"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Közös"</string>
 </resources>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 482e075..6e517fb 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Շաբաթ-կիրակի"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Միջոցառում"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Քնի ժամանակ"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Միացված է"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Անջատված է"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g>-ն անջատում է որոշ ձայներ"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Չհաջողվեց հայելապատճենել էկրանին"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Օգտագործեք այլ մալուխ և նորից փորձեք"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Ձեր սարքը գերտաքացել է և չի կարող հայելապատճենել էկրանը, մինչև ջերմաստիճանը չնվազի"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Մալուխը կարող է համատեղելի չլինել էկրանների հետ"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Հնարավոր է՝ USB-C մալուխը սխալ է միացված էկրանին"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen-ը միացված է"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածն օգտագործում է երկու էկրանները"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Ստեղնաշարի համար կարգավորված են <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g> դասավորությունները։ Հպեք փոխելու համար։"</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Ֆիզիկական ստեղնաշարերը կարգավորված են"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Հպեք՝ ստեղնաշարերը դիտելու համար"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Անձնական"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Կլոն"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Աշխատանքային"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Աշխատանքային 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Աշխատանքային 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Փորձնական"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Ընդհանուր"</string>
 </resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index f18d834..f263f47 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Akhir pekan"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Acara"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Tidur"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Aktif"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Nonaktif"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> mematikan beberapa suara"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Tidak dapat mencerminkan ke layar"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Gunakan kabel lain dan coba lagi"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Perangkat terlalu panas dan tidak dapat mencerminkan ke layar sampai cukup dingin"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kabel mungkin tidak mendukung layar"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Kabel USB-C mungkin tidak terhubung dengan benar ke layar"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual screen aktif"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> menggunakan kedua layar untuk menampilkan konten"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Tata letak keyboard disetel ke <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Ketuk untuk mengubah."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Keyboard fisik telah dikonfigurasi"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Ketuk untuk melihat keyboard"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Pribadi"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Clone"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Kerja"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Kerja 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Kerja 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Pengujian"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Umum"</string>
 </resources>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 30d4231..25608cf 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Helgi"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Viðburður"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Svefn"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Kveikt"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Slökkt"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> þaggar í einhverjum hljóðum"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Ekki er hægt að spegla á skjá"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Notaðu aðra snúru og reyndu aftur"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Tækið er of heitt og getur ekki speglað á skjáinn fyrr en það kólnar"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Ekki er víst að snúran styðji skjái"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Ekki er víst að USB-C-snúran tengist skjám á réttan hátt"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Tveir skjáir"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Kveikt er á tveimur skjám"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> er að nota báða skjái til að sýna efni"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 076c5a3..a99fbe6 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1907,6 +1907,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Fine settimana"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Evento"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Notte"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"On"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Off"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> sta disattivando alcuni suoni"</string>
@@ -2342,8 +2344,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Impossibile eseguire il mirroring al display"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Usa un altro cavo e riprova"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Il tuo dispositivo è troppo caldo e non può eseguire il mirroring al display finché non si raffredda"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Il cavo potrebbe non supportare i display"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Il cavo USB-C potrebbe non collegarsi correttamente ai display"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Doppio schermo"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Doppio schermo attivo"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> sta usando entrambi i display per mostrare contenuti"</string>
@@ -2360,18 +2360,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Layout tastiera impostato su <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Tocca per cambiare l\'impostazione."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Tastiere fisiche configurate"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Tocca per visualizzare le tastiere"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Privato"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Clone"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Lavoro"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Lavoro 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Lavoro 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Condiviso"</string>
 </resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index e8e3847..66250b0 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1907,6 +1907,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"סוף השבוע"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"אירוע"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"שינה"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"מצב פעיל"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"מצב מושבת"</string>
     <string name="muted_by" msgid="91464083490094950">"חלק מהצלילים מושתקים על ידי <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
@@ -2342,8 +2344,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"לא ניתן לשקף למסך"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"צריך להשתמש בכבל שונה ולנסות שוב"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"המכשיר שלך חם מדי. אי אפשר לשקף למסך עד שהמכשיר יתקרר"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"יכול להיות שהכבל לא תומך במסכים"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"‏יכול להיות שכבל ה-USB-C לא יתחבר למסכים כמו שצריך"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"מצב שני מסכים"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"מצב שני מסכים מופעל"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> משתמשת בשני המסכים כדי להציג תוכן"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 8931518..8b87228 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1078,7 +1078,7 @@
     <string name="permlab_addVoicemail" msgid="4770245808840814471">"留守番電話の追加"</string>
     <string name="permdesc_addVoicemail" msgid="5470312139820074324">"留守番電話受信トレイにメッセージを追加することをアプリに許可します。"</string>
     <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> にクリップボードから貼り付けました"</string>
-    <string name="more_item_label" msgid="7419249600215749115">"その他"</string>
+    <string name="more_item_label" msgid="7419249600215749115">"続きを見る"</string>
     <string name="prepend_shortcut_label" msgid="1743716737502867951">"MENU+"</string>
     <string name="menu_meta_shortcut_label" msgid="1623390163674762478">"Meta+"</string>
     <string name="menu_ctrl_shortcut_label" msgid="131911133027196485">"Ctrl+"</string>
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"週末"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"予定"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"睡眠中"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"ON"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"OFF"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> により一部の音はミュートに設定"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"ディスプレイにミラーリングできません"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"別のケーブルでもう一度お試しください"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"デバイスが熱すぎるため、温度が下がるまでディスプレイにミラーリングできません"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"ケーブルはディスプレイに対応していない可能性があります"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"USB-C ケーブルがディスプレイに正しく接続されていない可能性があります"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"デュアル スクリーン"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"デュアル スクリーン: ON"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g>は 2 画面でコンテンツを表示しています"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"キーボードのレイアウトは<xliff:g id="LAYOUT_1">%1$s</xliff:g>、<xliff:g id="LAYOUT_2">%2$s</xliff:g>、<xliff:g id="LAYOUT_3">%3$s</xliff:g>などに設定されています。タップで変更できます。"</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"物理キーボードの設定完了"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"タップするとキーボードを表示できます"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"非公開"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"複製"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"仕事用"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"仕事用 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"仕事用 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"テスト"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"共用"</string>
 </resources>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 1ecdf74..839a817 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"შაბათ-კვირა"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"მოვლენა"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"ძილისას"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"ჩართული"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"გამორთული"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> ზოგიერთ ხმას ადუმებს"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"ეკრანზე არეკვლა შეუძლებელია"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"გამოიყენეთ სხვა კაბელი და ცადეთ ხელახლა"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"თქვენი მოწყობილობა ძალიან თბილია და ვერ ასახავს ეკრანზე სანამ არ გაგრილდება"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"კაბელს შეიძლება არ ჰქონდეს ეკრანების მხარდაჭერა"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"თქვენი USB-C კაბელი შეიძლება სათანადოდ არ უკავშირდებოდეს ეკრანებს"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"ორმაგი ეკრანი"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"ორმაგი ეკრანი ჩართულია"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> იყენებს ორივე ეკრანს შინაარსის საჩვენებლად"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 3e33115..45abbef 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Демалыс күндері"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Іс-шара"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Ұйқы режимі"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Қосулы"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Өшірулі"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> кейбір дыбыстарды өшіруде"</string>
@@ -2329,20 +2331,18 @@
     <string name="system_locale_title" msgid="711882686834677268">"Жүйенің әдепкі параметрі"</string>
     <string name="default_card_name" msgid="9198284935962911468">"<xliff:g id="CARDNUMBER">%d</xliff:g>-КАРТА"</string>
     <string name="permlab_companionProfileWatch" msgid="2457738382085872542">"Сағаттарды басқаруға арналған қосымша сағат профилінің рұқсаты"</string>
-    <string name="permdesc_companionProfileWatch" msgid="5655698581110449397">"Қосымша қолданбаға сағаттарды басқаруға рұқсат беріледі."</string>
+    <string name="permdesc_companionProfileWatch" msgid="5655698581110449397">"Серік қолданбаға сағаттарды басқаруға рұқсат беріледі."</string>
     <string name="permlab_observeCompanionDevicePresence" msgid="9008994909653990465">"Серіктес құрылғының бар-жоғын бақылау"</string>
-    <string name="permdesc_observeCompanionDevicePresence" msgid="3011699826788697852">"Қосымша қолданбаға қолданбалар маңайда немесе алыста болған кезде қосымша құрылғының бар болуын бақылауға рұқсат беріледі."</string>
+    <string name="permdesc_observeCompanionDevicePresence" msgid="3011699826788697852">"Серік қолданбаға құрылғылар маңайда немесе алыста болуына қарамастан серік құрылғыны табуға рұқсат беріледі."</string>
     <string name="permlab_deliverCompanionMessages" msgid="3931552294842980887">"Ілеспе хабарлар жеткізу"</string>
-    <string name="permdesc_deliverCompanionMessages" msgid="2170847384281412850">"Қосымша қолданбаға ілеспе хабарларды басқа құрылғыларға жеткізуге рұқсат беріледі."</string>
+    <string name="permdesc_deliverCompanionMessages" msgid="2170847384281412850">"Серік қолданбаға басқа құрылғыларға серік хабарлар жеткізуге рұқсат беріледі."</string>
     <string name="permlab_startForegroundServicesFromBackground" msgid="6363004936218638382">"Экрандық режимдегі қызметтерді фоннан іске қосу"</string>
-    <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Қосымша қолданбаға экрандық режимдегі қызметтерді фоннан іске қосуға рұқсат беріледі."</string>
+    <string name="permdesc_startForegroundServicesFromBackground" msgid="4071826571656001537">"Серік қолданбаға экрандық режимдегі қызметтерді фоннан іске қосуға рұқсат беріледі."</string>
     <string name="mic_access_on_toast" msgid="2666925317663845156">"Микрофон қолжетімді."</string>
     <string name="mic_access_off_toast" msgid="8111040892954242437">"Микрофон блокталған."</string>
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Дисплейге көшірмені көрсету мүмкін емес"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Басқа кабельмен әрекетті қайталап көріңіз."</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Құрылғыңыз тым қызып кетті, сондықтан ол суымайынша, дисплейге экран көшірмесін көрсете алмайды."</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Кабель дисплейлерді қолдамауы мүмкін"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"USB-C кабелі дисплейлерге дұрыс жалғанбаған болуы мүмкін."</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen функциясы қосулы"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасы контентті көрсету үшін екі дисплейді де пайдаланады."</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Пернетақта схемасы \"<xliff:g id="LAYOUT_1">%1$s</xliff:g>\", \"<xliff:g id="LAYOUT_2">%2$s</xliff:g>\", \"<xliff:g id="LAYOUT_3">%3$s</xliff:g>\" деп орнатылды… Өзгерту үшін түртіңіз."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Физикалық пернетақталар конфигурацияланды"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Пернетақталарды көру үшін түртіңіз."</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Жеке"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Клон"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Жұмыс"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Жұмыс 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Жұмыс 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Сынақ"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Жалпы"</string>
 </resources>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 0bcf992..3aec1f6 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"ចុងសប្ដាហ៍"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"ព្រឹត្តិការណ៍"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"កំពុងដេក"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"បើក"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"បិទ"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> កំពុង​បិទសំឡេង​មួយចំនួន"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"មិនអាចបញ្ចាំងទៅផ្ទាំងអេក្រង់បានទេ"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"ប្រើខ្សែផ្សេង រួចព្យាយាមម្តងទៀត"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"ឧបករណ៍របស់អ្នកក្ដៅពេក និងមិនអាចបញ្ចាំងទៅផ្ទាំងអេក្រង់បានទេ រហូតទាល់តែវាចុះត្រជាក់សិន"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"ខ្សែប្រហែលជាមិនអាចប្រើជាមួយផ្ទាំងអេក្រង់បានទេ"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"ខ្សែ USB-C របស់អ្នក​ប្រហែលជា​មិនអាចភ្ជាប់​ផ្ទាំងអេក្រង់​បានត្រឹមត្រូវទេ"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"អេក្រង់ពីរ"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"អេក្រង់ពីរត្រូវបានបើក"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> កំពុងប្រើផ្ទាំងអេក្រង់ទាំងពីរដើម្បីបង្ហាញខ្លឹមសារ"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"បានកំណត់ប្លង់ក្ដារចុចទៅ <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… សូមចុចដើម្បីប្ដូរ។"</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"បានកំណត់រចនាសម្ព័ន្ធ​ក្ដារចុចរូបវន្ត"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"ចុចដើម្បីមើលក្ដារចុច"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"ឯកជន"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"ក្លូន"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"ការងារ"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"ការងារទី 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"ការងារទី 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"ការធ្វើ​តេស្ត"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"ទូទៅ"</string>
 </resources>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index a69601a..388fe20 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -1364,7 +1364,7 @@
     <string name="no_permissions" msgid="5729199278862516390">"ಯಾವುದೇ ಅನುಮತಿಗಳ ಅಗತ್ಯವಿಲ್ಲ"</string>
     <string name="perm_costs_money" msgid="749054595022779685">"ಇದು ನಿಮ್ಮ ಹಣವನ್ನು ವ್ಯಯಿಸಬಹುದು"</string>
     <string name="dlg_ok" msgid="5103447663504839312">"ಸರಿ"</string>
-    <string name="usb_charging_notification_title" msgid="1674124518282666955">"USB ಮೂಲಕ ಈ ಸಾಧನವು ಚಾರ್ಜ್‌ ಆಗುತ್ತಿದೆ"</string>
+    <string name="usb_charging_notification_title" msgid="1674124518282666955">"USB ಮೂಲಕ ಈ ಸಾಧನವನ್ನು ಚಾರ್ಜ್‌ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
     <string name="usb_supplying_notification_title" msgid="5378546632408101811">"USB ಮೂಲಕ ಸಂಪರ್ಕಗೊಂಡಿರುವ ಸಾಧನವನ್ನು ಚಾರ್ಜ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
     <string name="usb_mtp_notification_title" msgid="1065989144124499810">"USB ಫೈಲ್ ವರ್ಗಾವಣೆಯು ಆನ್‌ ಆಗಿದೆ"</string>
     <string name="usb_ptp_notification_title" msgid="5043437571863443281">"USB ಮೂಲಕ PTP ಆನ್‌ ಆಗಿದೆ"</string>
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"ವಾರಾಂತ್ಯ"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"ಈವೆಂಟ್"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"ನಿದ್ರೆಯ ಸಮಯ"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"ಆನ್ ಆಗಿದೆ"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"ಆಫ್ ಆಗಿದೆ"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> ಧ್ವನಿ ಮ್ಯೂಟ್ ಮಾಡುತ್ತಿದ್ದಾರೆ"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"ಡಿಸ್‌ಪ್ಲೇಗೆ ಪ್ರತಿಬಿಂಬಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"ಬೇರೆ ಕೇಬಲ್ ಬಳಸಿ ಹಾಗೂ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"ನಿಮ್ಮ ಸಾಧನವು ತುಂಬಾ ಬಿಸಿಯಾಗಿದೆ ಮತ್ತು ಅದು ತಣ್ಣಗಾಗುವವರೆಗೆ ಡಿಸ್‌ಪ್ಲೇಗೆ ಪ್ರತಿಬಿಂಬಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"ಡಿಸ್‌ಪ್ಲೇಗಳನ್ನು ಕೇಬಲ್ ಬೆಂಬಲಿಸದಿರಬಹುದು"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"ನಿಮ್ಮ USB-C ಕೇಬಲ್ ಡಿಸ್‌ಪ್ಲೇಗಳಿಗೆ ಸರಿಯಾಗಿ ಕನೆಕ್ಟ್ ಆಗದಿರಬಹುದು"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen ಆನ್ ಆಗಿದೆ"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"ಕಂಟೆಂಟ್‌ ಅನ್ನು ತೋರಿಸಲು <xliff:g id="APP_NAME">%1$s</xliff:g> ಎರಡೂ ಡಿಸ್‌ಪ್ಲೇಗಳನ್ನು ಬಳಸುತ್ತಿದೆ"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"ಕೀಬೋರ್ಡ್ ಲೇಔಟ್ ಅನ್ನು <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g> ಗೆ ಸೆಟ್ ಮಾಡಲಾಗಿದೆ… ಬದಲಾಯಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"ಭೌತಿಕ ಕೀಬೋರ್ಡ್‌ಗಳನ್ನು ಕಾನ್ಫಿಗರ್ ಮಾಡಲಾಗಿದೆ"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"ಕೀಬೋರ್ಡ್‌ಗಳನ್ನು ವೀಕ್ಷಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"ಖಾಸಗಿ"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"ಕ್ಲೋನ್"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"ಕೆಲಸ"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"ಕೆಲಸ 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"ಕೆಲಸ 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"ಪರೀಕ್ಷೆ"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"ಸಮುದಾಯ"</string>
 </resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 77d45c7..f002fd5 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"주말"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"캘린더 일정"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"수면 시간"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"사용"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"사용 중지"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g>(이)가 일부 소리를 음소거함"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"디스플레이에 미러링할 수 없음"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"다른 케이블을 사용하여 다시 시도해 보세요."</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"기기의 온도가 너무 높아서 온도가 내려갈 때까지 화면에 미러링할 수 없습니다."</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"디스플레이를 지원하지 않는 케이블일 수 있음"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"사용 중인 USB-C 케이블이 디스플레이에 제대로 연결되지 않을 수 있습니다."</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen 켜짐"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 두 화면을 모두 사용하여 콘텐츠를 표시합니다."</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"키보드 레이아웃이 <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>로 설정됩니다. 변경하려면 탭하세요."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"실제 키보드에 구성됨"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"키보드를 보려면 탭하세요."</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"비공개"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"복사"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"직장"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"직장 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"직장 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"테스트"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"공동"</string>
 </resources>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index ee7b407..73161e4 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -1454,7 +1454,7 @@
     <string name="ext_media_status_checking" msgid="159013362442090347">"Текшерилүүдө…"</string>
     <string name="ext_media_status_mounted" msgid="3459448555811203459">"Даяр"</string>
     <string name="ext_media_status_mounted_ro" msgid="1974809199760086956">"Окуу үчүн гана"</string>
-    <string name="ext_media_status_bad_removal" msgid="508448566481406245">"Коопсуз өчүрүлгөн жок"</string>
+    <string name="ext_media_status_bad_removal" msgid="508448566481406245">"Коопсуз өчкөн жок"</string>
     <string name="ext_media_status_unmountable" msgid="7043574843541087748">"Бузулган"</string>
     <string name="ext_media_status_unsupported" msgid="5460509911660539317">"Колдоого алынбайт"</string>
     <string name="ext_media_status_ejecting" msgid="7532403368044013797">"Чыгарылууда…"</string>
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Дем алыш"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Иш-чара"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Уйку режими"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Күйүк"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Өчүк"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> айрым үндөрдү өчүрүүдө"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Экранга күзгүдөй чагылдыруу мүмкүн эмес"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Башка кабелди колдонуп, кайра аракет кылыңыз"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Түзмөгүңүз өтө ысып кетти жана ал муздамайынча башка экранга чыгара албайт"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Кабель дисплейлерди колдоого албашы мүмкүн"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"USB-C кабели дисплейлерге туура туташпашы мүмкүн"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Кош экран"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen күйүк"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> контентти эки түзмөктө тең көрсөтүүдө"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Баскычтопко төмөнкү калып коюлду: <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Өзгөртүү үчүн басыңыз."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Физикалык баскычтоптор конфигурацияланды"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Баскычтопторду көрүү үчүн басыңыз"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Купуя"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Клон"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Жумуш"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Жумуш 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Жумуш 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Сыноо"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Жалпы"</string>
 </resources>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index d9698e3..e687436 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"ທ້າຍອາທິດ"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"ການນັດໝາຍ"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"ການນອນ"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"ເປີດຢູ່"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"ປິດຢູ່"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> ປິດສຽງບາງຢ່າງໄວ້"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"ບໍ່ສາມາດສະທ້ອນໄປຫາຈໍສະແດງຜົນໄດ້"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"ກະລຸນາໃຊ້ສາຍອື່ນແລ້ວລອງໃໝ່"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"ອຸປະກອນຂອງທ່ານຮ້ອນເກີນໄປ ແລະ ບໍ່ສາມາດສະທ້ອນໄປຫາຈໍສະແດງຜົນໄດ້ຈົນກວ່າມັນຈະເຢັນລົງ"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"ສາຍອາດບໍ່ຮອງຮັບຈໍສະແດງຜົນ"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"ສາຍ USB-C ຂອງທ່ານອາດບໍ່ໄດ້ເຊື່ອມຕໍ່ກັບຈໍສະແດງຜົນຢ່າງຖືກຕ້ອງ"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"ໜ້າຈໍຄູ່"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"ເປີດ Dual Screen ຢູ່"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> ກຳລັງໃຊ້ຈໍສະແດງຜົນທັງສອງເພື່ອສະແດງເນື້ອຫາ"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"ຕັ້ງໂຄງຮ່າງແປ້ນພິມເປັນ <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… ແຕະເພື່ອປ່ຽນແປງ."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"ຕັ້ງຄ່າແປ້ນພິມແທ້ແລ້ວ"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"ແຕະເພື່ອເບິ່ງແປ້ນພິມ"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"ສ່ວນຕົວ"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"ໂຄລນ"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"ວຽກ"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"ວຽກ 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"ວຽກ 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"ທົດສອບ"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"ສ່ວນກາງ"</string>
 </resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 2a2a088..b3c9f37 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1908,6 +1908,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Savaitgalį"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Įvykis"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Miegas"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Įjungti"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Išjungti"</string>
     <string name="muted_by" msgid="91464083490094950">"„<xliff:g id="THIRD_PARTY">%1$s</xliff:g>“ nutildo kai kuriuos garsus"</string>
@@ -2343,8 +2345,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Negalima bendrinti ekrano vaizdo ekrane"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Naudokite kitą laiką ir bandykite dar kartą"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Jūsų įrenginys per daug įkaitęs ir negali bendrinti ekrano vaizdo, kol atvės"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Laidas gali nepalaikyti ekranų"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Gali būti, kad USB-C laidu nepavyksta tinkamai prisijungti prie ekranų"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Įjungta „Dual Screen“"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ naudoja abu ekranus turiniui rodyti"</string>
@@ -2361,18 +2361,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Išdėstymas nustatytas į <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Palieskite, kad pakeistumėte."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Sukonfigūruotos fizinės klaviatūros"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Palieskite, kad peržiūrėtumėte klaviatūras"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Privatu"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Identiška kopija"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Darbas"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Darbas (2)"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Darbas (3)"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Bandymas"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Bendruomenės"</string>
 </resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 8c7c206..a14e7c5 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1907,6 +1907,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Nedēļas nogalē"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Pasākums"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Gulēšana"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Ieslēgta"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Izslēgta"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> izslēdz noteiktas skaņas"</string>
@@ -2342,8 +2344,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Nevar spoguļot displeju"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Izmantojiet citu vadu un mēģiniet vēlreiz."</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Jūsu ierīce ir pārāk silta, un to nevar spoguļot displejā, kamēr tā nav atdzisusi."</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Iespējams, vads neatbalsta displejus"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Iespējams, jūsu USB-C vads nevarēs nodrošināt pareizu savienojumu ar displejiem."</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen režīms"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Ieslēgts Dual Screen režīms"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> satura rādīšanai izmanto abus displejus."</string>
@@ -2360,18 +2360,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Ir iestatīti šādi tastatūras izkārtojumi: <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Lai to mainītu, pieskarieties."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Fiziskās tastatūras ir konfigurētas"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Lai skatītu tastatūras, pieskarieties"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Privāts"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Klons"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Darbam"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Darbam (2.)"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Darbam (3.)"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Testēšanai"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Kopīgs"</string>
 </resources>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 4d2f72e..e4ba9fa 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Викенд"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Настан"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Спиење"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Вклучено"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Исклучено"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> исклучи некои звуци"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Не може да се отсликува за прикажување"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Користете друг кабел и обидете се повторно"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Вашиот уред е премногу топол и не може да се отсликува на екранот додека не се излади"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Кабелот можеби не поддржува екрани"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Кабелот USB-C можеби нема да се поврзе правилно со екраните"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Вклучен е Dual Screen"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> ги користи двата екрани за да прикажува содржини"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Распоредот на тастатурата е поставен на <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Допрете за да промените."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Физичките тастатури се конфигурирани"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Допрете за да ги видите тастатурите"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Приватен профил"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Клониран профил"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Работен профил"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Работен профил 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Работен профил 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Профил за тестирање"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Профил на заедницата"</string>
 </resources>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index be40575..8aa2c9a 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"വാരാന്ത്യം"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"ഇവന്റ്"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"ഉറക്കം"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"ഓണാണ്"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"ഓഫാണ്"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> ചില ശബ്‌ദങ്ങൾ മ്യൂട്ട് ചെയ്യുന്നു"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"ഡിസ്‌പ്ലേയിലേക്ക് മിറർ ചെയ്യാനാകില്ല"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"മറ്റൊരു കേബിൾ ഉപയോഗിച്ച് വീണ്ടും ശ്രമിക്കുക"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"നിങ്ങളുടെ ഉപകരണത്തിന് ചൂട് വളരെ കൂടുതലാണ്, അത് തണുക്കുന്നത് വരെ ഡിസ്‌പ്ലേയിലേക്ക് മിറർ ചെയ്യാനാകില്ല"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"കേബിൾ, ഡിസ്പ്ലേകളെ പിന്തുണച്ചേക്കില്ല"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"നിങ്ങളുടെ USB-C കേബിൾ, ഡിസ്‌പ്ലേകളിലേക്ക് ശരിയായി കണക്റ്റ് ആയേക്കില്ല"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"ഡ്യുവൽ സ്ക്രീൻ"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"ഡ്യുവൽ സ്ക്രീൻ ഓണാണ്"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"ഉള്ളടക്കം കാണിക്കാൻ <xliff:g id="APP_NAME">%1$s</xliff:g> രണ്ട് ഡിസ്പ്ലേകളും ഉപയോഗിക്കുന്നു"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"കീബോർഡ് ലേഔട്ട് ആയി ഇനിപ്പറയുന്നവ സജ്ജീകരിച്ചു: <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… മാറ്റാൻ ടാപ്പ് ചെയ്യുക."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"യഥാർത്ഥ കീബോർഡുകൾ കോൺഫിഗർ ചെയ്‌തു"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"കീബോർഡുകൾ കാണാൻ ടാപ്പ് ചെയ്യുക"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"സ്വകാര്യം"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"ക്ലോൺ ചെയ്യുക"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"ഔദ്യോഗികം"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"ഔദ്യോഗികം 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"ഔദ്യോഗികം 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"ടെസ്‌റ്റ്"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"കമ്മ്യൂണൽ"</string>
 </resources>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index c215b88..27bcd80 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Амралтын өдөр"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Үйл явдал"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Унтлагын цаг"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Асаалттай"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Унтраалттай"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> зарим дууны дууг хааж байна"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Дэлгэцэд тусгал үүсгэх боломжгүй"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Өөр кабель ашиглаад, дахин оролдоно уу"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Таны төхөөрөмж хэт халсан бөгөөд үүнийг хөрөх хүртэл дэлгэцэд тусгал үүсгэх боломжгүй"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Кабель нь дэлгэцүүдийг дэмждэггүй байж магадгүй"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Таны USB-C кабель дэлгэцүүдэд зохих ёсоор холбогдохгүй байж магадгүй"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual screen асаалттай байна"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> контент харуулахын тулд хоёр дэлгэцийг хоёуланг нь ашиглаж байна"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Гарын бүдүүвчийг <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g> болгож тохируулсан… Өөрчлөхийн тулд товшино уу."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Биет гарыг тохируулсан"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Гарыг харахын тулд товшино уу"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Хувийн"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Клон"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Ажил"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Ажил 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Ажил 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Туршилт"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Нийтийн"</string>
 </resources>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 03fcc17..48d4fdb 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"आठवड्याच्या शेवटी"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"इव्‍हेंट"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"झोपताना"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"सुरू आहे"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"बंद आहे"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> काही ध्‍वनी म्‍यूट करत आहे"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"डिस्प्लेवर मिरर करू शकत नाही"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"वेगळी केबल वापरून पुन्हा प्रयत्न करा"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"तुमचे डिव्हाइस खूप गरम आहे आणि ते थंड होईपर्यंत डिस्प्लेमध्ये मिरर करू शकत नाही"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"केबल कदाचित डिस्प्लेना सपोर्ट करणार नाही"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"तुमची USB-C केबल कदाचित डिस्प्लेना योग्यरीत्या कनेक्ट होणार नाही"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual screen सुरू आहे"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"आशय दाखवण्यासाठी <xliff:g id="APP_NAME">%1$s</xliff:g> दोन्ही डिस्प्ले वापरत आहे"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"कीबोर्ड लेआउट <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g> वर सेट करा… बदलण्यासाठी टॅप करा."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"वास्तविक कीबोर्ड कॉंफिगर केला"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"कीबोर्ड पाहण्यासाठी टॅप करा"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"खाजगी"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"क्लोन"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"ऑफिस"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"ऑफिस २"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"ऑफिस ३"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"चाचणी"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"सामुदायिक"</string>
 </resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 84b79a8..5254490 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Hujung minggu"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Acara"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Tidur"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Hidup"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Mati"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> meredamkan sesetengah bunyi"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Tidak dapat menyegerakkan kepada paparan"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Gunakan kabel lain dan cuba lagi"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Peranti anda terlalu panas dan tidak dapat dicerminkan kepada paparan sehingga peranti sejuk"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kabel mungkin tidak menyokong paparan"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Kabel USB-C anda mungkin tidak bersambung kepada paparan dengan betul"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dwiskrin"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dwiskrin dihidupkan"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> menggunakan kedua-dua paparan untuk menunjukkan kandungan"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Reka letak papan kekunci ditetapkan kepada <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Ketik untuk menukar reka letak."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Papan kekunci fizikal dikonfigurasikan"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Ketik untuk melihat papan kekunci"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Peribadi"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Klon"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Kerja"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Kerja 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Kerja 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Ujian"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Umum"</string>
 </resources>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 01906b9..9e8a4a9 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"စနေ၊ တနင်္ဂနွေ"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"အစီအစဉ်"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"အိပ်နေချိန်"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"ဖွင့်"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"ပိတ်"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> သည် အချို့အသံကို ပိတ်နေသည်"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"ဖန်သားပြင်တွင် စကရင်ပွား၍ မရပါ"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"အခြားကေဘယ်ကြိုးသုံးပြီး ထပ်စမ်းကြည့်ပါ"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"သင့်စက်ပစ္စည်း ပူလွန်းနေသဖြင့် ၎င်းမအေးသေးမီ ဖန်သားပြင်သို့ စကရင်ပွား၍မရပါ"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"ကေဘယ်ကြိုးက ဖန်သားပြင်များကို မပံ့ပိုးခြင်း ဖြစ်နိုင်သည်"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"သင့် USB-C ကေဘယ်ကြိုးသည် ဖန်သားပြင်များနှင့် မှန်ကန်စွာ ချိတ်ဆက်မထားခြင်း ဖြစ်နိုင်သည်"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual screen ဖွင့်ထားသည်"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> သည် အကြောင်းအရာကို ပြရန် ဖန်သားပြင်နှစ်ခုစလုံးကို သုံးနေသည်"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"ကီးဘုတ်အပြင်အဆင်ကို <xliff:g id="LAYOUT_1">%1$s</xliff:g>၊ <xliff:g id="LAYOUT_2">%2$s</xliff:g>၊ <xliff:g id="LAYOUT_3">%3$s</xliff:g> သို့ သတ်မှတ်လိုက်သည်… ပြောင်းရန် တို့ပါ။"</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"ပကတိကီးဘုတ်များကို စီစဉ်သတ်မှတ်ထားသည်"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"ကီးဘုတ်များကြည့်ရန် တို့ပါ"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"သီးသန့်"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"ဆင်တူပြုလုပ်ရန်"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"အလုပ်"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"အလုပ် ၂"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"အလုပ် ၃"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"စမ်းသပ်မှု"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"အများသုံး"</string>
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index d8e3b40..196f98d 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Helg"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Aktivitet"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Sover"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"På"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Av"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> slår av noen lyder"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Kan ikke speile til skjermen"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Bruk en annen kabel og prøv igjen"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Enheten er for varm og kan ikke speiles til skjermen før den kjøles ned"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kabelen støtter kanskje ikke skjermer"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"USB-C-kabelen din kobler seg kanskje ikke til skjermer på riktig måte"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen er på"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> bruker begge skjermene til å vise innhold"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Tastaturoppsettet er satt til <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g> … Trykk for å endre det."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"De fysiske tastaturene er konfigurert"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Trykk for å se tastaturene"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Privat"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Klone"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Jobb"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Jobb 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Jobb 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Felles"</string>
 </resources>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 126f612..1411463 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"शनिबार"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"कार्यक्रम"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"निदाएका बेला"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"अन छ"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"अफ छ"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> ले केही ध्वनिहरू म्युट गर्दै छ"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"डिस्प्लेमा मिरर गर्न सकिएन"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"अर्कै केबल प्रयोग गरी फेरि प्रयास गर्नुहोस्"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"तपाईंको डिभाइस निकै तातो छ र यो चिसो नभएसम्म यसले डिस्प्लेमा मिरर गर्न सक्दैन"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"यो केबल डिस्प्लेहरूमा प्रयोग गर्न नमिल्न सक्छ"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"तपाईंको USB-C केबल डिस्प्लेहरूमा राम्रोसँग नजोडिन सक्छ"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen अन छ"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> ले सामग्री देखाउन दुई वटै डिस्प्ले प्रयोग गरिरहेको छ"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"किबोर्ड लेआउट <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g> भाषामा सेट गरिएको छ… बदल्न ट्याप गर्नुहोस्।"</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"भौतिक किबोर्डहरू कन्फिगर गरिएका छन्"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"किबोर्डहरू हेर्न ट्याप गर्नुहोस्"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"निजी"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"क्लोन"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"कार्य प्रोफाइल"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"कार्य प्रोफाइल २"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"कार्य प्रोफाइल ३"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"परीक्षण"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"सामुदायिक"</string>
 </resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index bc18797..c41dae7 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Weekend"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Afspraken"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Slapen"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Aan"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Uit"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> zet sommige geluiden uit"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Kan niet spiegelen naar scherm"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Gebruik een andere kabel en probeer het opnieuw"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Je apparaat is te warm en kan pas naar het scherm mirroren als het is afgekoeld"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"De kabel ondersteunt misschien geen schermen"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Je USB-C-kabel sluit misschien niet goed aan op schermen"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen staat aan"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> gebruikt beide schermen om content te tonen"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Toetsenbordindeling ingesteld op <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Tik om te wijzigen."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Fysieke toetsenborden zijn ingesteld"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Tik om toetsenborden te bekijken"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Privé"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Kloon"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Werk"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Werk 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Werk 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Gemeenschappelijk"</string>
 </resources>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 7f66887..7a1b7f4 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -910,7 +910,7 @@
     <string name="eventTypeCustom" msgid="3257367158986466481">"କଷ୍ଟମ୍‌"</string>
     <string name="eventTypeBirthday" msgid="7770026752793912283">"ଜନ୍ମଦିନ"</string>
     <string name="eventTypeAnniversary" msgid="4684702412407916888">"ଆନିଭର୍ସରୀ"</string>
-    <string name="eventTypeOther" msgid="530671238533887997">"ଅନ୍ୟାନ୍ୟ"</string>
+    <string name="eventTypeOther" msgid="530671238533887997">"ଅନ୍ୟ"</string>
     <string name="emailTypeCustom" msgid="1809435350482181786">"କଷ୍ଟମ୍‌"</string>
     <string name="emailTypeHome" msgid="1597116303154775999">"ହୋମ"</string>
     <string name="emailTypeWork" msgid="2020095414401882111">"ୱାର୍କ"</string>
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"ସପ୍ତାହାନ୍ତ"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"ଇଭେଣ୍ଟ"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"ଶୋଇବା"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"ଚାଲୁ ଅଛି"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"ବନ୍ଦ ଅଛି"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> କିଛି ସାଉଣ୍ଡକୁ ମ୍ୟୁଟ୍ କରୁଛି"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"ଡିସପ୍ଲେ କରିବାକୁ ମିରର କରାଯାଇପାରିବ ନାହିଁ"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"ଏକ ଭିନ୍ନ କେବୁଲ ବ୍ୟବହାର କରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"ଆପଣଙ୍କ ଡିଭାଇସ ବହୁତ ଗରମ ଅଛି ଏବଂ ଏହା ଥଣ୍ଡା ନହେବା ପର୍ଯ୍ୟନ୍ତ ଡିସପ୍ଲେକୁ ମିରର କରିପାରିବ ନାହିଁ"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"କେବୁଲ ଡିସପ୍ଲେଗୁଡ଼ିକୁ ସମର୍ଥନ କରିନପାରେ"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"ଆପଣଙ୍କ USB-C କେବୁଲ ଡିସପ୍ଲେଗୁଡ଼ିକ ସହ ସଠିକ ଭାବରେ କନେକ୍ଟ ହୋଇନପାରେ"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen ଚାଲୁ ଅଛି"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"ବିଷୟବସ୍ତୁ ଦେଖାଇବା ପାଇଁ <xliff:g id="APP_NAME">%1$s</xliff:g> ଉଭୟ ଡିସପ୍ଲେକୁ ବ୍ୟବହାର କରୁଛି"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"କୀବୋର୍ଡ ଲେଆଉଟକୁ <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>ରେ ସେଟ କରାଯାଇଛି… ପରିବର୍ତ୍ତନ କରିବାକୁ ଟାପ କରନ୍ତୁ।"</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"ଫିଜିକାଲ କୀବୋର୍ଡଗୁଡ଼ିକୁ କନଫିଗର କରାଯାଇଛି"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"କୀବୋର୍ଡଗୁଡ଼ିକୁ ଦେଖିବା ପାଇଁ ଟାପ କରନ୍ତୁ"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"ପ୍ରାଇଭେଟ"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"କ୍ଲୋନ"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"ୱାର୍କ"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"ୱାର୍କ 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"ୱାର୍କ 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"ଟେଷ୍ଟ"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"କମ୍ୟୁନାଲ"</string>
 </resources>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 0396149..cccb3dd 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"ਹਫ਼ਤੇ ਦਾ ਅੰਤਲਾ ਦਿਨ"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"ਇਵੈਂਟ"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"ਸੌਣ ਵੇਲੇ"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"ਚਾਲੂ ਹੈ"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"ਬੰਦ ਹੈ"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> ਕੁਝ ਧੁਨੀਆਂ ਨੂੰ ਮਿਊਟ ਕਰ ਰਹੀ ਹੈ"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"ਡਿਸਪਲੇ \'ਤੇ ਪ੍ਰਤਿਬਿੰਬਿਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"ਕੋਈ ਵੱਖਰੀ ਕੇਬਲ ਵਰਤ ਕੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"ਤੁਹਾਡਾ ਡੀਵਾਈਸ ਬਹੁਤ ਜ਼ਿਆਦਾ ਗਰਮ ਹੈ ਅਤੇ ਜਦੋਂ ਤੱਕ ਇਹ ਠੰਡਾ ਨਹੀਂ ਹੋ ਜਾਂਦਾ ਉਦੋਂ ਤੱਕ ਡਿਸਪਲੇ ਨੂੰ ਪ੍ਰਤਿਬਿੰਬਿਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਕੇਬਲ ਡਿਸਪਲੇਆਂ ਦਾ ਸਮਰਥਨ ਨਾ ਕਰੇ"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਤੁਹਾਡੀ USB-C ਕੇਬਲ ਡਿਸਪਲੇਆਂ ਨਾਲ ਠੀਕ ਤਰ੍ਹਾਂ ਕਨੈਕਟ ਨਾ ਹੋਵੇ"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen ਚਾਲੂ ਹੈ"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਸਮੱਗਰੀ ਨੂੰ ਦਿਖਾਉਣ ਲਈ ਦੋਵੇਂ ਡਿਸਪਲੇਆਂ ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੀ ਹੈ"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"ਕੀ-ਬੋਰਡ ਦਾ ਖਾਕਾ <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g> \'ਤੇ ਸੈੱਟ ਹੈ… ਬਦਲਣ ਲਈ ਟੈਪ ਕਰੋ।"</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"ਭੌਤਿਕ ਕੀ-ਬੋਰਡਾਂ ਦਾ ਸੰਰੂਪਣ ਕੀਤਾ ਗਿਆ"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"ਕੀ-ਬੋਰਡਾਂ ਨੂੰ ਦੇਖਣ ਲਈ ਟੈਪ ਕਰੋ"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"ਨਿੱਜੀ"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"ਕਲੋਨ"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"ਕਾਰਜ"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"ਕੰਮ ਸੰਬੰਧੀ 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"ਕੰਮ ਸੰਬੰਧੀ 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"ਜਾਂਚ"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"ਭਾਈਚਾਰਕ"</string>
 </resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 66d5570..5143e9e 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1908,6 +1908,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Weekend"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Wydarzenie"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Sen"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Włączono"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Wyłączono"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> wycisza niektóre dźwięki"</string>
@@ -2343,8 +2345,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Nie można utworzyć odbicia lustrzanego na wyświetlaczu"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Użyj innego kabla i spróbuj ponownie"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Urządzenie ma zbyt wysoką temperaturę i nie może utworzyć odbicia lustrzanego zawartości ekranu, dopóki się nie ochłodzi."</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kabel może nie obsługiwać wyświetlaczy"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Kabel USB-C może nie łączyć się prawidłowo z wyświetlaczami"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Podwójny ekran"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Włączono podwójny ekran"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> korzysta z obu wyświetlaczy, aby pokazać treści"</string>
@@ -2361,18 +2361,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Ustawiono układ klawiatury <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Kliknij, aby to zmienić."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Skonfigurowano klawiatury fizyczne"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Kliknij, aby wyświetlić klawiatury"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Prywatny"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Klon"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Służbowy"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Służbowy 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Służbowy 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Testowy"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Wspólny"</string>
 </resources>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index e32c738..f7b6b0b 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1365,7 +1365,7 @@
     <string name="no_permissions" msgid="5729199278862516390">"Nenhuma permissão necessária"</string>
     <string name="perm_costs_money" msgid="749054595022779685">"isso pode lhe custar dinheiro"</string>
     <string name="dlg_ok" msgid="5103447663504839312">"OK"</string>
-    <string name="usb_charging_notification_title" msgid="1674124518282666955">"Carregando este dispositivo via USB"</string>
+    <string name="usb_charging_notification_title" msgid="1674124518282666955">"Carregar dispositivo via USB"</string>
     <string name="usb_supplying_notification_title" msgid="5378546632408101811">"Carregando dispositivo conectado via USB"</string>
     <string name="usb_mtp_notification_title" msgid="1065989144124499810">"Transferência de arquivo via USB ativada"</string>
     <string name="usb_ptp_notification_title" msgid="5043437571863443281">"PTP via USB ativado"</string>
@@ -1907,6 +1907,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Fim de semana"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Evento"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Dormir"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Ativada"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Desativada"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> está silenciando alguns sons"</string>
@@ -2342,8 +2344,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Não é possível espelhar a tela"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Use outro cabo e tente de novo"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"O dispositivo está muito quente. Não será possível espelhar a tela até ele resfriar"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Talvez o cabo não tenha suporte a telas"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Seu cabo USB-C pode não se conectar a telas corretamente"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Tela dupla"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"A tela dupla está ativada"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está usando as duas telas para mostrar conteúdo"</string>
@@ -2360,18 +2360,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Layout do teclado definido como <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Toque para mudar."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Teclados físicos configurados"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Toque para conferir os teclados"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Particular"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Clone"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Trabalho"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Trabalho 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Trabalho 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Teste"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Público"</string>
 </resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 15e08ba..5e6cc3e 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1907,6 +1907,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Fim de semana"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Evento"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"A dormir"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Ativada"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Desativada"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> está a desativar alguns sons."</string>
@@ -2342,8 +2344,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Não é possível espelhar para o ecrã"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Use um cabo diferente e tente novamente"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"O dispositivo está demasiado quente e não consegue espelhar para o ecrã até arrefecer"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"O cabo pode não suportar ecrãs"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"O cabo USB-C pode não se ligar a ecrãs corretamente"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Funcionalidade Dual Screen ativada"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> está a usar ambos os ecrãs para mostrar conteúdo"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index e32c738..f7b6b0b 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1365,7 +1365,7 @@
     <string name="no_permissions" msgid="5729199278862516390">"Nenhuma permissão necessária"</string>
     <string name="perm_costs_money" msgid="749054595022779685">"isso pode lhe custar dinheiro"</string>
     <string name="dlg_ok" msgid="5103447663504839312">"OK"</string>
-    <string name="usb_charging_notification_title" msgid="1674124518282666955">"Carregando este dispositivo via USB"</string>
+    <string name="usb_charging_notification_title" msgid="1674124518282666955">"Carregar dispositivo via USB"</string>
     <string name="usb_supplying_notification_title" msgid="5378546632408101811">"Carregando dispositivo conectado via USB"</string>
     <string name="usb_mtp_notification_title" msgid="1065989144124499810">"Transferência de arquivo via USB ativada"</string>
     <string name="usb_ptp_notification_title" msgid="5043437571863443281">"PTP via USB ativado"</string>
@@ -1907,6 +1907,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Fim de semana"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Evento"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Dormir"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Ativada"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Desativada"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> está silenciando alguns sons"</string>
@@ -2342,8 +2344,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Não é possível espelhar a tela"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Use outro cabo e tente de novo"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"O dispositivo está muito quente. Não será possível espelhar a tela até ele resfriar"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Talvez o cabo não tenha suporte a telas"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Seu cabo USB-C pode não se conectar a telas corretamente"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Tela dupla"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"A tela dupla está ativada"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está usando as duas telas para mostrar conteúdo"</string>
@@ -2360,18 +2360,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Layout do teclado definido como <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Toque para mudar."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Teclados físicos configurados"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Toque para conferir os teclados"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Particular"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Clone"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Trabalho"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Trabalho 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Trabalho 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Teste"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Público"</string>
 </resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 7b41180..b5b411e 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1907,6 +1907,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Weekend"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Eveniment"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Somn"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Activată"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Dezactivată"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> dezactivează anumite sunete"</string>
@@ -2342,8 +2344,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Nu se poate oglindi pe ecran"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Folosește alt cablu și încearcă din nou"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Dispozitivul este prea cald și nu poate oglindi ecranul până când nu se răcește"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Cablul poate să nu fie compatibil cu ecranele"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Cablul USB-C poate să nu se conecteze corespunzător la ecrane"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Funcția Dual screen este activată"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> folosește ambele ecrane pentru a afișa conținut"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 2f16db3..6948a1a 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1908,6 +1908,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Выходные"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Мероприятие"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Время сна"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Включено"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Отключено"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> приглушает некоторые звуки."</string>
@@ -2343,8 +2345,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Не удается дублировать на экран"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Используйте другой кабель или повторите попытку."</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Ваше устройство слишком сильно нагрелось. Когда оно остынет, вы снова сможете передавать изображение на другой экран."</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Кабель может не подходить для подключения к дисплеям"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Возможно, подключение дисплеев с помощью этого кабеля USB-C не поддерживается."</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Функция Dual Screen включена"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> использует оба экрана."</string>
@@ -2361,18 +2361,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Настроены раскладки клавиатуры для яз.: <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g> и др. Нажмите, чтобы изменить."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Физические клавиатуры настроены"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Нажмите, чтобы посмотреть подключенные клавиатуры."</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Личный"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Клон"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Рабочий"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Рабочий 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Рабочий 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Тестовый"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Совместный"</string>
 </resources>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index ac86d7b..7ed085d 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"සති අන්තය"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"සිදුවීම"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"නිදා ගනිමින්"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"ක්‍රියාත්මකයි"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"ක්‍රියාවිරහිතයි"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> සමහර ශබ්ද නිහඬ කරමින්"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"සංදර්ශකයට දර්පණය කළ නොහැක"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"වෙනස් කේබලයක් භාවිතා කර නැවත උත්සාහ කරන්න"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"ඔබේ උපාංගය ඉතා උණුසුම් වන අතර එය සිසිල් වන තෙක් සංදර්ශකය වෙත පිළිබිඹු කළ නොහැක"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"කේබලය සංදර්ශක වෙත සහාය නොදැක්විය හැක"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"ඔබේ USB-C කේබලයට සංදර්ශකවලට නිසි ලෙස සම්බන්ධ නොවිය හැක"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen සක්‍රීයයි"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"අන්තර්ගතය පෙන්වීමට <xliff:g id="APP_NAME">%1$s</xliff:g> සංදර්ශන දෙකම භාවිත කරයි"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"යතුරු පුවරුව <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g> ලෙස සකසා ඇත… වෙනස් කිරීමට තට්ටු කරන්න."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"භෞතික යතුරු පුවරුව වින්‍යාස කෙරිණි"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"යතුරු පුවරු බැලීමට තට්ටු කරන්න"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"පෞද්ගලික"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"ක්ලෝන කරන්න"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"කාර්යාලය"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"කාර්යාලය 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"කාර්යාලය 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"පරීක්ෂණය"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"වාර්ගික"</string>
 </resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index d1d7897..b6dd850 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1908,6 +1908,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Víkend"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Udalosť"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Spánok"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Zapnuté"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Vypnuté"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> vypína niektoré zvuky"</string>
@@ -2343,8 +2345,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Nedá sa zrkadliť do obrazovky"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Použite iný kábel a skúste znova"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Zariadenie je príliš horúce a nemôže zrkadliť na obrazovku, kým sa neochladí"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kábel nemusí podporovať obrazovky"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Kábel USB‑C sa nemusí dať správne pripojiť k obrazovkám"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Je zapnutá funkcia Dual Screen"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> zobrazuje obsah na oboch obrazovkách"</string>
@@ -2361,18 +2361,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Rozloženie klávesnice je nastavené na jazyky <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g> a <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Môžete to zmeniť klepnutím."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Fyzické klávesnice sú nakonfigurované"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Klávesnice si zobrazíte klepnutím"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Súkromný"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Klon"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Pracovný"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"2. pracovný"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"3. pracovný"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Testovací"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Spoločný"</string>
 </resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 19866f3..df7e614 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1908,6 +1908,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Konec tedna"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Dogodek"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Spanje"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Vklopljeno"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Izklopljeno"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> izklaplja nekatere zvoke"</string>
@@ -2343,8 +2345,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Ni mogoče zrcaliti zaslona"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Uporabite drug kabel in poskusite znova"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Naprava je pretopla in ne more zrcaliti v zaslon, dokler se ne ohladi"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kabel morda ne podpira zaslonov"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Kabel USB-C se morda ne more ustrezno povezati z zasloni."</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen je vklopljen"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> uporablja oba zaslona za prikaz vsebine."</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 2cd76fd..f84966b 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Fundjava"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Ngjarje"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Në gjumë"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Aktivizuar"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Çaktivizuar"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> po çaktivizon disa tinguj"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Nuk mund të pasqyrojë tek ekrani"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Përdor një kabllo tjetër dhe provo përsëri"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Pajisja është shumë e nxehtë dhe nuk mund të pasqyrojë në ekran derisa të ftohet"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kablloja nuk mund të mbështetë ekranet"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Kablloja jote USB-C mund të mos lidhet siç duhet me ekranet"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen është aktiv"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> po i përdor të dyja ekranet për të shfaqur përmbajtje"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Struktura e tastierës u caktua në: <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Trokit për ta ndryshuar."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Tastierat fizike u konfiguruan"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Trokit për të parë tastierat"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Privat"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Klon"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Puna"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Puna 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Puna 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"I përbashkët"</string>
 </resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 9e77bf6..f37fe05 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1907,6 +1907,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Викенд"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Догађај"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Спавање"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Укључено"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Искључено"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> искључује неке звуке"</string>
@@ -2342,8 +2344,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Пресликавање на екран није могуће"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Употребите други кабл и пробајте поново"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Уређај је превише загрејан, па не може да се пресликава на екран док се не охлади"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Кабл не подржава екране"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"USB-C кабл се не повезује правилно са екранима"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen је укључен"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> користи оба екрана за приказивање садржаја"</string>
@@ -2360,18 +2360,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Распоред тастатуре је подешен на <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Додирните да бисте променили."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Физичке тастатуре су конфигурисане"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Додирните да бисте видели тастатуре"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Приватно"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Клонирано"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Посао"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Посао 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Посао 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Тест"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Заједничко"</string>
 </resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index ab5bfca..cbba6d44 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"I helgen"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Händelse"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"När jag sover"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"På"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Av"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> stänger av vissa ljud"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Det går inte spegla till skärmen"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Använd en annan kabel och försök igen"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Enheten är för varm för att spegla skärmen. Vänta tills den har svalnat"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kabeln kanske inte har stöd för skärmar"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Det kanske inte går att ansluta skärmar korrekt med den här USB-C-kabeln"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen är på"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> använder båda skärmarna för att visa innehåll"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Tangentbordslayouten är inställd på <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g> … Tryck om du vill ändra."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Fysiska tangentbord har konfigurerats"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Tryck för att visa tangentbord"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Privat"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Klon"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Arbete"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Arbete 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Arbete 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Allmän"</string>
 </resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 61c0b17..ae9c3f8 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -23,13 +23,13 @@
     <string name="byteShort" msgid="202579285008794431">"B"</string>
     <string name="fileSizeSuffix" msgid="4233671691980131257">"<xliff:g id="UNIT">%2$s</xliff:g> <xliff:g id="NUMBER">%1$s</xliff:g>"</string>
     <string name="untitled" msgid="3381766946944136678">"&lt;Haina jina&gt;"</string>
-    <string name="emptyPhoneNumber" msgid="5812172618020360048">"(Hakuna nambari ya simu)"</string>
+    <string name="emptyPhoneNumber" msgid="5812172618020360048">"(Hakuna namba ya simu)"</string>
     <string name="unknownName" msgid="7078697621109055330">"Isiyojulikana"</string>
     <string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Ujumbe wa sauti"</string>
     <string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
     <string name="mmiError" msgid="2862759606579822246">"Tatizo la muunganisho au msimbo batili MMI."</string>
     <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Kipengele hakitumiki."</string>
-    <string name="mmiFdnError" msgid="3975490266767565852">"Ni matumizi yanayohusisha nambari za simu zilizobainishwa pekee yatakayowezekana."</string>
+    <string name="mmiFdnError" msgid="3975490266767565852">"Ni matumizi yanayohusisha namba za simu zilizobainishwa pekee yatakayowezekana."</string>
     <string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Haiwezi kubadilisha mipangilio ya kusambaza simu kutoka kwenye simu yako ukiwa unatumia mitandao mingine."</string>
     <string name="serviceEnabled" msgid="7549025003394765639">"Huduma iliwezeshwa"</string>
     <string name="serviceEnabledFor" msgid="1463104778656711613">"Huduma iliwezesha kwa:"</string>
@@ -41,8 +41,8 @@
     <string name="badPin" msgid="888372071306274355">"PIN ya awali uliyoingiza si sahihi."</string>
     <string name="badPuk" msgid="4232069163733147376">"PUK uliyoingiza si sahihi."</string>
     <string name="mismatchPin" msgid="2929611853228707473">"PIN ulizoingiza haziambatani."</string>
-    <string name="invalidPin" msgid="7542498253319440408">"Chapisha PIN ambayo ina nambari 4 hadi 8."</string>
-    <string name="invalidPuk" msgid="8831151490931907083">"Andika PUK ambayo ina urefu wa nambari 8 au zaidi."</string>
+    <string name="invalidPin" msgid="7542498253319440408">"Chapisha PIN ambayo ina namba 4 hadi 8."</string>
+    <string name="invalidPuk" msgid="8831151490931907083">"Andika PUK ambayo ina urefu wa namba 8 au zaidi."</string>
     <string name="needPuk" msgid="3503414069503752211">"SIM yako imefungwa kwa PUK. Andika msimbo wa PUK ili kuifungua."</string>
     <string name="needPuk2" msgid="3910763547447344963">"Andika PUK2 ili uondoe kizuizi kwenye SIM."</string>
     <string name="enablePin" msgid="2543771964137091212">"Imeshindwa, washa ufungaji wa SIM/RUIM."</string>
@@ -62,10 +62,10 @@
     <string name="PwdMmi" msgid="3360991257288638281">"Badilisho la nenosiri"</string>
     <string name="PinMmi" msgid="7133542099618330959">"Badilisha PIN"</string>
     <string name="CnipMmi" msgid="4897531155968151160">"Nambari ya kupiga iliyopo"</string>
-    <string name="CnirMmi" msgid="885292039284503036">"Kupiga nambari kumezuiwa"</string>
+    <string name="CnirMmi" msgid="885292039284503036">"Kupiga namba kumezuiwa"</string>
     <string name="ThreeWCMmi" msgid="2436550866139999411">"Upigaji simu kwa njia tatu"</string>
     <string name="RuacMmi" msgid="1876047385848991110">"Ukataaji wa simu zinazokera zisizohitajika"</string>
-    <string name="CndMmi" msgid="185136449405618437">"Kuonyeshwa kwa nambari inayopiga"</string>
+    <string name="CndMmi" msgid="185136449405618437">"Kuonyeshwa kwa namba inayopiga"</string>
     <string name="DndMmi" msgid="8797375819689129800">"Usinisumbue"</string>
     <string name="CLIRDefaultOnNextCallOn" msgid="4511621022859867988">"Chaguomsingi za ID ya mpigaji simu za kutozuia. Simu ifuatayo: Imezuiliwa"</string>
     <string name="CLIRDefaultOnNextCallOff" msgid="5036749051007098105">"Chaguomsingi za kitambulisho cha mpigaji simu huwa kuzuiwa. Simu ifuatayo: Haijazuiliwa"</string>
@@ -86,7 +86,7 @@
     <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Huduma ya kupiga simu za dharura haipatikani"</string>
     <string name="EmergencyCallWarningSummary" msgid="1194185880092805497">"Huwezi kupiga simu ya dharura kupitia Wi‑Fi"</string>
     <string name="notification_channel_network_alert" msgid="4788053066033851841">"Arifa"</string>
-    <string name="notification_channel_call_forward" msgid="8230490317314272406">"Kupeleka simu kwenye nambari nyingine"</string>
+    <string name="notification_channel_call_forward" msgid="8230490317314272406">"Kupeleka simu kwenye namba nyingine"</string>
     <string name="notification_channel_emergency_callback" msgid="54074839059123159">"Hali ya kupiga simu za dharura"</string>
     <string name="notification_channel_mobile_data_status" msgid="1941911162076442474">"Hali ya data ya mtandao wa simu"</string>
     <string name="notification_channel_sms" msgid="1243384981025535724">"Ujumbe wa SMS"</string>
@@ -336,7 +336,7 @@
     <string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"Kuwasha \'Chunguza kwa Kugusa\'"</string>
     <string name="capability_desc_canRequestTouchExploration" msgid="4394677060796752976">"Vipengee utakavyogusa vitatamkwa kwa sauti na unaweza kukagua skrini kwa kutumia ishara."</string>
     <string name="capability_title_canRequestFilterKeyEvents" msgid="2772371671541753254">"Kutambua maandishi unayocharaza"</string>
-    <string name="capability_desc_canRequestFilterKeyEvents" msgid="2381315802405773092">"Inajumuisha data binafsi kama vile nambari za kadi za mikopo na manenosiri."</string>
+    <string name="capability_desc_canRequestFilterKeyEvents" msgid="2381315802405773092">"Inajumuisha data binafsi kama vile namba za kadi za mikopo na manenosiri."</string>
     <string name="capability_title_canControlMagnification" msgid="7701572187333415795">"Kudhibiti ukuzaji kwenye skrini"</string>
     <string name="capability_desc_canControlMagnification" msgid="2206586716709254805">"Kudhibiti kiwango cha kukuza na nafasi kwenye skrini."</string>
     <string name="capability_title_canPerformGestures" msgid="9106545062106728987">"Tekeleza ishara"</string>
@@ -359,7 +359,7 @@
     <string name="permlab_uninstall_shortcut" msgid="295263654781900390">"ondoa njia za mikato"</string>
     <string name="permdesc_uninstall_shortcut" msgid="1924735350988629188">"Huruhusu programu kuondoa njia za mkato za Skrini ya kwanza bila mtumiaji kuingilia."</string>
     <string name="permlab_processOutgoingCalls" msgid="4075056020714266558">"panga upya simu zinazotoka"</string>
-    <string name="permdesc_processOutgoingCalls" msgid="7833149750590606334">"Huruhusu programu kuona nambari inayopigwa wakati simu inapigwa ikiwa na chaguo la kuelekeza simu kwenye nambari tofauti au kukata simu kabisa."</string>
+    <string name="permdesc_processOutgoingCalls" msgid="7833149750590606334">"Huruhusu programu kuona namba inayopigwa wakati simu inapigwa ikiwa na chaguo la kuelekeza simu kwenye namba tofauti au kukata simu kabisa."</string>
     <string name="permlab_answerPhoneCalls" msgid="4131324833663725855">"kujibu simu"</string>
     <string name="permdesc_answerPhoneCalls" msgid="894386681983116838">"Inaruhusu programu kujibu simu inayopigwa."</string>
     <string name="permlab_receiveSms" msgid="505961632050451881">"pokea ujumbe wa maandishi wa SMS"</string>
@@ -507,24 +507,24 @@
     <string name="permlab_vibrate" msgid="8596800035791962017">"Kudhibiti mtetemo"</string>
     <string name="permdesc_vibrate" msgid="8733343234582083721">"Inaruhusu programu kudhibiti kitingishi."</string>
     <string name="permdesc_vibrator_state" msgid="7050024956594170724">"Huruhusu programu kufikia hali ya kitetemeshaji."</string>
-    <string name="permlab_callPhone" msgid="1798582257194643320">"piga simu moja kwa moja kwa nambari za simu"</string>
-    <string name="permdesc_callPhone" msgid="7892422187827695656">"Huruhusu programu kupiga simu kiotomatiki. Hii huenda ikasababisha gharama au simu usizotarajia. Kumbuka, idhini hii hairuhusu programu kupiga simu kwa nambari za dharura. Programu hasidi zinaweza kusababisha utozwe pesa kwa kupiga simu bila wewe kuthibitisha, au kupiga nambari za watoa huduma, hatua ambayo husababisha simu zinazoingia kusambazwa kwa nambari nyingine kiotomatiki."</string>
+    <string name="permlab_callPhone" msgid="1798582257194643320">"piga simu moja kwa moja kwa namba za simu"</string>
+    <string name="permdesc_callPhone" msgid="7892422187827695656">"Huruhusu programu kupiga simu kiotomatiki. Hii huenda ikasababisha gharama au simu usizotarajia. Kumbuka, idhini hii hairuhusu programu kupiga simu kwa namba za dharura. Programu hasidi zinaweza kusababisha utozwe pesa kwa kupiga simu bila wewe kuthibitisha, au kupiga namba za watoa huduma, hatua ambayo husababisha simu zinazoingia kusambazwa kwa namba nyingine kiotomatiki."</string>
     <string name="permlab_accessImsCallService" msgid="442192920714863782">"fikia huduma ya simu ya IMS"</string>
     <string name="permdesc_accessImsCallService" msgid="6328551241649687162">"Huruhusu programu kutumia huduma ya IMS kupiga simu bila udhibiti wako."</string>
     <string name="permlab_readPhoneState" msgid="8138526903259297969">"kusoma hali na kitambulisho cha simu"</string>
-    <string name="permdesc_readPhoneState" msgid="7229063553502788058">"Huruhusu programu kufikia vipengele vya simu vilivyo kwenye kifaa. Idhini hii inaruhusu programu kutambua nambari ya simu na kifaa, kama kuna simu inayopigwa, na nambari ya mbali iliyounganishwa kwenye simu."</string>
+    <string name="permdesc_readPhoneState" msgid="7229063553502788058">"Huruhusu programu kufikia vipengele vya simu vilivyo kwenye kifaa. Idhini hii inaruhusu programu kutambua namba ya simu na kifaa, kama kuna simu inayopigwa, na namba ya mbali iliyounganishwa kwenye simu."</string>
     <string name="permlab_readBasicPhoneState" msgid="3214853233263871347">"kusoma utambulisho na hali ya msingi ya simu"</string>
     <string name="permdesc_readBasicPhoneState" msgid="828185691675460520">"Huruhusu programu kufikia vipengele vya msingi vya simu kwenye kifaa."</string>
     <string name="permlab_manageOwnCalls" msgid="9033349060307561370">"elekeza simu kupitia mfumo"</string>
     <string name="permdesc_manageOwnCalls" msgid="4431178362202142574">"Huruhusu programu kuelekeza simu zake kupitia mfumo ili kuboresha hali ya kupiga simu."</string>
     <string name="permlab_callCompanionApp" msgid="3654373653014126884">"kuona na kudhibiti simu kupitia mfumo."</string>
-    <string name="permdesc_callCompanionApp" msgid="8474168926184156261">"Inaruhusu programu ione na kudhibiti simu zinazoendelea kupigwa kwenye kifaa. Hii inajumuisha maelezo kama vile nambari za simu zinazopigwa na hali ya simu."</string>
+    <string name="permdesc_callCompanionApp" msgid="8474168926184156261">"Inaruhusu programu ione na kudhibiti simu zinazoendelea kupigwa kwenye kifaa. Hii inajumuisha maelezo kama vile namba za simu zinazopigwa na hali ya simu."</string>
     <string name="permlab_exemptFromAudioRecordRestrictions" msgid="1164725468350759486">"ondoa vikwazo vya kurekodi sauti"</string>
     <string name="permdesc_exemptFromAudioRecordRestrictions" msgid="2425117015896871976">"Ondolea programu vikwazo ili urekodi sauti."</string>
     <string name="permlab_acceptHandover" msgid="2925523073573116523">"endelea na simu kutoka programu nyingine"</string>
     <string name="permdesc_acceptHandovers" msgid="7129026180128626870">"Huruhusu programu kuendelea na simu ambayo ilianzishwa katika programu nyingine."</string>
-    <string name="permlab_readPhoneNumbers" msgid="5668704794723365628">"kusoma nambari za simu"</string>
-    <string name="permdesc_readPhoneNumbers" msgid="7368652482818338871">"Inaruhusu programu kufikia nambari za simu zilizo kwenye kifaa."</string>
+    <string name="permlab_readPhoneNumbers" msgid="5668704794723365628">"kusoma namba za simu"</string>
+    <string name="permdesc_readPhoneNumbers" msgid="7368652482818338871">"Inaruhusu programu kufikia namba za simu zilizo kwenye kifaa."</string>
     <string name="permlab_wakeLock" product="automotive" msgid="1904736682319375676">"kuweka skrini ya gari isijizime"</string>
     <string name="permlab_wakeLock" product="tablet" msgid="1527660973931694000">"zuia kompyuta ndogo dhidi ya kulala"</string>
     <string name="permlab_wakeLock" product="tv" msgid="2856941418123343518">"zuia kifaa chako cha Android TV kisiingie katika hali tuli"</string>
@@ -957,8 +957,8 @@
     <string name="sipAddressTypeWork" msgid="7873967986701216770">"Kazi"</string>
     <string name="sipAddressTypeOther" msgid="6317012577345187275">"Nyinginezo"</string>
     <string name="quick_contacts_not_available" msgid="1262709196045052223">"Hakuna programu iliyopatikana ili kuona anwani hii."</string>
-    <string name="keyguard_password_enter_pin_code" msgid="6401406801060956153">"Weka nambari ya PIN"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3112256684547584093">"Weka PUK na nambari mpya ya PIN"</string>
+    <string name="keyguard_password_enter_pin_code" msgid="6401406801060956153">"Weka namba ya PIN"</string>
+    <string name="keyguard_password_enter_puk_code" msgid="3112256684547584093">"Weka PUK na namba mpya ya PIN"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="2825313071899938305">"Msimbo wa PUK"</string>
     <string name="keyguard_password_enter_pin_prompt" msgid="5505434724229581207">"Nambari mpya ya PIN"</string>
     <string name="keyguard_password_entry_touch_hint" msgid="4032288032993261520"><font size="17">"Gusa ili uandike nenosiri"</font></string>
@@ -1482,7 +1482,7 @@
     <string name="ime_action_done" msgid="6299921014822891569">"Nimemaliza"</string>
     <string name="ime_action_previous" msgid="6548799326860401611">"Iliyotangulia"</string>
     <string name="ime_action_default" msgid="8265027027659800121">"Tekeleza"</string>
-    <string name="dial_number_using" msgid="6060769078933953531">"Piga nambari \n kwa kutumia <xliff:g id="NUMBER">%s</xliff:g>"</string>
+    <string name="dial_number_using" msgid="6060769078933953531">"Piga namba \n kwa kutumia <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="create_contact_using" msgid="6200708808003692594">"Unda anwani \n kwa kutumia <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="grant_credentials_permission_message_header" msgid="5365733888842570481">"Programu moja au zaidi zifuatazo zinaomba ruhusa ya kufikia akaunti yako, sasa na baadaye."</string>
     <string name="grant_credentials_permission_message_footer" msgid="1886710210516246461">"Unataka kuruhusu ombi hili?"</string>
@@ -1658,8 +1658,8 @@
     <string name="kg_pin_instructions" msgid="7355933174673539021">"Weka PIN"</string>
     <string name="kg_password_instructions" msgid="7179782578809398050">"Weka Nenosiri"</string>
     <string name="kg_puk_enter_puk_hint" msgid="6696187482616360994">"SIM sasa imelemazwa. Ingiza msimbo wa PUK ili kuendelea. Wasiliana na mtoa huduma kwa maelezo."</string>
-    <string name="kg_puk_enter_pin_hint" msgid="8190982314659429770">"Weka nambari yako ya PIN"</string>
-    <string name="kg_enter_confirm_pin_hint" msgid="6372557107414074580">"Thibitisha nambari ya PIN uliyoweka"</string>
+    <string name="kg_puk_enter_pin_hint" msgid="8190982314659429770">"Weka namba yako ya PIN"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="6372557107414074580">"Thibitisha namba ya PIN uliyoweka"</string>
     <string name="kg_sim_unlock_progress_dialog_message" msgid="5743634657721110967">"Inafungua SIM…"</string>
     <string name="kg_password_wrong_pin_code" msgid="9013856346870572451">"Nambari ya PIN uliyoweka si sahihi."</string>
     <string name="kg_invalid_sim_pin_hint" msgid="4821601451222564077">"Charaza PIN iliyo na tarakimu kati ya 4 na 8."</string>
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Wikendi"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Tukio"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Kulala"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Imewashwa"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Imezimwa"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> inazima baadhi ya sauti"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Imeshindwa kuakisi kwenye skrini"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Tumia kebo tofauti kisha ujaribu tena"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Kifaa chako kina joto sana, hakiwezi kuakisi skrini hadi joto lake lipungue"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Huenda kebo haioani na skrini"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Huenda kebo yako ya USB-C isiunganishwe vizuri na skrini"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual screen imewasha"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> inatumia skrini zote kuonyesha maudhui"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Muundo wa kibodi umewekwa kuwa <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Gusa ili ubadilishe."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Mipangilio ya kibodi halisi imewekwa"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Gusa ili uangalie kibodi"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Wa faragha"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Nakala"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Wa kazini"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Wa 2 wa Kazini"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Wa 3 wa Kazini"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Jaribio"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Unaoshirikiwa"</string>
 </resources>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index edf6c2d..cfa5c72 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"வார இறுதி"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"நிகழ்வு"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"உறக்கத்தில்"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"ஆன்"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"ஆஃப்"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> சில ஒலிகளை முடக்குகிறது"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"டிஸ்ப்ளேயில் பிரதிபலிக்க முடியவில்லை"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"வெவ்வேறு கேபிள்களைப் பயன்படுத்தி மீண்டும் முயலவும்"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"உங்கள் சாதனம் மிகவும் சூடாக இருப்பதால், அது குறையும் வரை காட்சியைப் பிரதிபலிக்க முடியாது"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"டிஸ்ப்ளேக்களைக் கேபிள் ஆதரிக்காமல் இருக்கக்கூடும்"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"டிஸ்ப்ளேக்களில் உங்கள் USB-C கேபிள் சரியாக இணைக்கப்படாமல் இருக்கக்கூடும்"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"இரட்டைத் திரை"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"இரட்டைத் திரை அம்சம் இயக்கத்தில் உள்ளது"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"உள்ளடக்கத்தைக் காட்டுவதற்கு இரண்டு டிஸ்ப்ளேக்களையும் <xliff:g id="APP_NAME">%1$s</xliff:g> பயன்படுத்துகிறது"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"கீபோர்டு தளவமைப்பு <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… ஆகிய மொழிகளில் அமைக்கப்பட்டது, மாற்ற தட்டவும்."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"கீபோர்டுகள் உள்ளமைக்கப்பட்டன"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"கீபோர்டுகளைப் பார்க்க தட்டவும்"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"தனிப்பட்டது"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"குளோன்"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"பணி"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"பணி 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"பணி 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"பரிசோதனை"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"பொது"</string>
 </resources>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index d862e2f..52d7539 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"వారాంతం"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"ఈవెంట్"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"నిద్రావస్థ"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"ఆన్‌లో ఉంది"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"ఆఫ్‌లో ఉంది"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> కొన్ని ధ్వనులను మ్యూట్ చేస్తోంది"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"డిస్‌ప్లే చేయడానికి మిర్రర్ చేయడం సాధ్యపడదు"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"వేరే కేబుల్‌ను ఉపయోగించి, మళ్లీ ట్రై చేయండి"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"మీ పరికరం చాలా వెచ్చగా ఉంది, అది చల్లబడే వరకు డిస్‌ప్లే చేయడానికి మిర్రర్ చేయడం సాధ్యపడదు"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"డిస్‌ప్లేలను కేబుల్ సపోర్ట్ చేయకపోవచ్చు"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"మీ USB-C కేబుల్, డిస్‌ప్లేలకు సరిగ్గా కనెక్ట్ కాకపోవచ్చు"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen ఆన్‌లో ఉంది"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"కంటెంట్‌ను చూపడం కోసం <xliff:g id="APP_NAME">%1$s</xliff:g> రెండు డిస్‌ప్లేలనూ ఉపయోగిస్తోంది"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"కీబోర్డ్ లేఅవుట్ <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>‌కు సెట్ చేయబడింది… మార్చడానికి ట్యాప్ చేయండి."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"ఫిజికల్ కీబోర్డ్‌లు కాన్ఫిగర్ చేయబడ్డాయి"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"కీబోర్డ్‌లను చూడటానికి ట్యాప్ చేయండి"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"ప్రైవేట్"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"క్లోన్ చేయండి"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"ఆఫీస్"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"ఆఫీస్ 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"ఆఫీస్ 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"పరీక్ష"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"కమ్యూనల్"</string>
 </resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index bda7e8a..759b6e4 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"สุดสัปดาห์"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"กิจกรรม"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"นอนหลับ"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"เปิด"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"ปิด"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> กำลังปิดเสียงบางรายการ"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"มิเรอร์ไปยังจอแสดงผลไม่ได้"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"โปรดใช้สายอื่นและลองอีกครั้ง"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"อุปกรณ์ร้อนเกินไปและไม่สามารถมิเรอร์ไปยังจอแสดงผลได้จนกว่าจะเย็นลง"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"สายสัญญาณอาจไม่รองรับจอแสดงผล"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"สาย USB-C อาจเชื่อมต่อกับจอแสดงผลอย่างไม่ถูกต้อง"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen เปิดอยู่"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> กำลังใช้จอแสดงผลทั้งสองจอเพื่อแสดงเนื้อหา"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"ตั้งค่ารูปแบบแป้นพิมพ์เป็นภาษา<xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… แตะเพื่อเปลี่ยน"</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"กำหนดค่าแป้นพิมพ์จริงแล้ว"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"แตะเพื่อดูแป้นพิมพ์"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"ส่วนตัว"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"โคลน"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"งาน"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"งาน 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"งาน 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"ทดสอบ"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"ส่วนกลาง"</string>
 </resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 53201ea..650b3fe 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Weekend"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Event"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Pag-sleep"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Naka-on"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Naka-off"</string>
     <string name="muted_by" msgid="91464083490094950">"Minu-mute ng <xliff:g id="THIRD_PARTY">%1$s</xliff:g> ang ilang tunog"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Hindi makapag-mirror sa display"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Gumamit ng ibang cable at subukan ulit"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Masyadong mainit ang iyong device at hindi ito makakapag-mirror sa display hanggang sa lumamig ito"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Posibleng hindi sinusuportahan ng cable ang mga display"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Posibleng hindi kumonekta nang maayos sa mga display ang iyong USB-C cable"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Naka-on ang dual screen"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"Ginagamit ng <xliff:g id="APP_NAME">%1$s</xliff:g> ang parehong display para magpakita ng content"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Naitakda ang layout ng keyboard sa <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… I-tap para baguhin."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Na-configure ang mga pisikal na keyboard"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"I-tap para tingnan ang mga keyboard"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Pribado"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"I-clone"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Trabaho"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Trabaho 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Trabaho 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Communal"</string>
 </resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index ee1168f..9e84fdd 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Hafta sonu"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Etkinlik"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Uyku"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Açık"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Kapalı"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> bazı sesleri kapatıyor"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Ekrana yansıtılamıyor"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Farklı kablo kullanarak tekrar deneyin"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Cihazınız çok ısındığı için soğuyana kadar ekrana yansıtılamaz"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kablo, ekranları desteklemeyebilir"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"USB-C kablonuz ekranlara doğru şekilde bağlanamayabilir"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen açık"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g>, içeriği göstermek için her iki ekranı da kullanıyor"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Klavye düzeni <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g> olarak ayarlandı… Değiştirmek için dokunun."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Fiziksel klavyeler yapılandırıldı"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Klavyeleri görüntülemek için dokunun"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Gizli"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Klon"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"İş"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"İş 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"İş 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Paylaşılan"</string>
 </resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index b1adf52..2772eb4 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1908,6 +1908,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"На вихідних"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Подія"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Під час сну"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Увімкнено"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Вимкнено"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> вимикає деякі звуки"</string>
@@ -2343,8 +2345,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Неможливо дублювати на дисплей"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Скористайтесь іншим кабелем і повторіть спробу"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Пристрій перегрівся й не зможе дублювати контент на дисплей, поки не охолоне"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Кабель може не підтримувати дисплеї"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Ваш кабель USB-C може не підключатися до дисплеїв належним чином"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual Screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Dual Screen увімкнено"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> використовує обидва екрани для показу контенту"</string>
@@ -2361,18 +2361,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Вибрано такі розкладки клавіатури: <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Натисніть, щоб змінити."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Фізичні клавіатури налаштовано"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Натисніть, щоб переглянути клавіатури"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Приватний профіль"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Копія профілю"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Робочий профіль"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Робочий профіль 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Робочий профіль 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Тестовий профіль"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Спільний профіль"</string>
 </resources>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 92fd266..0324697 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"ویک اینڈ"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"ایونٹ"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"سونا"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"آن ہے"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"آف ہے"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> کچھ آوازوں کو خاموش کر رہا ہے"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"ڈسپلے پر دو طرفہ مطابقت پذیری ممکن نہیں ہے"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"مختلف کیبل استعمال کریں اور دوبارہ کوشش کریں"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"آپ کا آلہ بہت گرم ہے اور جب تک یہ ٹھنڈا نہیں ہو جاتا اس وقت تک ڈسپلے میں عکس دو طرفہ مطابقت پذیر نہیں ہو سکتا"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"ہو سکتا ہے کہ کیبل ڈسپلیز کو سپورٹ نہ کرے"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"‏ہو سکتا ہے کہ آپ کی USB-C کیبل مناسب طریقے سے ڈسپلیز سے منسلک نہ ہو"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"دوہری اسکرین"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"دوہری اسکرین آن ہے"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"مواد دکھانے کیلئے <xliff:g id="APP_NAME">%1$s</xliff:g> دونوں ڈسپلیز استعمال کر رہی ہے"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"کی بورڈ لے آؤٹ <xliff:g id="LAYOUT_1">%1$s</xliff:g>، <xliff:g id="LAYOUT_2">%2$s</xliff:g>، <xliff:g id="LAYOUT_3">%3$s</xliff:g> پر سیٹ ہے… تبدیل کرنے کے لیے تھپتھپائیں۔"</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"فزیکل کی بورڈز کنفیگر کئے گئے"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"کی بورڈز دیکھنے کے لیے تھپتھپائیں"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"نجی"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"کلون"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"دفتری پروفائل"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"دوسری دفتری پروفائل"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"تیسری دفتری پروفائل"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"ٹیسٹ"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"کمیونل"</string>
 </resources>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 79d9f9d..1a83288 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Dam olish kunlari"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Tadbir"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Uyquda"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Yoniq"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Oʻchiq"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> ayrim tovushlarni ovozsiz qilgan"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Displeyga translatsiya qilinmaydi"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Boshqa kabel yordamida qayta urining"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Qurilma qizib ketdi va u sovimaguncha displeyni aks ettirmaydi"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Kabel displeylar bilan ishlamasligi mumkin"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"USB-C kabelingiz displeylarga toʻgʻri ulanmasligi mumkin"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Ikkita ekran"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Ikki ekranli rejim yoniq"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> kontentni ikkala ekranda chiqarmoqda"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Klaviatura terilmasi bunga sozlandi: <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Oʻzgartirish uchun ustiga bosing."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Tashqi klaviaturalar sozlandi"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Klaviaturalarni ochish uchun ustiga bosing"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Yopiq"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Nusxasini yaratish"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Ish"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Ish 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Ish 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Test"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Umumiy"</string>
 </resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 2ddf49f..a6c64ee 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Cuối tuần"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Sự kiện"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Ngủ"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Bật"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Tắt"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> đang tắt một số âm thanh"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Không chiếu được nội dung lên màn hình"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Hãy dùng một cáp khác rồi thử lại"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Thiết bị của bạn quá nóng nên không phản chiếu được nội dung lên màn hình. Hãy để thiết bị nguội bớt"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Có thể cáp không hỗ trợ màn hình"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Có thể cáp USB-C của bạn chưa kết nối đúng cách với màn hình"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Dual screen"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Chế độ Dual screen bật"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> đang dùng cả hai màn hình để thể hiện nội dung"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Đã thiết lập bố cục bàn phím thành <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Hãy nhấn để thay đổi."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Đã định cấu hình bàn phím vật lý"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Nhấn để xem bàn phím"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Riêng tư"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Sao chép"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Công việc"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Công việc 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Công việc 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Kiểm thử"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Dùng chung"</string>
 </resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index f3b6a39..4b64daf 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"周末"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"活动"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"睡眠"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"已启用"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"已停用"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g>正在将某些音效设为静音"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"无法镜像到显示屏"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"请改用其他数据线并重试"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"设备温度过高,在温度降下来之前,设备无法镜像到显示屏"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"数据线可能不支持显示屏"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"您的 USB-C 数据线可能没有正确连接到显示屏"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"双屏幕"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"双屏幕功能已开启"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g>正在使用双屏幕显示内容"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"键盘布局已设为<xliff:g id="LAYOUT_1">%1$s</xliff:g>、<xliff:g id="LAYOUT_2">%2$s</xliff:g>、<xliff:g id="LAYOUT_3">%3$s</xliff:g>…点按即可更改。"</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"已配置物理键盘"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"点按即可查看键盘"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"私密"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"克隆"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"工作"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"工作 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"工作 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"测试"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"共用"</string>
 </resources>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index bf72080..9610a38 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"週末"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"活動"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"睡眠"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"已開啟"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"已關閉"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g>正將某些音效設為靜音"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"無法將畫面鏡像投放至螢幕"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"請改用其他連接線,然後再試一次"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"裝置過熱,請等到降溫後再將畫面鏡像投射至螢幕"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"連接線可能不支援顯示屏"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"你的 USB-C 連接線可能未妥善連接顯示屏"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"雙螢幕"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"已開啟雙螢幕功能"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在使用雙螢幕顯示內容"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"鍵盤版面配置已設定為<xliff:g id="LAYOUT_1">%1$s</xliff:g>、<xliff:g id="LAYOUT_2">%2$s</xliff:g>、<xliff:g id="LAYOUT_3">%3$s</xliff:g>…輕按即可變更。"</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"已設定實體鍵盤"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"輕按即可查看鍵盤"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"私人"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"複製"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"工作"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"工作 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"工作 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"測試"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"共用"</string>
 </resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 1158cfd..6164be5 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"週末"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"活動"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"睡眠"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"已啟用"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"已停用"</string>
     <string name="muted_by" msgid="91464083490094950">"「<xliff:g id="THIRD_PARTY">%1$s</xliff:g>」正在關閉部分音效"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"無法將畫面鏡像投放至螢幕"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"請改用其他傳輸線,然後再試一次"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"裝置過熱,請等到降溫後再將畫面鏡像投放至螢幕"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"傳輸線可能不支援螢幕"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"USB-C 傳輸線可能未妥善連接到螢幕"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"雙螢幕"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"雙螢幕功能已啟用"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在使用雙螢幕顯示內容"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"鍵盤配置已設為<xliff:g id="LAYOUT_1">%1$s</xliff:g>、<xliff:g id="LAYOUT_2">%2$s</xliff:g>、<xliff:g id="LAYOUT_3">%3$s</xliff:g>…輕觸即可變更。"</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"已設定實體鍵盤"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"輕觸即可查看鍵盤"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"私人"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"副本"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"工作"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"工作 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"工作 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"測試"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"通用"</string>
 </resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index db7c253..f2a23bc 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1906,6 +1906,8 @@
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Ngempelasonto"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Umcimbi"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Ulele"</string>
+    <!-- no translation found for zen_mode_implicit_trigger_description (5714956693073007111) -->
+    <skip />
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Kuvuliwe"</string>
     <string name="zen_mode_implicit_deactivated" msgid="8688441768371501750">"Kuvaliwe"</string>
     <string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> ithulisa eminye imisindo"</string>
@@ -2341,8 +2343,6 @@
     <string name="connected_display_unavailable_notification_title" msgid="5265409360902073556">"Ayikwazi ukufanisa nesibonisi"</string>
     <string name="connected_display_unavailable_notification_content" msgid="3845903313751217516">"Sebenzisa ikhebuli ehlukile bese uyazama futhi"</string>
     <string name="connected_display_thermally_unavailable_notification_content" msgid="9205758199439955949">"Idivayisi yakho ifudumele kakhulu futhi ayikwazi ukwenza isibuko kusibonisi size siphole"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_title" msgid="8477183783847392465">"Ikhebuli ingase ingasekeli iziboniso"</string>
-    <string name="connected_display_cable_dont_support_displays_notification_content" msgid="8080498819171483973">"Ikhebuli yakho ye-USB-C ingase ingaxhumi kahle kuzibonisi"</string>
     <string name="concurrent_display_notification_name" msgid="1526911253558311131">"Isikrini esikabili"</string>
     <string name="concurrent_display_notification_active_title" msgid="4892473462327943673">"Isikrini esikabili sivuliwe"</string>
     <string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> isebenzisa zombili izibonisi ukukhombisa okuqukethwe"</string>
@@ -2359,18 +2359,11 @@
     <string name="keyboard_layout_notification_more_than_three_selected_message" msgid="1581834181578206937">"Uhlaka lwekhibhodi lusethelwe ku-<xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>, <xliff:g id="LAYOUT_3">%3$s</xliff:g>… Thepha ukuze ushintshe."</string>
     <string name="keyboard_layout_notification_multiple_selected_title" msgid="5242444914367024499">"Amakhibhodi aphathekayo amisiwe"</string>
     <string name="keyboard_layout_notification_multiple_selected_message" msgid="6576533454124419202">"Thepha ukuze ubuke amakhibhodi"</string>
-    <!-- no translation found for profile_label_private (6463418670715290696) -->
-    <skip />
-    <!-- no translation found for profile_label_clone (769106052210954285) -->
-    <skip />
-    <!-- no translation found for profile_label_work (3495359133038584618) -->
-    <skip />
-    <!-- no translation found for profile_label_work_2 (4691533661598632135) -->
-    <skip />
-    <!-- no translation found for profile_label_work_3 (4834572253956798917) -->
-    <skip />
-    <!-- no translation found for profile_label_test (9168641926186071947) -->
-    <skip />
-    <!-- no translation found for profile_label_communal (8743921499944800427) -->
-    <skip />
+    <string name="profile_label_private" msgid="6463418670715290696">"Okuyimfihlo"</string>
+    <string name="profile_label_clone" msgid="769106052210954285">"Yenza i-Clone"</string>
+    <string name="profile_label_work" msgid="3495359133038584618">"Umsebenzi"</string>
+    <string name="profile_label_work_2" msgid="4691533661598632135">"Umsebenzi 2"</string>
+    <string name="profile_label_work_3" msgid="4834572253956798917">"Umsebenzi 3"</string>
+    <string name="profile_label_test" msgid="9168641926186071947">"Hlola"</string>
+    <string name="profile_label_communal" msgid="8743921499944800427">"Okomphakathi"</string>
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 698c5ba..5cfb1a3 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3854,6 +3854,11 @@
         <!-- Specifies if an IME can only be used while a device is in VR mode or on a dedicated
              device -->
         <attr name="isVrOnly" format="boolean"/>
+        <!-- Specifies if an IME can only be used on a display created by a virtual device.
+             @see android.companion.virtual.VirtualDeviceParams.Builder#setInputMethodComponent
+             @hide @SystemApi -->
+        <!-- @FlaggedApi("android.companion.virtual.flags.vdm_custom_ime") -->
+        <attr name="isVirtualDeviceOnly" format="boolean"/>
         <attr name="__removed2" format="boolean" />
         <!-- Specifies whether the IME supports showing inline suggestions. -->
         <attr name="supportsInlineSuggestions" format="boolean" />
@@ -9797,6 +9802,17 @@
         <attr name="supportedTypes" format="reference" />
     </declare-styleable>
 
+    <!-- Use <code>tv-ad-service</code> as the root tag of the XML resource that describes a
+         android.media.tv.ad.TvAdService, which is referenced from its
+         android.media.tv.ad.TvAdService#SERVICE_META_DATA meta-data entry. Described here
+         are the attributes that can be included in that tag. -->
+    <declare-styleable name="TvAdService">
+        <!-- The advertisement types that the TV ad service supports.
+             Reference to a string array resource that describes the supported types,
+             e.g. linear, overlay. -->
+        <attr name="adServiceTypes" format="reference" />
+    </declare-styleable>
+
 
     <!-- Attributes that can be used with <code>rating-system-definition</code> tags inside of the
          XML resource that describes TV content rating of a {@link android.media.tv.TvInputService},
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index f8546b7..596cfe5 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -2515,6 +2515,10 @@
         <attr name="versionMajor" format="integer" />
         <!-- The SHA-256 digest of the SDK library signing certificate. -->
         <attr name="certDigest" format="string" />
+        <!-- Specify whether the SDK is optional. The default is false, false means app can be
+        installed even if the SDK library doesn't exist, and the SDK library can be uninstalled
+        when the app is still installed. -->
+        <attr name="optional" format="boolean" />
     </declare-styleable>
 
     <!-- The <code>static-library</code> tag declares that this apk is providing itself
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 1229453..d0de5f0 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1404,6 +1404,9 @@
     <!-- Shutdown if the battery temperature exceeds (this value * 0.1) Celsius. -->
     <integer name="config_shutdownBatteryTemperature">680</integer>
 
+    <!-- Shutdown if battery is critically low and the device is not powered. -->
+    <bool name="config_shutdownIfNoPower">true</bool>
+
     <!-- Display low battery warning when battery level dips to this value -->
     <integer name="config_lowBatteryWarningLevel">20</integer>
 
@@ -4252,6 +4255,9 @@
     -->
     <bool name="config_wallpaperTopApp">false</bool>
 
+    <!-- True if the device supports dVRR  -->
+    <bool name="config_supportsDvrr">false</bool>
+
     <!-- True if the device supports at least one form of multi-window.
          E.g. freeform, split-screen, picture-in-picture. -->
     <bool name="config_supportsMultiWindow">true</bool>
@@ -6853,4 +6859,7 @@
     <!-- Whether the View-based scroll haptic feedback implementation is enabled for
          {@link InputDevice#SOURCE_ROTARY_ENCODER}s. -->
     <bool name="config_viewBasedRotaryEncoderHapticsEnabled">false</bool>
+
+    <!-- Whether the media player is shown on the quick settings -->
+    <bool name="config_quickSettingsShowMediaPlayer">true</bool>
 </resources>
diff --git a/core/res/res/values/public-staging.xml b/core/res/res/values/public-staging.xml
index 4cd4f63..540967d 100644
--- a/core/res/res/values/public-staging.xml
+++ b/core/res/res/values/public-staging.xml
@@ -112,6 +112,13 @@
   <staging-public-group type="attr" first-id="0x01bd0000">
     <!-- @FlaggedApi("android.content.res.default_locale") -->
     <public name="defaultLocale"/>
+    <!-- @FlaggedApi("android.companion.virtual.flags.vdm_custom_ime")
+         @hide @SystemApi -->
+    <public name="isVirtualDeviceOnly"/>
+    <!-- @FlaggedApi("android.content.pm.sdk_lib_independence") -->
+    <public name="optional"/>
+    <!-- @FlaggedApi("android.media.tv.flags.enable_ad_service_fw") -->
+    <public name="adServiceTypes" />
   </staging-public-group>
 
   <staging-public-group type="id" first-id="0x01bc0000">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 73a7e42..d2fb9e1 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -5252,6 +5252,8 @@
     <!-- Zen mode - name of default automatic calendar time-based rule that is triggered every night (when sleeping). [CHAR LIMIT=40] -->
     <string name="zen_mode_default_every_night_name">Sleeping</string>
 
+    <!-- Zen mode - Trigger description of the rule, indicating which app owns it. [CHAR_LIMIT=100] -->
+    <string name="zen_mode_implicit_trigger_description">Managed by <xliff:g id="app_name">%1$s</xliff:g></string>
     <!-- Zen mode - Condition summary when a rule is activated due to a call to setInterruptionFilter(). [CHAR_LIMIT=NONE] -->
     <string name="zen_mode_implicit_activated">On</string>
     <!-- Zen mode - Condition summary when a rule is deactivated due to a call to setInterruptionFilter(). [CHAR_LIMIT=NONE] -->
@@ -6312,11 +6314,6 @@
     <!-- Content of connected display unavailable due to thermals notification. [CHAR LIMIT=NONE] -->
     <string name="connected_display_thermally_unavailable_notification_content">Your device is too warm and can\'t mirror to the display until it cools down</string>
 
-    <!-- Title of cable don't support displays notifications. [CHAR LIMIT=NONE] -->
-    <string name="connected_display_cable_dont_support_displays_notification_title">Cable may not support displays</string>
-    <!-- Content of cable don't support displays notification. [CHAR LIMIT=NONE] -->
-    <string name="connected_display_cable_dont_support_displays_notification_content">Your USB-C cable may not connect to displays properly</string>
-
     <!-- Name of concurrent display notifications. [CHAR LIMIT=NONE] -->
     <string name="concurrent_display_notification_name">Dual screen</string>
     <!-- Title of concurrent display active notification. [CHAR LIMIT=NONE] -->
@@ -6366,4 +6363,10 @@
     <!-- Communal profile label on a screen. This can be used as a tab label for this profile in tabbed views and can be used to represent the profile in sharing surfaces, etc. [CHAR LIMIT=20] -->
     <string name="profile_label_communal">Communal</string>
 
+    <!-- Notification message used when a notification's normal message contains sensitive information. -->
+    <!-- TODO b/301960090: replace with redacted message string and action title, when/if UX provides one -->
+    <!-- DO NOT TRANSLATE -->
+    <string name="redacted_notification_message"></string>
+    <!-- Notification action title used instead of a notification's normal title sensitive [CHAR_LIMIT=NOTIF_BODY] -->
+    <string name="redacted_notification_action_title"></string>
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 93aacdf..3894330 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -404,6 +404,7 @@
   <java-symbol type="bool" name="config_supportAudioSourceUnprocessed" />
   <java-symbol type="bool" name="config_freeformWindowManagement" />
   <java-symbol type="bool" name="config_supportsBubble" />
+  <java-symbol type="bool" name="config_supportsDvrr" />
   <java-symbol type="bool" name="config_supportsMultiWindow" />
   <java-symbol type="bool" name="config_supportsSplitScreenMultiWindow" />
   <java-symbol type="bool" name="config_supportsMultiDisplay" />
@@ -2094,6 +2095,7 @@
   <java-symbol type="integer" name="config_autoBrightnessShortTermModelTimeout" />
   <java-symbol type="integer" name="config_progressTimeoutFallbackHome" />
   <java-symbol type="integer" name="config_shutdownBatteryTemperature" />
+  <java-symbol type="bool" name="config_shutdownIfNoPower" />
   <java-symbol type="integer" name="config_undockedHdmiRotation" />
   <java-symbol type="integer" name="config_virtualKeyQuietTimeMillis" />
   <java-symbol type="integer" name="config_brightness_ramp_rate_fast" />
@@ -2585,6 +2587,7 @@
   <java-symbol type="string" name="zen_mode_default_weekends_name" />
   <java-symbol type="string" name="zen_mode_default_events_name" />
   <java-symbol type="string" name="zen_mode_default_every_night_name" />
+  <java-symbol type="string" name="zen_mode_implicit_trigger_description" />
   <java-symbol type="string" name="zen_mode_implicit_activated" />
   <java-symbol type="string" name="zen_mode_implicit_deactivated" />
   <java-symbol type="string" name="display_rotation_camera_compat_toast_after_rotation" />
@@ -5106,8 +5109,6 @@
   <java-symbol type="string" name="connected_display_unavailable_notification_title"/>
   <java-symbol type="string" name="connected_display_unavailable_notification_content"/>
   <java-symbol type="string" name="connected_display_thermally_unavailable_notification_content"/>
-  <java-symbol type="string" name="connected_display_cable_dont_support_displays_notification_title"/>
-  <java-symbol type="string" name="connected_display_cable_dont_support_displays_notification_content"/>
   <java-symbol type="string" name="concurrent_display_notification_name"/>
   <java-symbol type="string" name="concurrent_display_notification_active_title"/>
   <java-symbol type="string" name="concurrent_display_notification_active_content"/>
@@ -5157,6 +5158,10 @@
   <java-symbol type="string" name="keyboard_layout_notification_multiple_selected_title"/>
   <java-symbol type="string" name="keyboard_layout_notification_multiple_selected_message"/>
 
+  <!-- For redacted notifications -->
+  <java-symbol type="string" name="redacted_notification_message"/>
+  <java-symbol type="string" name="redacted_notification_action_title"/>
+
   <java-symbol type="bool" name="config_batteryStatsResetOnUnplugHighBatteryLevel" />
   <java-symbol type="bool" name="config_batteryStatsResetOnUnplugAfterSignificantCharge" />
   <java-symbol type="integer" name="config_defaultPowerStatsThrottlePeriodCpu" />
@@ -5299,4 +5304,6 @@
   <java-symbol type="array" name="config_tvExternalInputLoggingDeviceBrandNames" />
   <java-symbol type="bool" name="config_viewRotaryEncoderHapticScrollFedbackEnabled" />
   <java-symbol type="bool" name="config_viewBasedRotaryEncoderHapticsEnabled" />
+
+  <java-symbol type="bool" name="config_quickSettingsShowMediaPlayer" />
 </resources>
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index 37f592f..1a3ec27 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -7,19 +7,35 @@
     default_applicable_licenses: ["frameworks_base_license"],
 }
 
+filegroup {
+    name: "FrameworksCoreTests-aidl",
+    srcs: [
+        "src/**/I*.aidl",
+        "aidl/**/I*.aidl",
+    ],
+    visibility: ["//visibility:private"],
+}
+
+filegroup {
+    name: "FrameworksCoreTests-helpers",
+    srcs: [
+        "DisabledTestApp/src/**/*.java",
+        "EnabledTestApp/src/**/*.java",
+        "BinderProxyCountingTestApp/src/**/*.java",
+        "BinderProxyCountingTestService/src/**/*.java",
+        "BinderDeathRecipientHelperApp/src/**/*.java",
+    ],
+    visibility: ["//visibility:private"],
+}
+
 android_test {
     name: "FrameworksCoreTests",
 
     srcs: [
         "src/**/*.java",
         "src/**/*.kt",
-        "src/**/I*.aidl",
-        "DisabledTestApp/src/**/*.java",
-        "EnabledTestApp/src/**/*.java",
-        "BinderProxyCountingTestApp/src/**/*.java",
-        "BinderProxyCountingTestService/src/**/*.java",
-        "BinderDeathRecipientHelperApp/src/**/*.java",
-        "aidl/**/I*.aidl",
+        ":FrameworksCoreTests-aidl",
+        ":FrameworksCoreTests-helpers",
         ":FrameworksCoreTestDoubles-sources",
     ],
 
@@ -167,12 +183,39 @@
 
 android_ravenwood_test {
     name: "FrameworksCoreTestsRavenwood",
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+    ],
     static_libs: [
+        "core-test-rules", // for libcore.dalvik.system.CloseGuardSupport
+        "androidx.core_core",
         "androidx.annotation_annotation",
         "androidx.test.rules",
+        "androidx.test.ext.junit",
+        "androidx.test.uiautomator_uiautomator",
+        "compatibility-device-util-axt",
+        "flag-junit",
+        "mockito_ravenwood",
+        "platform-test-annotations",
+        "flag-junit",
+        "testng",
     ],
     srcs: [
-        "src/android/os/FileUtilsTest.java",
+        "src/android/os/**/*.java",
+        "src/com/android/internal/os/**/*.java",
+        "src/android/util/**/*.java",
+        "src/com/android/internal/os/LongArrayMultiStateCounterTest.java",
+        "src/com/android/internal/util/**/*.java",
+        "src/com/android/internal/power/EnergyConsumerStatsTest.java",
+        ":FrameworksCoreTests{.aapt.srcjar}",
+        ":FrameworksCoreTests-aidl",
+        ":FrameworksCoreTests-helpers",
+        ":FrameworksCoreTestDoubles-sources",
     ],
+    aidl: {
+        generate_get_transaction_name: true,
+        local_include_dirs: ["aidl"],
+    },
     auto_gen_config: true,
 }
diff --git a/core/tests/coretests/res/xml/ime_meta_virtual_device_only.xml b/core/tests/coretests/res/xml/ime_meta_virtual_device_only.xml
new file mode 100644
index 0000000..1905365
--- /dev/null
+++ b/core/tests/coretests/res/xml/ime_meta_virtual_device_only.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+    Copyright (C) 2023 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+
+<input-method
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:settingsActivity="com.android.inputmethod.latin.settings.SettingsActivity"
+    android:isVirtualDeviceOnly="true">
+</input-method>
diff --git a/core/tests/coretests/src/android/app/AutomaticZenRuleTest.java b/core/tests/coretests/src/android/app/AutomaticZenRuleTest.java
index ba2ea88..1925588 100644
--- a/core/tests/coretests/src/android/app/AutomaticZenRuleTest.java
+++ b/core/tests/coretests/src/android/app/AutomaticZenRuleTest.java
@@ -19,15 +19,20 @@
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.fail;
 
+import static org.junit.Assert.assertThrows;
+
 import android.content.ComponentName;
 import android.net.Uri;
 import android.os.Parcel;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 
 import com.google.common.base.Strings;
 
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -38,6 +43,9 @@
 public class AutomaticZenRuleTest {
     private static final String CLASS = "android.app.AutomaticZenRule";
 
+    @Rule
+    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
     @Test
     public void testLongFields_inConstructor() {
         String longString = Strings.repeat("A", 65536);
@@ -100,6 +108,7 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_MODES_API)
     public void testLongInputsFromParcel() {
         // Create a rule with long fields, set directly via reflection so that we can confirm that
         // a rule with too-long fields that comes in via a parcel has its fields truncated directly.
@@ -152,6 +161,69 @@
                 fromParcel.getOwner().getPackageName().length());
         assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
                 fromParcel.getOwner().getClassName().length());
-        assertEquals(AutomaticZenRule.MAX_DESC_LENGTH, rule.getTriggerDescription().length());
+        assertEquals(AutomaticZenRule.MAX_DESC_LENGTH, fromParcel.getTriggerDescription().length());
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_MODES_API)
+    public void builderConstructor_nullInputs_throws() {
+        assertThrows(NullPointerException.class,
+                () -> new AutomaticZenRule.Builder(null, Uri.parse("condition")));
+        assertThrows(NullPointerException.class,
+                () -> new AutomaticZenRule.Builder("name", null));
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_MODES_API)
+    public void validate_builderWithValidType_succeeds() throws Exception {
+        AutomaticZenRule rule = new AutomaticZenRule.Builder("rule", Uri.parse("uri"))
+                .setType(AutomaticZenRule.TYPE_BEDTIME)
+                .build();
+        rule.validate(); // No exception.
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_MODES_API)
+    public void validate_builderWithoutType_succeeds() throws Exception {
+        AutomaticZenRule rule = new AutomaticZenRule.Builder("rule", Uri.parse("uri")).build();
+        rule.validate(); // No exception.
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_MODES_API)
+    public void validate_constructorWithoutType_succeeds() throws Exception {
+        AutomaticZenRule rule = new AutomaticZenRule("rule", new ComponentName("pkg", "cps"),
+                new ComponentName("pkg", "activity"), Uri.parse("condition"), null,
+                NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+        rule.validate(); // No exception.
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_MODES_API)
+    public void validate_invalidType_throws() throws Exception {
+        AutomaticZenRule rule = new AutomaticZenRule.Builder("rule", Uri.parse("uri")).build();
+
+        // Set the field via reflection.
+        Field typeField = AutomaticZenRule.class.getDeclaredField("mType");
+        typeField.setAccessible(true);
+        typeField.set(rule, 100);
+
+        assertThrows(IllegalArgumentException.class, rule::validate);
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_MODES_API)
+    public void setType_invalidType_throws() {
+        AutomaticZenRule rule = new AutomaticZenRule.Builder("rule", Uri.parse("uri")).build();
+
+        assertThrows(IllegalArgumentException.class, () -> rule.setType(100));
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_MODES_API)
+    public void setTypeBuilder_invalidType_throws() {
+        AutomaticZenRule.Builder builder = new AutomaticZenRule.Builder("rule", Uri.parse("uri"));
+
+        assertThrows(IllegalArgumentException.class, () -> builder.setType(100));
     }
 }
diff --git a/core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java b/core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java
index 3768063..cd6abdd 100644
--- a/core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java
+++ b/core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java
@@ -20,9 +20,13 @@
 import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertSame;
 
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
+
 import androidx.test.filters.SmallTest;
 
 import org.junit.After;
+import org.junit.Rule;
 import org.junit.Test;
 
 /**
@@ -35,7 +39,10 @@
  *  atest FrameworksCoreTests:PropertyInvalidatedCacheTests
  */
 @SmallTest
+@IgnoreUnderRavenwood(blockedBy = PropertyInvalidatedCache.class)
 public class PropertyInvalidatedCacheTests {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
 
     // Configuration for creating caches
     private static final String MODULE = PropertyInvalidatedCache.MODULE_TEST;
diff --git a/core/tests/coretests/src/android/os/AidlTest.java b/core/tests/coretests/src/android/os/AidlTest.java
index d0c3470..006828f 100644
--- a/core/tests/coretests/src/android/os/AidlTest.java
+++ b/core/tests/coretests/src/android/os/AidlTest.java
@@ -16,23 +16,36 @@
 
 package android.os;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
+
 import androidx.test.filters.SmallTest;
 
 import com.google.android.collect.Lists;
 
-import junit.framework.TestCase;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
 
 import java.util.List;
 
-public class AidlTest extends TestCase {
+@IgnoreUnderRavenwood(blockedBy = Parcel.class)
+public class AidlTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
 
     private IAidlTest mRemote;
     private AidlObject mLocal;
     private NonAutoGeneratedObject mNonAutoGenerated;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @Before
+    public void setUp() throws Exception {
         mLocal = new AidlObject();
         mRemote = IAidlTest.Stub.asInterface(mLocal);
         mNonAutoGenerated = new NonAutoGeneratedObject("NonAutoGeneratedObject");
@@ -212,12 +225,14 @@
         }
     }
 
+    @Test
     @SmallTest
     public void testInt() throws Exception {
         int result = mRemote.intMethod(42);
         assertEquals(42, result);
     }
 
+    @Test
     @SmallTest
     public void testParcelableIn() throws Exception {
         TestParcelable arg = new TestParcelable(43, "hi");
@@ -228,6 +243,7 @@
         assertEquals(44, result.mAnInt);
     }
 
+    @Test
     @SmallTest
     public void testParcelableOut() throws Exception {
         TestParcelable arg = new TestParcelable(43, "hi");
@@ -236,6 +252,7 @@
         assertEquals(44, arg.mAnInt);
     }
 
+    @Test
     @SmallTest
     public void testParcelableInOut() throws Exception {
         TestParcelable arg = new TestParcelable(43, "hi");
@@ -244,6 +261,7 @@
         assertEquals(44, arg.mAnInt);
     }
 
+    @Test
     @SmallTest
     public void testListParcelableLonger() throws Exception {
         List<TestParcelable> list = Lists.newArrayList();
@@ -268,6 +286,7 @@
         assertNotSame(list.get(1), list.get(2));
     }
 
+    @Test
     @SmallTest
     public void testListParcelableShorter() throws Exception {
         List<TestParcelable> list = Lists.newArrayList();
@@ -290,6 +309,7 @@
         assertNotSame(list.get(0), list.get(1));
     }
 
+    @Test
     @SmallTest
     public void testArrays() throws Exception {
         // boolean
@@ -363,14 +383,14 @@
         float[] fr = mRemote.floatArray(f0, f1, f2);
 
         assertEquals(1, fr.length);
-        assertEquals(90.1f, fr[0]);
+        assertEquals(90.1f, fr[0], 0.0f);
 
-        assertEquals(90.1f, f1[0]);
+        assertEquals(90.1f, f1[0], 0.0f);
         assertEquals(0f, f1[1], 0.0f);
 
-        assertEquals(90.1f, f2[0]);
-        assertEquals(90.5f, f2[1]);
-        assertEquals(90.6f, f2[2]);
+        assertEquals(90.1f, f2[0], 0.0f);
+        assertEquals(90.5f, f2[1], 0.0f);
+        assertEquals(90.6f, f2[2], 0.0f);
 
         // double
         double[] d0 = new double[]{100.1};
@@ -379,14 +399,14 @@
         double[] dr = mRemote.doubleArray(d0, d1, d2);
 
         assertEquals(1, dr.length);
-        assertEquals(100.1, dr[0]);
+        assertEquals(100.1, dr[0], 0.0);
 
-        assertEquals(100.1, d1[0]);
+        assertEquals(100.1, d1[0], 0.0);
         assertEquals(0, d1[1], 0.0);
 
-        assertEquals(100.1, d2[0]);
-        assertEquals(100.5, d2[1]);
-        assertEquals(100.6, d2[2]);
+        assertEquals(100.1, d2[0], 0.0);
+        assertEquals(100.5, d2[1], 0.0);
+        assertEquals(100.6, d2[2], 0.0);
 
         // String
         String[] s0 = new String[]{"s0[0]"};
@@ -405,6 +425,7 @@
         assertEquals("s2[2]", s2[2]);
     }
 
+    @Test
     @SmallTest
     public void testVoidSecurityException() throws Exception {
         boolean good = false;
@@ -416,6 +437,7 @@
         assertEquals(good, true);
     }
 
+    @Test
     @SmallTest
     public void testIntSecurityException() throws Exception {
         boolean good = false;
@@ -427,6 +449,7 @@
         assertEquals(good, true);
     }
 
+    @Test
     @SmallTest
     public void testGetTransactionNameAutoGenerated() throws Exception {
         assertEquals(15, mLocal.getMaxTransactionId());
@@ -446,6 +469,7 @@
                 mLocal.getTransactionTraceName(IAidlTest.Stub.TRANSACTION_parcelableIn));
     }
 
+    @Test
     @SmallTest
     public void testGetTransactionNameNonAutoGenerated() throws Exception {
         assertEquals(0, mNonAutoGenerated.getMaxTransactionId());
diff --git a/core/tests/coretests/src/android/os/BinderDeathRecipientTest.java b/core/tests/coretests/src/android/os/BinderDeathRecipientTest.java
index 2cce43f..eff52f0 100644
--- a/core/tests/coretests/src/android/os/BinderDeathRecipientTest.java
+++ b/core/tests/coretests/src/android/os/BinderDeathRecipientTest.java
@@ -25,6 +25,8 @@
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.util.ArraySet;
 import android.util.Log;
 import android.util.Pair;
@@ -36,6 +38,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -52,6 +55,7 @@
  * Tests functionality of {@link android.os.IBinder.DeathRecipient} callbacks.
  */
 @RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = ActivityManager.class)
 public class BinderDeathRecipientTest {
     private static final String TAG = BinderDeathRecipientTest.class.getSimpleName();
     private static final String TEST_PACKAGE_NAME_1 =
@@ -59,6 +63,9 @@
     private static final String TEST_PACKAGE_NAME_2 =
             "com.android.frameworks.coretests.bdr_helper_app2";
 
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     private Context mContext;
     private Handler mHandler;
     private ActivityManager mActivityManager;
diff --git a/core/tests/coretests/src/android/os/BinderProxyCountingTest.java b/core/tests/coretests/src/android/os/BinderProxyCountingTest.java
index 2089c6c..bcd9521 100644
--- a/core/tests/coretests/src/android/os/BinderProxyCountingTest.java
+++ b/core/tests/coretests/src/android/os/BinderProxyCountingTest.java
@@ -24,6 +24,8 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.util.Log;
 
 import androidx.test.InstrumentationRegistry;
@@ -35,7 +37,8 @@
 import com.android.frameworks.coretests.aidl.IBpcTestAppCmdService;
 import com.android.frameworks.coretests.aidl.IBpcTestServiceCmdService;
 
-import org.junit.BeforeClass;
+import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -71,6 +74,7 @@
  */
 @LargeTest
 @RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = ActivityManager.class)
 public class BinderProxyCountingTest {
     private static final String TAG = BinderProxyCountingTest.class.getSimpleName();
 
@@ -107,11 +111,14 @@
     };
     private static int sTestPkgUid;
 
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     /**
      * Setup any common data for the upcoming tests.
      */
-    @BeforeClass
-    public static void setUpOnce() throws Exception {
+    @Before
+    public void setUp() throws Exception {
         sContext = InstrumentationRegistry.getContext();
         sTestPkgUid = sContext.getPackageManager().getPackageUid(TEST_APP_PKG, 0);
         ((ActivityManager) sContext.getSystemService(Context.ACTIVITY_SERVICE)).killUid(sTestPkgUid,
diff --git a/core/tests/coretests/src/android/os/BinderProxyTest.java b/core/tests/coretests/src/android/os/BinderProxyTest.java
index 3567d17..a903ed9 100644
--- a/core/tests/coretests/src/android/os/BinderProxyTest.java
+++ b/core/tests/coretests/src/android/os/BinderProxyTest.java
@@ -16,19 +16,34 @@
 
 package android.os;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
 import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
-import android.test.AndroidTestCase;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.MediumTest;
 
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
-public class BinderProxyTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = PowerManager.class)
+public class BinderProxyTest {
     private static class CountingListener implements Binder.ProxyTransactListener {
         int mStartedCount;
         int mEndedCount;
@@ -43,17 +58,22 @@
         }
     };
 
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
+    private Context mContext;
     private PowerManager mPowerManager;
 
     /**
      * Setup any common data for the upcoming tests.
      */
-    @Override
+    @Before
     public void setUp() throws Exception {
-        super.setUp();
+        mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
         mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
     }
 
+    @Test
     @MediumTest
     public void testNoListener() throws Exception {
         CountingListener listener = new CountingListener();
@@ -66,6 +86,7 @@
         assertEquals(0, listener.mEndedCount);
     }
 
+    @Test
     @MediumTest
     public void testListener() throws Exception {
         CountingListener listener = new CountingListener();
@@ -77,6 +98,7 @@
         assertEquals(1, listener.mEndedCount);
     }
 
+    @Test
     @MediumTest
     public void testSessionPropagated() throws Exception {
         Binder.setProxyTransactListener(new Binder.ProxyTransactListener() {
@@ -95,6 +117,7 @@
 
     private IBinder mRemoteBinder = null;
 
+    @Test
     @MediumTest
     public void testGetExtension() throws Exception {
         final CountDownLatch bindLatch = new CountDownLatch(1);
diff --git a/core/tests/coretests/src/android/os/BinderTest.java b/core/tests/coretests/src/android/os/BinderTest.java
index 02f8790..6c8b69f 100644
--- a/core/tests/coretests/src/android/os/BinderTest.java
+++ b/core/tests/coretests/src/android/os/BinderTest.java
@@ -16,21 +16,35 @@
 
 package android.os;
 
-import androidx.test.filters.SmallTest;
-
-import junit.framework.TestCase;
-
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
 import static org.testng.Assert.assertThrows;
 
-public class BinderTest extends TestCase {
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+@IgnoreUnderRavenwood(blockedBy = WorkSource.class)
+public class BinderTest {
     private static final int UID = 100;
 
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
+    @Test
     @SmallTest
     public void testSetWorkSource() throws Exception {
         Binder.setCallingWorkSourceUid(UID);
         assertEquals(UID, Binder.getCallingWorkSourceUid());
     }
 
+    @Test
     @SmallTest
     public void testClearWorkSource() throws Exception {
         Binder.setCallingWorkSourceUid(UID);
@@ -38,6 +52,7 @@
         assertEquals(-1, Binder.getCallingWorkSourceUid());
     }
 
+    @Test
     @SmallTest
     public void testRestoreWorkSource() throws Exception {
         Binder.setCallingWorkSourceUid(UID);
@@ -46,11 +61,13 @@
         assertEquals(UID, Binder.getCallingWorkSourceUid());
     }
 
+    @Test
     @SmallTest
     public void testGetCallingUidOrThrow_throws() throws Exception {
         assertThrows(IllegalStateException.class, () -> Binder.getCallingUidOrThrow());
     }
 
+    @Test
     @SmallTest
     public void testGetExtension() throws Exception {
         Binder binder = new Binder();
diff --git a/core/tests/coretests/src/android/os/BinderThreadPriorityTest.java b/core/tests/coretests/src/android/os/BinderThreadPriorityTest.java
index 48c9df6..4172bff 100644
--- a/core/tests/coretests/src/android/os/BinderThreadPriorityTest.java
+++ b/core/tests/coretests/src/android/os/BinderThreadPriorityTest.java
@@ -16,21 +16,42 @@
 
 package android.os;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import android.app.ActivityManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
-import android.test.AndroidTestCase;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.util.Log;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import java.io.File;
 import java.io.IOException;
 
 /**
  * Test whether Binder calls inherit thread priorities correctly.
  */
-public class BinderThreadPriorityTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = ActivityManager.class)
+public class BinderThreadPriorityTest {
     private static final String TAG = "BinderThreadPriorityTest";
+
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
+    private Context mContext;
     private IBinderThreadPriorityService mService;
     private int mSavedPriority;
 
@@ -55,12 +76,11 @@
         private static void fail() { throw new RuntimeException("unimplemented"); }
     }
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        getContext().bindService(
-                new Intent(getContext(), BinderThreadPriorityService.class),
+    @Before
+    public void setUp() throws Exception {
+        mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+        mContext.bindService(
+                new Intent(mContext, BinderThreadPriorityService.class),
                 mConnection, Context.BIND_AUTO_CREATE);
 
         synchronized (this) {
@@ -80,8 +100,8 @@
         Log.i(TAG, "Saved priority: " + mSavedPriority);
     }
 
-    @Override
-    protected void tearDown() throws Exception {
+    @After
+    public void tearDown() throws Exception {
         // HACK -- see bug 2665914 -- setThreadPriority() doesn't always set the
         // scheduler group reliably unless we start out with background priority.
         Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
@@ -89,8 +109,7 @@
         assertEquals(mSavedPriority, Process.getThreadPriority(Process.myTid()));
         assertEquals(expectedSchedulerGroup(mSavedPriority), getSchedulerGroup());
 
-        getContext().unbindService(mConnection);
-        super.tearDown();
+        mContext.unbindService(mConnection);
     }
 
     public static String getSchedulerGroup() {
@@ -111,6 +130,7 @@
         return "/";
     }
 
+    @Test
     public void testPassPriorityToService() throws Exception {
         for (int prio = 19; prio >= -20; prio--) {
             Process.setThreadPriority(prio);
@@ -125,6 +145,7 @@
         }
     }
 
+    @Test
     public void testCallBackFromServiceWithPriority() throws Exception {
         for (int prio = -20; prio <= 19; prio++) {
             final int expected = prio;
diff --git a/core/tests/coretests/src/android/os/BinderWorkSourceTest.java b/core/tests/coretests/src/android/os/BinderWorkSourceTest.java
index b14c88f..552066c 100644
--- a/core/tests/coretests/src/android/os/BinderWorkSourceTest.java
+++ b/core/tests/coretests/src/android/os/BinderWorkSourceTest.java
@@ -19,11 +19,14 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 
+import android.app.ActivityManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
 import android.platform.test.annotations.Presubmit;
+import android.platform.test.ravenwood.RavenwoodRule;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.LargeTest;
@@ -33,6 +36,7 @@
 import org.junit.After;
 import org.junit.Before;
 import org.junit.BeforeClass;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -42,12 +46,16 @@
 @LargeTest
 @Presubmit
 @RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = ActivityManager.class)
 public class BinderWorkSourceTest {
     private static Context sContext;
     private static final int UID = 100;
     private static final int SECOND_UID = 200;
     private static final int UID_NONE = ThreadLocalWorkSource.UID_NONE;
 
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     private IBinderWorkSourceService mService;
     private IBinderWorkSourceNestedService mNestedService;
 
@@ -71,13 +79,9 @@
         }
     };
 
-    @BeforeClass
-    public static void setUpOnce() throws Exception {
-        sContext = InstrumentationRegistry.getContext();
-    }
-
     @Before
     public void setUp() throws Exception {
+        sContext = InstrumentationRegistry.getContext();
         sContext.bindService(
                 new Intent(sContext, BinderWorkSourceService.class),
                 mConnection, Context.BIND_AUTO_CREATE);
diff --git a/core/tests/coretests/src/android/os/BroadcasterTest.java b/core/tests/coretests/src/android/os/BroadcasterTest.java
index b4c47af9..7829457 100644
--- a/core/tests/coretests/src/android/os/BroadcasterTest.java
+++ b/core/tests/coretests/src/android/os/BroadcasterTest.java
@@ -16,16 +16,26 @@
 
 package android.os;
 
+import android.platform.test.ravenwood.RavenwoodRule;
+
 import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
 
-import junit.framework.TestCase;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
-public class BroadcasterTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+public class BroadcasterTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     private static final int MESSAGE_A = 23234;
     private static final int MESSAGE_B = 3;
     private static final int MESSAGE_C = 14;
     private static final int MESSAGE_D = 95;
 
+    @Test
     @MediumTest
     public void test1() throws Exception {
         /*
@@ -103,6 +113,7 @@
         }
     }
 
+    @Test
     @MediumTest
     public void test2() throws Exception {
         /*
@@ -112,6 +123,7 @@
         tester.doTest(1000);
     }
 
+    @Test
     @MediumTest
     public void test3() throws Exception {
         /*
@@ -121,6 +133,7 @@
         tester.doTest(1000);
     }
 
+    @Test
     @MediumTest
     public void test4() throws Exception {
         /*
@@ -156,6 +169,7 @@
         tester.doTest(1000);
     }
 
+    @Test
     @MediumTest
     public void test5() throws Exception {
         /*
@@ -191,6 +205,7 @@
         tester.doTest(1000);
     }
 
+    @Test
     @MediumTest
     public void test6() throws Exception {
         /*
diff --git a/core/tests/coretests/src/android/os/BuildTest.java b/core/tests/coretests/src/android/os/BuildTest.java
index 2295eb9..3162e6d 100644
--- a/core/tests/coretests/src/android/os/BuildTest.java
+++ b/core/tests/coretests/src/android/os/BuildTest.java
@@ -16,19 +16,37 @@
 
 package android.os;
 
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.flag.junit.SetFlagsRule;
+import android.platform.test.ravenwood.RavenwoodRule;
+
 import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import junit.framework.Assert;
-import junit.framework.TestCase;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 /**
  * Provides test cases for android.os.Build and, in turn, many of the
  * system properties set by the build system.
  */
-public class BuildTest extends TestCase {
-
+@RunWith(AndroidJUnit4.class)
+public class BuildTest {
     private static final String TAG = "BuildTest";
 
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
+    @Rule
+    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
     /**
      * Asserts that a String is non-null and non-empty.  If it is not,
      * an AssertionFailedError is thrown with the given message.
@@ -50,7 +68,9 @@
     /**
      * Asserts that all android.os.Build fields are non-empty and/or in a valid range.
      */
+    @Test
     @SmallTest
+    @IgnoreUnderRavenwood(blockedBy = Build.class)
     public void testBuildFields() throws Exception {
         assertNotEmpty("ID", Build.ID);
         assertNotEmpty("DISPLAY", Build.DISPLAY);
@@ -72,4 +92,16 @@
         // (e.g., must be a C identifier, must be a valid filename, must not contain any spaces)
         // add tests for them.
     }
+
+    @Test
+    public void testFlagEnabled() throws Exception {
+        mSetFlagsRule.enableFlags(Flags.FLAG_ANDROID_OS_BUILD_VANILLA_ICE_CREAM);
+        assertTrue(Flags.androidOsBuildVanillaIceCream());
+    }
+
+    @Test
+    public void testFlagDisabled() throws Exception {
+        mSetFlagsRule.disableFlags(Flags.FLAG_ANDROID_OS_BUILD_VANILLA_ICE_CREAM);
+        assertFalse(Flags.androidOsBuildVanillaIceCream());
+    }
 }
diff --git a/core/tests/coretests/src/android/os/BundleTest.java b/core/tests/coretests/src/android/os/BundleTest.java
index a3bda8b..e7b5dff6 100644
--- a/core/tests/coretests/src/android/os/BundleTest.java
+++ b/core/tests/coretests/src/android/os/BundleTest.java
@@ -23,13 +23,16 @@
 import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 
+import android.platform.test.annotations.IgnoreUnderRavenwood;
 import android.platform.test.annotations.Presubmit;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.util.Log;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -45,6 +48,9 @@
 @Presubmit
 @RunWith(AndroidJUnit4.class)
 public class BundleTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     private Log.TerribleFailureHandler mWtfHandler;
 
     @After
@@ -115,6 +121,7 @@
     }
 
     @Test
+    @IgnoreUnderRavenwood(blockedBy = ParcelFileDescriptor.class)
     public void testCreateFromParcel() throws Exception {
         boolean withFd;
         Parcel p;
@@ -295,6 +302,7 @@
     }
 
     @Test
+    @IgnoreUnderRavenwood(blockedBy = Parcel.class)
     public void kindofEquals_lazyValuesAndDifferentClassLoaders_returnsFalse() {
         Parcelable p1 = new CustomParcelable(13, "Tiramisu");
         Parcelable p2 = new CustomParcelable(13, "Tiramisu");
@@ -350,6 +358,7 @@
     }
 
     @Test
+    @IgnoreUnderRavenwood(blockedBy = Parcel.class)
     public void readWriteLengthMismatch_logsWtf() throws Exception {
         mWtfHandler = Log.setWtfHandler((tag, e, system) -> {
             throw new RuntimeException(e);
@@ -364,6 +373,7 @@
     }
 
     @Test
+    @IgnoreUnderRavenwood(blockedBy = Parcel.class)
     public void getParcelable_whenThrowingAndNotDefusing_throws() throws Exception {
         Bundle.setShouldDefuse(false);
         Bundle bundle = new Bundle();
@@ -376,6 +386,7 @@
     }
 
     @Test
+    @IgnoreUnderRavenwood(blockedBy = Parcel.class)
     public void getParcelable_whenThrowingAndDefusing_returnsNull() throws Exception {
         Bundle.setShouldDefuse(true);
         Bundle bundle = new Bundle();
@@ -391,6 +402,7 @@
     }
 
     @Test
+    @IgnoreUnderRavenwood(blockedBy = Parcel.class)
     public void getParcelable_whenThrowingAndDefusing_leavesElement() throws Exception {
         Bundle.setShouldDefuse(true);
         Bundle bundle = new Bundle();
diff --git a/core/tests/coretests/src/android/os/CancellationSignalBeamerTest.java b/core/tests/coretests/src/android/os/CancellationSignalBeamerTest.java
index 42c97f3..c2cea0a 100644
--- a/core/tests/coretests/src/android/os/CancellationSignalBeamerTest.java
+++ b/core/tests/coretests/src/android/os/CancellationSignalBeamerTest.java
@@ -22,6 +22,8 @@
 
 import android.content.Context;
 import android.os.CancellationSignalBeamer.Receiver;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.util.PollingCheck;
 import android.util.PollingCheck.PollingCheckCondition;
 
@@ -29,6 +31,8 @@
 import androidx.test.platform.app.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
+import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -40,11 +44,20 @@
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
+@IgnoreUnderRavenwood(blockedBy = CancellationSignalBeamer.class)
 public class CancellationSignalBeamerTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
 
-    private CancellationSignal mSenderSignal = new CancellationSignal();
+    private CancellationSignal mSenderSignal;
     private CancellationSignal mReceivedSignal;
-    private Context mContext = InstrumentationRegistry.getInstrumentation().getContext();
+    private Context mContext;
+
+    @Before
+    public void setUp() {
+        mSenderSignal = new CancellationSignal();
+        mContext = InstrumentationRegistry.getInstrumentation().getContext();
+    }
 
     @Test
     public void testBeam_null() {
@@ -208,17 +221,22 @@
         mReceivedSignal = mReceiver.unbeam(cancellationSignalToken);
     }
 
-    private final Sender mSender = new Sender() {
-        @Override
-        public void onCancel(IBinder token) {
-            mReceiver.cancel(token);
-        }
+    private Sender mSender;
+    private Receiver mReceiver;
 
-        @Override
-        public void onForget(IBinder token) {
-            mReceiver.forget(token);
-        }
-    };
+    @Before
+    public void setUpSenderReceiver() {
+        mSender = new Sender() {
+            @Override
+            public void onCancel(IBinder token) {
+                mReceiver.cancel(token);
+            }
 
-    private final Receiver mReceiver = new Receiver(false);
+            @Override
+            public void onForget(IBinder token) {
+                mReceiver.forget(token);
+            }
+        };
+        mReceiver = new Receiver(false);
+    }
 }
diff --git a/core/tests/coretests/src/android/os/EnvironmentTest.java b/core/tests/coretests/src/android/os/EnvironmentTest.java
index ef38cde..1aa263f 100644
--- a/core/tests/coretests/src/android/os/EnvironmentTest.java
+++ b/core/tests/coretests/src/android/os/EnvironmentTest.java
@@ -28,12 +28,15 @@
 
 import android.content.Context;
 import android.os.storage.StorageManager;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -43,7 +46,11 @@
 import java.util.function.BiFunction;
 
 @RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = Environment.class)
 public class EnvironmentTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     private File dir;
 
     private static Context getContext() {
diff --git a/core/tests/coretests/src/android/os/FileBridgeTest.java b/core/tests/coretests/src/android/os/FileBridgeTest.java
index 708bfa6..726670b 100644
--- a/core/tests/coretests/src/android/os/FileBridgeTest.java
+++ b/core/tests/coretests/src/android/os/FileBridgeTest.java
@@ -19,12 +19,25 @@
 import static android.os.ParcelFileDescriptor.MODE_CREATE;
 import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
 
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
 import android.os.FileBridge.FileBridgeOutputStream;
-import android.test.AndroidTestCase;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.test.MoreAsserts;
 
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
 import libcore.io.Streams;
 
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
@@ -32,18 +45,20 @@
 import java.nio.charset.StandardCharsets;
 import java.util.Random;
 
-public class FileBridgeTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = ParcelFileDescriptor.class)
+public class FileBridgeTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
 
     private File file;
     private ParcelFileDescriptor outputFile;
     private FileBridge bridge;
     private FileBridgeOutputStream client;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        file = getContext().getFileStreamPath("meow.dat");
+    @Before
+    public void setUp() throws Exception {
+        file = File.createTempFile("meow", "dat");
         file.delete();
 
         outputFile = ParcelFileDescriptor.open(file, MODE_CREATE | MODE_READ_WRITE);
@@ -54,8 +69,8 @@
         client = new FileBridgeOutputStream(bridge.getClientSocket());
     }
 
-    @Override
-    protected void tearDown() throws Exception {
+    @After
+    public void tearDown() throws Exception {
         outputFile.close();
         file.delete();
     }
@@ -76,17 +91,20 @@
         MoreAsserts.assertEquals(expected, Streams.readFully(new FileInputStream(file)));
     }
 
+    @Test
     public void testNoWriteNoSync() throws Exception {
         assertOpen();
         closeAndAssertClosed();
     }
 
+    @Test
     public void testNoWriteSync() throws Exception {
         assertOpen();
         client.flush();
         closeAndAssertClosed();
     }
 
+    @Test
     public void testWriteNoSync() throws Exception {
         assertOpen();
         client.write("meow".getBytes(StandardCharsets.UTF_8));
@@ -94,6 +112,7 @@
         assertContents("meow".getBytes(StandardCharsets.UTF_8));
     }
 
+    @Test
     public void testWriteSync() throws Exception {
         assertOpen();
         client.write("cake".getBytes(StandardCharsets.UTF_8));
@@ -102,6 +121,7 @@
         assertContents("cake".getBytes(StandardCharsets.UTF_8));
     }
 
+    @Test
     public void testWriteSyncWrite() throws Exception {
         assertOpen();
         client.write("meow".getBytes(StandardCharsets.UTF_8));
@@ -111,6 +131,7 @@
         assertContents("meowcake".getBytes(StandardCharsets.UTF_8));
     }
 
+    @Test
     public void testEmptyWrite() throws Exception {
         assertOpen();
         client.write(new byte[0]);
@@ -118,6 +139,7 @@
         assertContents(new byte[0]);
     }
 
+    @Test
     public void testWriteAfterClose() throws Exception {
         assertOpen();
         client.write("meow".getBytes(StandardCharsets.UTF_8));
@@ -130,6 +152,7 @@
         assertContents("meow".getBytes(StandardCharsets.UTF_8));
     }
 
+    @Test
     public void testRandomWrite() throws Exception {
         final Random r = new Random();
         final ByteArrayOutputStream result = new ByteArrayOutputStream();
@@ -146,6 +169,7 @@
         assertContents(result.toByteArray());
     }
 
+    @Test
     public void testGiantWrite() throws Exception {
         final byte[] test = new byte[263401];
         new Random().nextBytes(test);
diff --git a/core/tests/coretests/src/android/os/FileObserverTest.java b/core/tests/coretests/src/android/os/FileObserverTest.java
index ece7645..3cd8045 100644
--- a/core/tests/coretests/src/android/os/FileObserverTest.java
+++ b/core/tests/coretests/src/android/os/FileObserverTest.java
@@ -16,21 +16,37 @@
 
 package android.os;
 
-import android.test.AndroidTestCase;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.util.Log;
 
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.MediumTest;
 
 import com.google.android.collect.Lists;
 import com.google.android.collect.Maps;
 
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import java.io.File;
 import java.io.FileOutputStream;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
-public class FileObserverTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = FileObserver.class)
+public class FileObserverTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     private Observer mObserver;
     private File mTestFile;
 
@@ -57,18 +73,19 @@
         }
     }
 
-    @Override
-    protected void setUp() throws Exception {
+    @Before
+    public void setUp() throws Exception {
         mTestFile = File.createTempFile(".file_observer_test", ".txt");
     }
 
-    @Override
-    protected void tearDown() throws Exception {
+    @After
+    public void tearDown() throws Exception {
         if (mTestFile != null && mTestFile.exists()) {
             mTestFile.delete();
         }
     }
 
+    @Test
     @MediumTest
     public void testRun() throws Exception {
         // make file changes and wait for them
diff --git a/core/tests/coretests/src/android/os/HandlerThreadTest.java b/core/tests/coretests/src/android/os/HandlerThreadTest.java
index 93cfc40..0bac1c7 100644
--- a/core/tests/coretests/src/android/os/HandlerThreadTest.java
+++ b/core/tests/coretests/src/android/os/HandlerThreadTest.java
@@ -16,18 +16,35 @@
 
 package android.os;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.platform.test.ravenwood.RavenwoodRule;
+
 import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
 
-import junit.framework.TestCase;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
-public class HandlerThreadTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+public class HandlerThreadTest {
     private static final int TEST_WHAT = 1;
 
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     private boolean mGotMessage = false;
     private int mGotMessageWhat = -1;
     private volatile boolean mDidSetup = false;
     private volatile int mLooperTid = -1;
-    
+
+    @Test
     @MediumTest
     public void testHandlerThread() throws Exception {
         HandlerThread th1 =  new HandlerThread("HandlerThreadTest") {
diff --git a/core/tests/coretests/src/android/os/IdleHandlerTest.java b/core/tests/coretests/src/android/os/IdleHandlerTest.java
index d8886c9..8644663 100644
--- a/core/tests/coretests/src/android/os/IdleHandlerTest.java
+++ b/core/tests/coretests/src/android/os/IdleHandlerTest.java
@@ -17,12 +17,19 @@
 package android.os;
 
 import android.os.MessageQueue.IdleHandler;
+import android.platform.test.ravenwood.RavenwoodRule;
 
 import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
 
-import junit.framework.TestCase;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
-public class IdleHandlerTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+public class IdleHandlerTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
 
     private static class BaseTestHandler extends TestHandlerThread {
         Handler mHandler;
@@ -54,6 +61,7 @@
         }
     }
 
+    @Test
     @MediumTest
     public void testOneShotFirst() throws Exception {
         TestHandlerThread tester = new BaseTestHandler() {
@@ -88,6 +96,7 @@
         tester.doTest(1000);
     }
 
+    @Test
     @MediumTest
     public void testOneShotLater() throws Exception {
         TestHandlerThread tester = new BaseTestHandler() {
@@ -125,6 +134,7 @@
     }
 
 
+    @Test
     @MediumTest
     public void testRepeatedFirst() throws Exception {
         TestHandlerThread tester = new BaseTestHandler() {
@@ -159,6 +169,7 @@
         tester.doTest(1000);
     }
 
+    @Test
     @MediumTest
     public void testRepeatedLater() throws Exception {
         TestHandlerThread tester = new BaseTestHandler() {
diff --git a/core/tests/coretests/src/android/os/IpcDataCacheTest.java b/core/tests/coretests/src/android/os/IpcDataCacheTest.java
index 34712ce..b03fd64 100644
--- a/core/tests/coretests/src/android/os/IpcDataCacheTest.java
+++ b/core/tests/coretests/src/android/os/IpcDataCacheTest.java
@@ -17,12 +17,14 @@
 package android.os;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotSame;
-import static org.junit.Assert.assertSame;
+
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 
 import androidx.test.filters.SmallTest;
 
 import org.junit.After;
+import org.junit.Rule;
 import org.junit.Test;
 
 /**
@@ -35,7 +37,10 @@
  *  atest FrameworksCoreTests:IpcDataCacheTest
  */
 @SmallTest
+@IgnoreUnderRavenwood(blockedBy = IpcDataCache.class)
 public class IpcDataCacheTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
 
     // Configuration for creating caches
     private static final String MODULE = IpcDataCache.MODULE_TEST;
diff --git a/core/tests/coretests/src/android/os/LocaleListTest.java b/core/tests/coretests/src/android/os/LocaleListTest.java
index 88fc826..0025e3a 100644
--- a/core/tests/coretests/src/android/os/LocaleListTest.java
+++ b/core/tests/coretests/src/android/os/LocaleListTest.java
@@ -16,13 +16,29 @@
 
 package android.os;
 
-import androidx.test.filters.SmallTest;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.fail;
 
-import junit.framework.TestCase;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.util.Locale;
 
-public class LocaleListTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = LocaleList.class)
+public class LocaleListTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
+    @Test
     @SmallTest
     public void testConstructor() throws Exception {
         LocaleList ll;
@@ -51,6 +67,7 @@
         assertEquals("fr,de", ll.toLanguageTags());
     }
 
+    @Test
     @SmallTest
     public void testConstructor_nullThrows() throws Exception {
         try {
@@ -61,6 +78,7 @@
         }
     }
 
+    @Test
     @SmallTest
     public void testGetDefault_localeSetDefaultCalledButNoChangeNecessary() throws Exception {
         final Locale originalLocale = Locale.getDefault();
@@ -82,6 +100,7 @@
         LocaleList.setDefault(originalLocaleList, originalLocaleIndex);
     }
 
+    @Test
     @SmallTest
     public void testIntersection() {
         LocaleList localesWithN = new LocaleList(
diff --git a/core/tests/coretests/src/android/os/MemoryFileTest.java b/core/tests/coretests/src/android/os/MemoryFileTest.java
index 05c2995..a695424 100644
--- a/core/tests/coretests/src/android/os/MemoryFileTest.java
+++ b/core/tests/coretests/src/android/os/MemoryFileTest.java
@@ -16,11 +16,21 @@
 
 package android.os;
 
-import android.test.AndroidTestCase;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
 
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.LargeTest;
 import androidx.test.filters.SmallTest;
 
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -29,7 +39,11 @@
 import java.util.Arrays;
 import java.util.List;
 
-public class MemoryFileTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = MemoryFile.class)
+public class MemoryFileTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
 
     private void compareBuffers(byte[] buffer1, byte[] buffer2, int length) throws Exception {
         for (int i = 0; i < length; i++) {
@@ -44,6 +58,8 @@
      */
     // Flaky test - temporarily suppress from large suite for now
     // @LargeTest
+    @Test
+    @Ignore("Flaky test")
     public void testPurge() throws Exception {
         List<MemoryFile> files = new ArrayList<MemoryFile>();
         try {
@@ -70,6 +86,7 @@
         }
     }
 
+    @Test
     @SmallTest
     public void testRun() throws Exception {
         MemoryFile file = new MemoryFile("MemoryFileTest", 1000000);
@@ -102,6 +119,7 @@
     }
 
     // http://code.google.com/p/android/issues/detail?id=11415
+    @Test
     public void testOutputStreamAdvances() throws IOException {
         MemoryFile file = new MemoryFile("MemoryFileTest", 10);
 
@@ -142,24 +160,28 @@
         }
     }
 
+    @Test
     @SmallTest
     public void testReadNegativeOffset() throws Exception {
         readIndexOutOfBoundsException(-1, 5,
                 "read() with negative offset should throw IndexOutOfBoundsException");
     }
 
+    @Test
     @SmallTest
     public void testReadNegativeCount() throws Exception {
         readIndexOutOfBoundsException(5, -1,
                 "read() with negative length should throw IndexOutOfBoundsException");
     }
 
+    @Test
     @SmallTest
     public void testReadOffsetOverflow() throws Exception {
         readIndexOutOfBoundsException(testString.length + 10, 5,
                 "read() with offset outside buffer should throw IndexOutOfBoundsException");
     }
 
+    @Test
     @SmallTest
     public void testReadOffsetCountOverflow() throws Exception {
         readIndexOutOfBoundsException(testString.length, 11,
@@ -167,6 +189,7 @@
     }
 
     // Test behavior of read() at end of file
+    @Test
     @SmallTest
     public void testReadEOF() throws Exception {
         MemoryFile file = new MemoryFile("MemoryFileTest", testString.length);
@@ -189,6 +212,7 @@
     }
 
     // Tests that close() is idempotent
+    @Test
     @SmallTest
     public void testCloseClose() throws Exception {
         MemoryFile file = new MemoryFile("MemoryFileTest", 1000000);
@@ -199,6 +223,7 @@
     }
 
     // Tests that we can't read from a closed memory file
+    @Test
     @SmallTest
     public void testCloseRead() throws Exception {
         MemoryFile file = new MemoryFile("MemoryFileTest", 1000000);
@@ -214,6 +239,7 @@
     }
 
     // Tests that we can't write to a closed memory file
+    @Test
     @SmallTest
     public void testCloseWrite() throws Exception {
         MemoryFile file = new MemoryFile("MemoryFileTest", 1000000);
@@ -229,6 +255,7 @@
     }
 
     // Tests that we can't call allowPurging() after close()
+    @Test
     @SmallTest
     public void testCloseAllowPurging() throws Exception {
         MemoryFile file = new MemoryFile("MemoryFileTest", 1000000);
@@ -245,6 +272,7 @@
     }
 
     // Tests that we don't leak file descriptors or mmap areas
+    @Test
     @LargeTest
     public void testCloseLeak() throws Exception {
         // open enough memory files that we should run out of
diff --git a/core/tests/coretests/src/android/os/MessageQueueTest.java b/core/tests/coretests/src/android/os/MessageQueueTest.java
index 2c5588e..851e612 100644
--- a/core/tests/coretests/src/android/os/MessageQueueTest.java
+++ b/core/tests/coretests/src/android/os/MessageQueueTest.java
@@ -16,13 +16,22 @@
 
 package android.os;
 
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
+
 import androidx.test.filters.MediumTest;
 import androidx.test.filters.Suppress;
+import androidx.test.runner.AndroidJUnit4;
 
-import junit.framework.TestCase;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 @Suppress  // Failing.
-public class MessageQueueTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+public class MessageQueueTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
 
     private static class BaseTestHandler extends TestHandlerThread {
         Handler mHandler;
@@ -61,6 +70,7 @@
         }
     }
 
+    @Test
     @MediumTest
     public void testMessageOrder() throws Exception {
         TestHandlerThread tester = new BaseTestHandler() {
@@ -80,6 +90,7 @@
         tester.doTest(1000);
     }
 
+    @Test
     @MediumTest
     public void testAtFrontOfQueue() throws Exception {
         TestHandlerThread tester = new BaseTestHandler() {
@@ -141,7 +152,9 @@
         }
     }
 
+    @Test
     @MediumTest
+    @IgnoreUnderRavenwood(reason = "Flaky test, b/315872700")
     public void testFieldIntegrity() throws Exception {
 
         TestHandlerThread tester = new TestFieldIntegrityHandler() {
@@ -157,7 +170,7 @@
             public void handleMessage(Message msg) {
                 super.handleMessage(msg);
                 if (msg.what == 0) {
-                    msg.flags = -1;
+                    msg.flags = Message.FLAGS_TO_CLEAR_ON_COPY_FROM;
                     msg.what = 1;
                     msg.arg1 = 456;
                     msg.arg2 = 789;
diff --git a/core/tests/coretests/src/android/os/MessengerTest.java b/core/tests/coretests/src/android/os/MessengerTest.java
index 9143ff1..eb6263f 100644
--- a/core/tests/coretests/src/android/os/MessengerTest.java
+++ b/core/tests/coretests/src/android/os/MessengerTest.java
@@ -16,15 +16,31 @@
 
 package android.os;
 
+import android.app.ActivityManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
-import android.test.AndroidTestCase;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.MediumTest;
 
-public class MessengerTest extends AndroidTestCase {
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = ActivityManager.class)
+public class MessengerTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
+    private Context mContext;
     private Messenger mServiceMessenger;
     
     private ServiceConnection mConnection = new ServiceConnection() {
@@ -86,10 +102,10 @@
         }
     };
     
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        getContext().bindService(new Intent(mContext, MessengerService.class),
+    @Before
+    public void setUp() throws Exception {
+        mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+        mContext.bindService(new Intent(mContext, MessengerService.class),
                 mConnection, Context.BIND_AUTO_CREATE);
         synchronized (this) {
             while (mServiceMessenger == null) {
@@ -101,15 +117,14 @@
         }
     }
 
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
-        getContext().unbindService(mConnection);
+    @After
+    public void tearDown() throws Exception {
+        mContext.unbindService(mConnection);
     }
 
+    @Test
     @MediumTest
     public void testSend() {
         (new TestThread()).doTest(1000);
-        
     }
 }
diff --git a/core/tests/coretests/src/android/os/OsTests.java b/core/tests/coretests/src/android/os/OsTests.java
deleted file mode 100644
index 08fb945..0000000
--- a/core/tests/coretests/src/android/os/OsTests.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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 junit.framework.TestSuite;
-
-public class OsTests {
-    public static TestSuite suite() {
-        TestSuite suite = new TestSuite(OsTests.class.getName());
-
-        suite.addTestSuite(AidlTest.class);
-        suite.addTestSuite(BroadcasterTest.class);
-        suite.addTestSuite(FileObserverTest.class);
-        suite.addTestSuite(IdleHandlerTest.class);
-        suite.addTestSuite(MessageQueueTest.class);
-        suite.addTestSuite(MessengerTest.class);
-        suite.addTestSuite(PatternMatcherTest.class);
-
-        return suite;
-    }
-}
diff --git a/core/tests/coretests/src/android/os/ParcelNullabilityTest.java b/core/tests/coretests/src/android/os/ParcelNullabilityTest.java
index b4e180c..ffeab29 100644
--- a/core/tests/coretests/src/android/os/ParcelNullabilityTest.java
+++ b/core/tests/coretests/src/android/os/ParcelNullabilityTest.java
@@ -20,11 +20,14 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.util.ArrayMap;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -36,6 +39,9 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public final class ParcelNullabilityTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     @Test
     public void nullByteArray() {
         Parcel p = Parcel.obtain();
@@ -61,6 +67,7 @@
     }
 
     @Test
+    @IgnoreUnderRavenwood(blockedBy = Parcel.class)
     public void nullCharSequence() {
         Parcel p = Parcel.obtain();
         p.writeCharSequence(null);
@@ -69,6 +76,7 @@
     }
 
     @Test
+    @IgnoreUnderRavenwood(blockedBy = Parcel.class)
     public void nullStrongBinder() {
         Parcel p = Parcel.obtain();
         p.writeStrongBinder(null);
@@ -77,6 +85,7 @@
     }
 
     @Test
+    @IgnoreUnderRavenwood(blockedBy = Parcel.class)
     public void nullStringInterface() {
         Parcel p = Parcel.obtain();
         p.writeStrongInterface(null);
diff --git a/core/tests/coretests/src/android/os/ParcelTest.java b/core/tests/coretests/src/android/os/ParcelTest.java
index 4b993fa..26f6d69 100644
--- a/core/tests/coretests/src/android/os/ParcelTest.java
+++ b/core/tests/coretests/src/android/os/ParcelTest.java
@@ -21,22 +21,29 @@
 import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 
+import android.platform.test.annotations.IgnoreUnderRavenwood;
 import android.platform.test.annotations.Presubmit;
+import android.platform.test.ravenwood.RavenwoodRule;
 
 import androidx.test.runner.AndroidJUnit4;
 
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 @Presubmit
 @RunWith(AndroidJUnit4.class)
 public class ParcelTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     private static final int WORK_SOURCE_1 = 1000;
     private static final int WORK_SOURCE_2 = 1002;
     private static final String INTERFACE_TOKEN_1 = "IBinder interface token";
     private static final String INTERFACE_TOKEN_2 = "Another IBinder interface token";
 
     @Test
+    @IgnoreUnderRavenwood(blockedBy = Parcel.class)
     public void testIsForRpc() {
         Parcel p = Parcel.obtain();
         assertEquals(false, p.isForRpc());
@@ -44,6 +51,7 @@
     }
 
     @Test
+    @IgnoreUnderRavenwood(blockedBy = Parcel.class)
     public void testCallingWorkSourceUidAfterWrite() {
         Parcel p = Parcel.obtain();
         // Method does not throw if replaceCallingWorkSourceUid is called before requests headers
@@ -64,6 +72,7 @@
     }
 
     @Test
+    @IgnoreUnderRavenwood(blockedBy = Parcel.class)
     public void testCallingWorkSourceUidAfterEnforce() {
         Parcel p = Parcel.obtain();
         p.writeInterfaceToken(INTERFACE_TOKEN_1);
@@ -81,6 +90,7 @@
     }
 
     @Test
+    @IgnoreUnderRavenwood(blockedBy = Parcel.class)
     public void testParcelWithMultipleHeaders() {
         Parcel p = Parcel.obtain();
         Binder.setCallingWorkSourceUid(WORK_SOURCE_1);
@@ -138,6 +148,7 @@
     }
 
     @Test
+    @IgnoreUnderRavenwood(blockedBy = Parcel.class)
     public void testCompareDataInRange_whenSameDataWithBinder() {
         Binder binder = new Binder();
         Parcel pA = Parcel.obtain();
@@ -297,6 +308,7 @@
      * and 1M length for complex objects are allowed.
      */
     @Test
+    @IgnoreUnderRavenwood(blockedBy = Parcel.class)
     public void testAllocations_whenWithinLimit() {
         Binder.setIsDirectlyHandlingTransactionOverride(true);
         Parcel p = Parcel.obtain();
diff --git a/core/tests/coretests/src/android/os/PatternMatcherTest.java b/core/tests/coretests/src/android/os/PatternMatcherTest.java
index 82350cd..a5e036d 100644
--- a/core/tests/coretests/src/android/os/PatternMatcherTest.java
+++ b/core/tests/coretests/src/android/os/PatternMatcherTest.java
@@ -16,9 +16,10 @@
 
 package android.os;
 
-import androidx.test.filters.SmallTest;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
-import junit.framework.TestCase;
+import androidx.test.filters.SmallTest;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -26,7 +27,7 @@
 
 @RunWith(JUnit4.class)
 @SmallTest
-public class PatternMatcherTest extends TestCase{
+public class PatternMatcherTest {
 
     @Test
     public void testAdvancedPatternMatchesAnyToken() {
diff --git a/core/tests/coretests/src/android/os/PerformanceCollectorTest.java b/core/tests/coretests/src/android/os/PerformanceCollectorTest.java
index 38ad90f..46f1706 100644
--- a/core/tests/coretests/src/android/os/PerformanceCollectorTest.java
+++ b/core/tests/coretests/src/android/os/PerformanceCollectorTest.java
@@ -16,33 +16,48 @@
 
 package android.os;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
 import android.os.PerformanceCollector.PerformanceResultsWriter;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 
 import androidx.test.filters.MediumTest;
 import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
-import junit.framework.TestCase;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.Random;
 
-public class PerformanceCollectorTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = PerformanceCollector.class)
+public class PerformanceCollectorTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
 
     private PerformanceCollector mPerfCollector;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @Before
+    public void setUp() throws Exception {
         mPerfCollector = new PerformanceCollector();
     }
 
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
+    @After
+    public void tearDown() throws Exception {
         mPerfCollector = null;
     }
 
+    @Test
     @SmallTest
     public void testBeginSnapshotNoWriter() throws Exception {
         mPerfCollector.beginSnapshot("testBeginSnapshotNoWriter");
@@ -54,6 +69,7 @@
         assertEquals(2, snapshot.size());
     }
 
+    @Test
     @MediumTest
     public void testEndSnapshotNoWriter() throws Exception {
         mPerfCollector.beginSnapshot("testEndSnapshotNoWriter");
@@ -63,6 +79,7 @@
         verifySnapshotBundle(snapshot);
     }
 
+    @Test
     @SmallTest
     public void testStartTimingNoWriter() throws Exception {
         mPerfCollector.startTiming("testStartTimingNoWriter");
@@ -74,6 +91,7 @@
         verifyTimingBundle(measurement, new ArrayList<String>());
     }
 
+    @Test
     @SmallTest
     public void testAddIterationNoWriter() throws Exception {
         mPerfCollector.startTiming("testAddIterationNoWriter");
@@ -83,6 +101,7 @@
         verifyIterationBundle(iteration, "timing1");
     }
 
+    @Test
     @SmallTest
     public void testStopTimingNoWriter() throws Exception {
         mPerfCollector.startTiming("testStopTimingNoWriter");
@@ -100,6 +119,7 @@
         verifyTimingBundle(timing, labels);
     }
 
+    @Test
     @SmallTest
     public void testBeginSnapshot() throws Exception {
         MockPerformanceResultsWriter writer = new MockPerformanceResultsWriter();
@@ -114,6 +134,7 @@
         assertEquals(2, snapshot.size());
     }
 
+    @Test
     @MediumTest
     public void testEndSnapshot() throws Exception {
         MockPerformanceResultsWriter writer = new MockPerformanceResultsWriter();
@@ -127,6 +148,7 @@
         verifySnapshotBundle(snapshot1);
     }
 
+    @Test
     @SmallTest
     public void testStartTiming() throws Exception {
         MockPerformanceResultsWriter writer = new MockPerformanceResultsWriter();
@@ -141,6 +163,7 @@
         verifyTimingBundle(measurement, new ArrayList<String>());
     }
 
+    @Test
     @SmallTest
     public void testAddIteration() throws Exception {
         mPerfCollector.startTiming("testAddIteration");
@@ -150,6 +173,7 @@
         verifyIterationBundle(iteration, "timing5");
     }
 
+    @Test
     @SmallTest
     public void testStopTiming() throws Exception {
         mPerfCollector.startTiming("testStopTiming");
@@ -167,6 +191,7 @@
         verifyTimingBundle(timing, labels);
     }
 
+    @Test
     @SmallTest
     public void testAddMeasurementLong() throws Exception {
         MockPerformanceResultsWriter writer = new MockPerformanceResultsWriter();
@@ -188,6 +213,7 @@
         assertEquals(-19354, results.getLong("testAddMeasurementLongNeg"));
     }
 
+    @Test
     @SmallTest
     public void testAddMeasurementFloat() throws Exception {
         MockPerformanceResultsWriter writer = new MockPerformanceResultsWriter();
@@ -202,13 +228,14 @@
         Bundle results = writer.timingResults;
         assertEquals(4, results.size());
         assertTrue(results.containsKey("testAddMeasurementFloatZero"));
-        assertEquals(0.0f, results.getFloat("testAddMeasurementFloatZero"));
+        assertEquals(0.0f, results.getFloat("testAddMeasurementFloatZero"), 0.0f);
         assertTrue(results.containsKey("testAddMeasurementFloatPos"));
-        assertEquals(348573.345f, results.getFloat("testAddMeasurementFloatPos"));
+        assertEquals(348573.345f, results.getFloat("testAddMeasurementFloatPos"), 0.0f);
         assertTrue(results.containsKey("testAddMeasurementFloatNeg"));
-        assertEquals(-19354.093f, results.getFloat("testAddMeasurementFloatNeg"));
+        assertEquals(-19354.093f, results.getFloat("testAddMeasurementFloatNeg"), 0.0f);
     }
 
+    @Test
     @SmallTest
     public void testAddMeasurementString() throws Exception {
         MockPerformanceResultsWriter writer = new MockPerformanceResultsWriter();
@@ -230,6 +257,7 @@
         assertEquals("Hello World", results.getString("testAddMeasurementStringNonEmpty"));
     }
 
+    @Test
     @MediumTest
     public void testSimpleSequence() throws Exception {
         MockPerformanceResultsWriter writer = new MockPerformanceResultsWriter();
@@ -262,6 +290,7 @@
         verifyTimingBundle(timing, labels);
     }
 
+    @Test
     @MediumTest
     public void testLongSequence() throws Exception {
         MockPerformanceResultsWriter writer = new MockPerformanceResultsWriter();
@@ -348,6 +377,7 @@
      * Verify that snapshotting and timing do not interfere w/ each other,
      * by staggering calls to snapshot and timing functions.
      */
+    @Test
     @MediumTest
     public void testOutOfOrderSequence() {
         MockPerformanceResultsWriter writer = new MockPerformanceResultsWriter();
diff --git a/core/tests/coretests/src/android/os/PerformanceHintManagerTest.java b/core/tests/coretests/src/android/os/PerformanceHintManagerTest.java
index 9b4dec4..12a2844 100644
--- a/core/tests/coretests/src/android/os/PerformanceHintManagerTest.java
+++ b/core/tests/coretests/src/android/os/PerformanceHintManagerTest.java
@@ -24,18 +24,25 @@
 import static org.junit.Assume.assumeNotNull;
 
 import android.os.PerformanceHintManager.Session;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
 @RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = PerformanceHintManager.class)
 public class PerformanceHintManagerTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     private static final long RATE_1000 = 1000L;
     private static final long TARGET_166 = 166L;
     private static final long DEFAULT_TARGET_NS = 16666666L;
diff --git a/core/tests/coretests/src/android/os/PowerManagerTest.java b/core/tests/coretests/src/android/os/PowerManagerTest.java
index 5d213ca..cb281ff 100644
--- a/core/tests/coretests/src/android/os/PowerManagerTest.java
+++ b/core/tests/coretests/src/android/os/PowerManagerTest.java
@@ -17,7 +17,9 @@
 package android.os;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.reset;
@@ -26,28 +28,34 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
-import android.os.Flags;
+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.test.AndroidTestCase;
+import android.platform.test.ravenwood.RavenwoodRule;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 import androidx.test.uiautomator.UiDevice;
 
 import org.junit.After;
+import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
 
-public class PowerManagerTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = PowerManager.class)
+public class PowerManagerTest {
 
     private static final String TAG = "PowerManagerTest";
+    private Context mContext;
     private PowerManager mPm;
     private UiDevice mUiDevice;
     private Executor mExec = Executors.newSingleThreadExecutor();
@@ -68,21 +76,27 @@
             String[] keys, String[] values);
 
     static {
-        System.loadLibrary("powermanagertest_jni");
+        if (!RavenwoodRule.isUnderRavenwood()) {
+            System.loadLibrary("powermanagertest_jni");
+        }
     }
 
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     // Required for RequiresFlagsEnabled and RequiresFlagsDisabled annotations to take effect.
     @Rule
-    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+    public final CheckFlagsRule mCheckFlagsRule = RavenwoodRule.isUnderRavenwood() ? null
+            : DeviceFlagsValueProvider.createCheckFlagsRule();
 
     /**
      * Setup any common data for the upcoming tests.
      */
-    @Override
+    @Before
     public void setUp() throws Exception {
-        super.setUp();
         MockitoAnnotations.initMocks(this);
         mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+        mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
         mPm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mUiDevice.executeShellCommand("cmd thermalservice override-status 0");
     }
@@ -100,6 +114,7 @@
      *
      * @throws Exception
      */
+    @Test
     @SmallTest
     public void testPreconditions() throws Exception {
         assertNotNull(mPm);
@@ -110,6 +125,7 @@
      *
      * @throws Exception
      */
+    @Test
     @SmallTest
     public void testNewWakeLock() throws Exception {
         PowerManager.WakeLock wl = mPm.newWakeLock(PowerManager.FULL_WAKE_LOCK, "FULL_WAKE_LOCK");
@@ -133,6 +149,7 @@
      *
      * @throws Exception
      */
+    @Test
     @SmallTest
     public void testBadNewWakeLock() throws Exception {
         final int badFlags = PowerManager.SCREEN_BRIGHT_WAKE_LOCK
@@ -152,6 +169,7 @@
      *
      * @throws Exception
      */
+    @Test
     @SmallTest
     public void testWakeLockWithWorkChains() throws Exception {
         PowerManager.WakeLock wakeLock = mPm.newWakeLock(
diff --git a/core/tests/coretests/src/android/os/ProcessTest.java b/core/tests/coretests/src/android/os/ProcessTest.java
index b2ffdc0..310baa3 100644
--- a/core/tests/coretests/src/android/os/ProcessTest.java
+++ b/core/tests/coretests/src/android/os/ProcessTest.java
@@ -17,12 +17,23 @@
 
 package android.os;
 
-import junit.framework.TestCase;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
-public class ProcessTest extends TestCase {
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+@IgnoreUnderRavenwood(blockedBy = Process.class)
+public class ProcessTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
 
     private static final int BAD_PID = 0;
 
+    @Test
     public void testProcessGetUidFromName() throws Exception {
         assertEquals(android.os.Process.SYSTEM_UID, Process.getUidForName("system"));
         assertEquals(Process.BLUETOOTH_UID, Process.getUidForName("bluetooth"));
@@ -36,6 +47,7 @@
                 Process.getUidForName("u3_a100"));
     }
 
+    @Test
     public void testProcessGetUidFromNameFailure() throws Exception {
         // Failure cases
         assertEquals(-1, Process.getUidForName("u2a_foo"));
@@ -51,6 +63,7 @@
      * Tests getUidForPid() by ensuring that it returns the correct value when the process queried
      * doesn't exist.
      */
+    @Test
     public void testGetUidForPidInvalidPid() {
         assertEquals(-1, Process.getUidForPid(BAD_PID));
     }
@@ -59,6 +72,7 @@
      * Tests getParentPid() by ensuring that it returns the correct value when the process queried
      * doesn't exist.
      */
+    @Test
     public void testGetParentPidInvalidPid() {
         assertEquals(-1, Process.getParentPid(BAD_PID));
     }
@@ -67,11 +81,13 @@
      * Tests getThreadGroupLeader() by ensuring that it returns the correct value when the
      * thread queried doesn't exist.
      */
+    @Test
     public void testGetThreadGroupLeaderInvalidTid() {
         // This function takes a TID instead of a PID but BAD_PID should also be a bad TID.
         assertEquals(-1, Process.getThreadGroupLeader(BAD_PID));
     }
 
+    @Test
     public void testGetAdvertisedMem() {
         assertTrue(Process.getAdvertisedMem() > 0);
         assertTrue(Process.getTotalMemory() <= Process.getAdvertisedMem());
diff --git a/core/tests/coretests/src/android/os/RedactingFileDescriptorTest.java b/core/tests/coretests/src/android/os/RedactingFileDescriptorTest.java
index eff4826..25ce240 100644
--- a/core/tests/coretests/src/android/os/RedactingFileDescriptorTest.java
+++ b/core/tests/coretests/src/android/os/RedactingFileDescriptorTest.java
@@ -24,6 +24,8 @@
 import static org.junit.Assert.assertEquals;
 
 import android.content.Context;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.system.Os;
 
 import androidx.test.InstrumentationRegistry;
@@ -31,6 +33,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -41,7 +44,11 @@
 import java.util.Arrays;
 
 @RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = RedactingFileDescriptor.class)
 public class RedactingFileDescriptorTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     private Context mContext;
     private File mFile;
 
diff --git a/core/tests/coretests/src/android/os/TraceTest.java b/core/tests/coretests/src/android/os/TraceTest.java
index d07187c..593833ec 100644
--- a/core/tests/coretests/src/android/os/TraceTest.java
+++ b/core/tests/coretests/src/android/os/TraceTest.java
@@ -16,24 +16,36 @@
 
 package android.os;
 
-import android.test.AndroidTestCase;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.util.Log;
 
 import androidx.test.filters.LargeTest;
 import androidx.test.filters.SmallTest;
 import androidx.test.filters.Suppress;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 /**
  * 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.
  */
-public class TraceTest extends AndroidTestCase
-{
+@RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = Trace.class)
+public class TraceTest {
     private static final String TAG = "TraceTest";
+
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     private int eMethodCalls = 0;
     private int fMethodCalls = 0;
     private int gMethodCalls = 0;
 
+    @Test
     public void testNullStrings() {
         Trace.traceCounter(Trace.TRACE_TAG_ACTIVITY_MANAGER, null, 42);
         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, null);
@@ -48,6 +60,7 @@
         Trace.instantForTrack(Trace.TRACE_TAG_ACTIVITY_MANAGER, null, null);
     }
 
+    @Test
     @SmallTest
     public void testNativeTracingFromJava()
     {
@@ -80,7 +93,8 @@
 
     native void nativeMethod();
     native void nativeMethodAndStartTracing();
-    
+
+    @Test
     @LargeTest
     @Suppress  // Failing.
     public void testMethodTracing()
diff --git a/core/tests/coretests/src/android/os/VintfObjectTest.java b/core/tests/coretests/src/android/os/VintfObjectTest.java
index ae6e79a..f34b8fd 100644
--- a/core/tests/coretests/src/android/os/VintfObjectTest.java
+++ b/core/tests/coretests/src/android/os/VintfObjectTest.java
@@ -16,12 +16,27 @@
 
 package android.os;
 
-import junit.framework.TestCase;
+import static org.junit.Assert.assertTrue;
 
-public class VintfObjectTest extends TestCase {
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = VintfObject.class)
+public class VintfObjectTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     /**
      * Quick check for {@link VintfObject#report VintfObject.report()}.
      */
+    @Test
     public void testReport() {
         String[] xmls = VintfObject.report();
         assertTrue(xmls.length > 0);
diff --git a/core/tests/coretests/src/android/os/WorkSourceParcelTest.java b/core/tests/coretests/src/android/os/WorkSourceParcelTest.java
index 4831606..5f49186 100644
--- a/core/tests/coretests/src/android/os/WorkSourceParcelTest.java
+++ b/core/tests/coretests/src/android/os/WorkSourceParcelTest.java
@@ -16,17 +16,25 @@
 
 package android.os;
 
+import static org.junit.Assert.assertEquals;
+
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
+
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 
-import static org.junit.Assert.assertEquals;
-
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
+@IgnoreUnderRavenwood(reason = "JNI")
 public class WorkSourceParcelTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     /**
      * END_OF_PARCEL_MARKER is added at the end of Parcel on native or java side on write and
      * then read on java or native side on read. This way we can ensure that no extra data
@@ -41,8 +49,11 @@
             String[] names, int parcelEndMarker);
 
     static {
-        System.loadLibrary("worksourceparceltest_jni");
+        if (!RavenwoodRule.isUnderRavenwood()) {
+            System.loadLibrary("worksourceparceltest_jni");
+        }
     }
+
     /**
      * Confirm that we can pass WorkSource from native to Java.
      */
diff --git a/core/tests/coretests/src/android/os/WorkSourceTest.java b/core/tests/coretests/src/android/os/WorkSourceTest.java
index 4206fd2..85dc127 100644
--- a/core/tests/coretests/src/android/os/WorkSourceTest.java
+++ b/core/tests/coretests/src/android/os/WorkSourceTest.java
@@ -16,9 +16,19 @@
 
 package android.os;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
 import android.os.WorkSource.WorkChain;
 
-import junit.framework.TestCase;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -28,7 +38,9 @@
  *
  * These tests will be moved to CTS when finalized.
  */
-public class WorkSourceTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+public class WorkSourceTest {
+    @Test
     public void testWorkChain_add() {
         WorkChain wc1 = new WorkChain();
         wc1.addNode(56, null);
@@ -46,6 +58,7 @@
         assertEquals(2, wc1.getSize());
     }
 
+    @Test
     public void testWorkChain_equalsHashCode() {
         WorkChain wc1 = new WorkChain();
         WorkChain wc2 = new WorkChain();
@@ -78,6 +91,7 @@
         assertFalse(wc1.hashCode() == wc2.hashCode());
     }
 
+    @Test
     public void testWorkChain_constructor() {
         WorkChain wc1 = new WorkChain();
         wc1.addNode(1, "foo")
@@ -91,6 +105,7 @@
         assertFalse(wc1.equals(wc2));
     }
 
+    @Test
     public void testDiff_workChains() {
         WorkSource ws1 = new WorkSource();
         ws1.add(50);
@@ -104,6 +119,7 @@
         assertFalse(ws2.diff(ws1));
     }
 
+    @Test
     public void testEquals_workChains() {
         WorkSource ws1 = new WorkSource();
         ws1.add(50);
@@ -128,6 +144,7 @@
         assertFalse(ws3.equals(ws1));
     }
 
+    @Test
     public void testEquals_workChains_nullEmptyAreEquivalent() {
         // Construct a WorkSource that has no WorkChains, but whose workChains list
         // is non-null.
@@ -145,6 +162,7 @@
         assertFalse(ws1.equals(ws2));
     }
 
+    @Test
     public void testWorkSourceParcelling() {
         WorkSource ws = new WorkSource();
 
@@ -164,6 +182,7 @@
         assertEquals(unparcelled, ws);
     }
 
+    @Test
     public void testSet_workChains() {
         WorkSource ws1 = new WorkSource();
         ws1.add(50);
@@ -193,6 +212,7 @@
         assertEquals(1, ws1.getWorkChains().get(0).getSize());
     }
 
+    @Test
     public void testSet_nullWorkChain() {
         WorkSource ws = new WorkSource();
         ws.add(60);
@@ -203,6 +223,7 @@
         assertEquals(0, ws.getWorkChains().size());
     }
 
+    @Test
     public void testAdd_workChains() {
         WorkSource ws = new WorkSource();
         ws.createWorkChain().addNode(70, "foo");
@@ -224,6 +245,7 @@
         assertEquals(2, workChains.size());
     }
 
+    @Test
     public void testSet_noWorkChains() {
         WorkSource ws = new WorkSource();
         ws.set(10);
@@ -237,6 +259,7 @@
         assertEquals("foo", ws2.getPackageName(0));
     }
 
+    @Test
     public void testDiffChains_noChanges() {
         // WorkSources with no chains.
         assertEquals(null, WorkSource.diffChains(new WorkSource(), new WorkSource()));
@@ -254,6 +277,7 @@
         assertEquals(null, WorkSource.diffChains(ws2, ws1));
     }
 
+    @Test
     public void testDiffChains_noChains() {
         // Diffs against a worksource with no chains.
         WorkSource ws1 = new WorkSource();
@@ -276,6 +300,7 @@
         assertEquals(ws2.getWorkChains(), diffs[1]);
     }
 
+    @Test
     public void testDiffChains_onlyAdditionsOrRemovals() {
         WorkSource ws1 = new WorkSource();
         WorkSource ws2 = new WorkSource();
@@ -302,6 +327,7 @@
     }
 
 
+    @Test
     public void testDiffChains_generalCase() {
         WorkSource ws1 = new WorkSource();
         WorkSource ws2 = new WorkSource();
@@ -340,6 +366,7 @@
         assertEquals(new WorkChain().addNode(2, "tag2"), diffs[1].get(1));
     }
 
+    @Test
     public void testGetAttributionId() {
         WorkSource ws = new WorkSource();
         WorkChain wc1 = ws.createWorkChain();
@@ -355,6 +382,7 @@
         assertEquals(100, ws.getAttributionUid());
     }
 
+    @Test
     public void testGetAttributionIdWithoutWorkChain() {
         WorkSource ws1 = new WorkSource(100);
         ws1.add(200);
@@ -365,6 +393,7 @@
         assertEquals(100, ws2.getAttributionUid());
     }
 
+    @Test
     public void testGetAttributionWhenEmpty() {
         WorkSource ws = new WorkSource();
         assertEquals(-1, ws.getAttributionUid());
@@ -374,6 +403,7 @@
         assertNull(wc.getAttributionTag());
     }
 
+    @Test
     public void testGetAttributionTag() {
         WorkSource ws1 = new WorkSource();
         WorkChain wc = ws1.createWorkChain();
@@ -383,6 +413,7 @@
         assertEquals("tag", wc.getAttributionTag());
     }
 
+    @Test
     public void testRemove_fromChainedWorkSource() {
         WorkSource ws1 = new WorkSource();
         ws1.createWorkChain().addNode(50, "foo");
@@ -403,6 +434,7 @@
         assertEquals(75, ws1.getWorkChains().get(0).getAttributionUid());
     }
 
+    @Test
     public void testRemove_fromSameWorkSource() {
         WorkSource ws1 = new WorkSource(50, "foo");
         WorkSource ws2 = ws1;
@@ -414,6 +446,7 @@
         assertEquals("foo", ws1.getPackageName(0));
     }
 
+    @Test
     public void testTransferWorkChains() {
         WorkSource ws1 = new WorkSource();
         WorkChain wc1 = ws1.createWorkChain().addNode(100, "tag");
diff --git a/core/tests/coretests/src/android/provider/DeviceConfigTest.java b/core/tests/coretests/src/android/provider/DeviceConfigTest.java
index 7c4136d..9300d1e 100644
--- a/core/tests/coretests/src/android/provider/DeviceConfigTest.java
+++ b/core/tests/coretests/src/android/provider/DeviceConfigTest.java
@@ -831,6 +831,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 299483542)
     public void onPropertiesChangedListener_setPropertiesCallback() {
         DeviceConfig.setProperty(NAMESPACE, KEY, VALUE, false);
         DeviceConfig.setProperty(NAMESPACE, KEY2, VALUE2, false);
diff --git a/core/tests/coretests/src/android/service/notification/ConditionTest.java b/core/tests/coretests/src/android/service/notification/ConditionTest.java
index 612562e..e94273e 100644
--- a/core/tests/coretests/src/android/service/notification/ConditionTest.java
+++ b/core/tests/coretests/src/android/service/notification/ConditionTest.java
@@ -21,9 +21,12 @@
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.fail;
 
+import static org.junit.Assert.assertThrows;
+
 import android.app.Flags;
 import android.net.Uri;
 import android.os.Parcel;
+import android.platform.test.annotations.EnableFlags;
 import android.platform.test.flag.junit.SetFlagsRule;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -36,6 +39,7 @@
 import org.junit.runner.RunWith;
 
 import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
@@ -194,4 +198,59 @@
         Condition fromParcel = new Condition(parcel);
         assertThat(fromParcel).isEqualTo(cond);
     }
+
+    @Test
+    @EnableFlags(Flags.FLAG_MODES_API)
+    public void constructor_unspecifiedSource_succeeds() {
+        new Condition(Uri.parse("id"), "Summary", Condition.STATE_TRUE);
+        // No exception.
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_MODES_API)
+    public void constructor_validSource_succeeds() {
+        new Condition(Uri.parse("id"), "Summary", Condition.STATE_TRUE, Condition.SOURCE_CONTEXT);
+        // No exception.
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_MODES_API)
+    public void constructor_invalidSource_throws() {
+        assertThrows(IllegalArgumentException.class,
+                () -> new Condition(Uri.parse("uri"), "Summary", Condition.STATE_TRUE, 1000));
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_MODES_API)
+    public void constructor_parcelWithInvalidSource_throws() {
+        Condition original = new Condition(Uri.parse("condition"), "Summary", Condition.STATE_TRUE,
+                Condition.SOURCE_SCHEDULE);
+        Parcel parcel = Parcel.obtain();
+        original.writeToParcel(parcel, 0);
+
+        // Tweak the parcel to contain and invalid source value.
+        parcel.setDataPosition(parcel.dataPosition() - 8); // going back two int fields.
+        parcel.writeInt(100);
+        parcel.setDataPosition(0);
+
+        assertThrows(IllegalArgumentException.class, () -> new Condition(parcel));
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_MODES_API)
+    public void validate_invalidSource_throws() throws Exception {
+        Condition condition = new Condition(Uri.parse("condition"), "Summary", Condition.STATE_TRUE,
+                Condition.SOURCE_SCHEDULE);
+
+        Field typeField = Condition.class.getDeclaredField("source");
+
+        // Reflection on reflection (ugh) to make a final field non-final
+        Field fieldAccessFlagsField = Field.class.getDeclaredField("accessFlags");
+        fieldAccessFlagsField.setAccessible(true);
+        fieldAccessFlagsField.setInt(typeField, typeField.getModifiers() & ~Modifier.FINAL);
+
+        typeField.setInt(condition, 30);
+
+        assertThrows(IllegalArgumentException.class, condition::validate);
+    }
 }
diff --git a/core/tests/coretests/src/android/util/ArrayMapTest.java b/core/tests/coretests/src/android/util/ArrayMapTest.java
index b212cf6..1e444ad 100644
--- a/core/tests/coretests/src/android/util/ArrayMapTest.java
+++ b/core/tests/coretests/src/android/util/ArrayMapTest.java
@@ -14,11 +14,17 @@
 
 package android.util;
 
+import static org.junit.Assert.fail;
+
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
+
 import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
 
-import junit.framework.TestCase;
-
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.util.ConcurrentModificationException;
 
@@ -26,10 +32,14 @@
  * Unit tests for ArrayMap that don't belong in CTS.
  */
 @LargeTest
-public class ArrayMapTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+public class ArrayMapTest {
     private static final String TAG = "ArrayMapTest";
     ArrayMap<String, String> map = new ArrayMap<>();
 
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     /**
      * Attempt to generate a ConcurrentModificationException in ArrayMap.
      * <p>
@@ -41,6 +51,7 @@
      * @throws Exception
      */
     @Test
+    @IgnoreUnderRavenwood(reason = "Long test runtime")
     public void testConcurrentModificationException() throws Exception {
         final int TEST_LEN_MS = 5000;
         System.out.println("Starting ArrayMap concurrency test");
diff --git a/core/tests/coretests/src/android/util/ArraySetTest.java b/core/tests/coretests/src/android/util/ArraySetTest.java
index f1bebfb..51de634 100644
--- a/core/tests/coretests/src/android/util/ArraySetTest.java
+++ b/core/tests/coretests/src/android/util/ArraySetTest.java
@@ -16,12 +16,14 @@
 
 package android.util;
 
-import androidx.test.filters.LargeTest;
+import static org.junit.Assert.fail;
 
-import junit.framework.TestCase;
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.util.ConcurrentModificationException;
 
@@ -29,7 +31,8 @@
  * Unit tests for ArraySet that don't belong in CTS.
  */
 @LargeTest
-public class ArraySetTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+public class ArraySetTest {
     private static final String TAG = "ArraySetTest";
     ArraySet<String> mSet = new ArraySet<>();
 
diff --git a/core/tests/coretests/src/android/util/Base64Test.java b/core/tests/coretests/src/android/util/Base64Test.java
index 15c51af..b648266 100644
--- a/core/tests/coretests/src/android/util/Base64Test.java
+++ b/core/tests/coretests/src/android/util/Base64Test.java
@@ -16,9 +16,16 @@
 
 package android.util;
 
-import androidx.test.filters.LargeTest;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
 
-import junit.framework.TestCase;
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
@@ -32,7 +39,8 @@
 import java.util.stream.Collectors;
 
 @LargeTest
-public class Base64Test extends TestCase {
+@RunWith(AndroidJUnit4.class)
+public class Base64Test {
     private static final String TAG = "Base64Test";
 
     /** Decodes a string, returning a string. */
@@ -62,7 +70,7 @@
     }
 
     /** Assert that actual equals the first len bytes of expected. */
-    private void assertEquals(byte[] expected, int len, byte[] actual) {
+    private void assertPartialEquals(byte[] expected, int len, byte[] actual) {
         assertEquals(len, actual.length);
         for (int i = 0; i < len; ++i) {
             assertEquals(expected[i], actual[i]);
@@ -70,21 +78,14 @@
     }
 
     /** Assert that actual equals the first len bytes of expected. */
-    private void assertEquals(byte[] expected, int len, byte[] actual, int alen) {
+    private void assertPartialEquals(byte[] expected, int len, byte[] actual, int alen) {
         assertEquals(len, alen);
         for (int i = 0; i < len; ++i) {
             assertEquals(expected[i], actual[i]);
         }
     }
 
-    /** Assert that actual equals the first len bytes of expected. */
-    private void assertEquals(byte[] expected, byte[] actual) {
-        assertEquals(expected.length, actual.length);
-        for (int i = 0; i < expected.length; ++i) {
-            assertEquals(expected[i], actual[i]);
-        }
-    }
-
+    @Test
     public void testDecodeExtraChars() throws Exception {
         // padding 0
         assertEquals("hello, world", decodeString("aGVsbG8sIHdvcmxk"));
@@ -131,28 +132,30 @@
                                           (byte) 0xcc, (byte) 0xbb, (byte) 0xaa,
                                           (byte) 0x99, (byte) 0x88, (byte) 0x77 };
 
+    @Test
     public void testBinaryDecode() throws Exception {
-        assertEquals(BYTES, 0, Base64.decode("", 0));
-        assertEquals(BYTES, 1, Base64.decode("/w==", 0));
-        assertEquals(BYTES, 2, Base64.decode("/+4=", 0));
-        assertEquals(BYTES, 3, Base64.decode("/+7d", 0));
-        assertEquals(BYTES, 4, Base64.decode("/+7dzA==", 0));
-        assertEquals(BYTES, 5, Base64.decode("/+7dzLs=", 0));
-        assertEquals(BYTES, 6, Base64.decode("/+7dzLuq", 0));
-        assertEquals(BYTES, 7, Base64.decode("/+7dzLuqmQ==", 0));
-        assertEquals(BYTES, 8, Base64.decode("/+7dzLuqmYg=", 0));
+        assertPartialEquals(BYTES, 0, Base64.decode("", 0));
+        assertPartialEquals(BYTES, 1, Base64.decode("/w==", 0));
+        assertPartialEquals(BYTES, 2, Base64.decode("/+4=", 0));
+        assertPartialEquals(BYTES, 3, Base64.decode("/+7d", 0));
+        assertPartialEquals(BYTES, 4, Base64.decode("/+7dzA==", 0));
+        assertPartialEquals(BYTES, 5, Base64.decode("/+7dzLs=", 0));
+        assertPartialEquals(BYTES, 6, Base64.decode("/+7dzLuq", 0));
+        assertPartialEquals(BYTES, 7, Base64.decode("/+7dzLuqmQ==", 0));
+        assertPartialEquals(BYTES, 8, Base64.decode("/+7dzLuqmYg=", 0));
     }
 
+    @Test
     public void testWebSafe() throws Exception {
-        assertEquals(BYTES, 0, Base64.decode("", Base64.URL_SAFE));
-        assertEquals(BYTES, 1, Base64.decode("_w==", Base64.URL_SAFE));
-        assertEquals(BYTES, 2, Base64.decode("_-4=", Base64.URL_SAFE));
-        assertEquals(BYTES, 3, Base64.decode("_-7d", Base64.URL_SAFE));
-        assertEquals(BYTES, 4, Base64.decode("_-7dzA==", Base64.URL_SAFE));
-        assertEquals(BYTES, 5, Base64.decode("_-7dzLs=", Base64.URL_SAFE));
-        assertEquals(BYTES, 6, Base64.decode("_-7dzLuq", Base64.URL_SAFE));
-        assertEquals(BYTES, 7, Base64.decode("_-7dzLuqmQ==", Base64.URL_SAFE));
-        assertEquals(BYTES, 8, Base64.decode("_-7dzLuqmYg=", Base64.URL_SAFE));
+        assertPartialEquals(BYTES, 0, Base64.decode("", Base64.URL_SAFE));
+        assertPartialEquals(BYTES, 1, Base64.decode("_w==", Base64.URL_SAFE));
+        assertPartialEquals(BYTES, 2, Base64.decode("_-4=", Base64.URL_SAFE));
+        assertPartialEquals(BYTES, 3, Base64.decode("_-7d", Base64.URL_SAFE));
+        assertPartialEquals(BYTES, 4, Base64.decode("_-7dzA==", Base64.URL_SAFE));
+        assertPartialEquals(BYTES, 5, Base64.decode("_-7dzLs=", Base64.URL_SAFE));
+        assertPartialEquals(BYTES, 6, Base64.decode("_-7dzLuq", Base64.URL_SAFE));
+        assertPartialEquals(BYTES, 7, Base64.decode("_-7dzLuqmQ==", Base64.URL_SAFE));
+        assertPartialEquals(BYTES, 8, Base64.decode("_-7dzLuqmYg=", Base64.URL_SAFE));
 
         assertEquals("", Base64.encodeToString(BYTES, 0, 0, Base64.URL_SAFE));
         assertEquals("_w==\n", Base64.encodeToString(BYTES, 0, 1, Base64.URL_SAFE));
@@ -165,6 +168,7 @@
         assertEquals("_-7dzLuqmYg=\n", Base64.encodeToString(BYTES, 0, 8, Base64.URL_SAFE));
     }
 
+    @Test
     public void testFlags() throws Exception {
         assertEquals("YQ==\n",       encodeToString("a", 0));
         assertEquals("YQ==",         encodeToString("a", Base64.NO_WRAP));
@@ -195,6 +199,7 @@
         assertEquals("YWJjZA\r\n",   encodeToString("abcd", Base64.CRLF | Base64.NO_PADDING));
     }
 
+    @Test
     public void testLineLength() throws Exception {
         String in_56 = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd";
         String in_57 = in_56 + "e";
@@ -245,7 +250,9 @@
      * us to get at package-private members (Base64.Encoder in
      * this case).
      */
-    public void XXXtestEncodeInternal() throws Exception {
+    @Test
+    @Ignore
+    public void testEncodeInternal() throws Exception {
         byte[] input = { (byte) 0x61, (byte) 0x62, (byte) 0x63 };
         byte[] output = new byte[100];
 
@@ -253,11 +260,11 @@
                                                     output);
 
         encoder.process(input, 0, 3, false);
-        assertEquals("YWJj".getBytes(), 4, encoder.output, encoder.op);
+        assertPartialEquals("YWJj".getBytes(), 4, encoder.output, encoder.op);
         assertEquals(0, encoder.tailLen);
 
         encoder.process(input, 0, 3, false);
-        assertEquals("YWJj".getBytes(), 4, encoder.output, encoder.op);
+        assertPartialEquals("YWJj".getBytes(), 4, encoder.output, encoder.op);
         assertEquals(0, encoder.tailLen);
 
         encoder.process(input, 0, 1, false);
@@ -269,7 +276,7 @@
         assertEquals(2, encoder.tailLen);
 
         encoder.process(input, 0, 1, false);
-        assertEquals("YWFh".getBytes(), 4, encoder.output, encoder.op);
+        assertPartialEquals("YWFh".getBytes(), 4, encoder.output, encoder.op);
         assertEquals(0, encoder.tailLen);
 
         encoder.process(input, 0, 2, false);
@@ -277,15 +284,15 @@
         assertEquals(2, encoder.tailLen);
 
         encoder.process(input, 0, 2, false);
-        assertEquals("YWJh".getBytes(), 4, encoder.output, encoder.op);
+        assertPartialEquals("YWJh".getBytes(), 4, encoder.output, encoder.op);
         assertEquals(1, encoder.tailLen);
 
         encoder.process(input, 0, 2, false);
-        assertEquals("YmFi".getBytes(), 4, encoder.output, encoder.op);
+        assertPartialEquals("YmFi".getBytes(), 4, encoder.output, encoder.op);
         assertEquals(0, encoder.tailLen);
 
         encoder.process(input, 0, 1, true);
-        assertEquals("YQ".getBytes(), 2, encoder.output, encoder.op);
+        assertPartialEquals("YQ".getBytes(), 2, encoder.output, encoder.op);
     }
 
     private static final String lipsum =
@@ -311,6 +318,7 @@
             "molestie dapibus commodo. Ut vel tellus at massa gravida " +
             "semper non sed orci.";
 
+    @Test
     public void testInputStream() throws Exception {
         int[] flagses = { Base64.DEFAULT,
                           Base64.NO_PADDING,
@@ -343,7 +351,7 @@
             while ((b = b64is.read(actual, ap, actual.length-ap)) != -1) {
                 ap += b;
             }
-            assertEquals(actual, ap, plain);
+            assertPartialEquals(actual, ap, plain);
 
             // read individual bytes
             bais = new ByteArrayInputStream(encoded);
@@ -352,7 +360,7 @@
             while ((b = b64is.read()) != -1) {
                 actual[ap++] = (byte) b;
             }
-            assertEquals(actual, ap, plain);
+            assertPartialEquals(actual, ap, plain);
 
             // mix reads of variously-sized arrays with one-byte reads
             bais = new ByteArrayInputStream(encoded);
@@ -371,7 +379,7 @@
                     }
                 }
             }
-            assertEquals(actual, ap, plain);
+            assertPartialEquals(actual, ap, plain);
 
             // ----- test encoding ("plain" -> "encoded") -----
 
@@ -382,7 +390,7 @@
             while ((b = b64is.read(actual, ap, actual.length-ap)) != -1) {
                 ap += b;
             }
-            assertEquals(actual, ap, encoded);
+            assertPartialEquals(actual, ap, encoded);
 
             // read individual bytes
             bais = new ByteArrayInputStream(plain);
@@ -391,7 +399,7 @@
             while ((b = b64is.read()) != -1) {
                 actual[ap++] = (byte) b;
             }
-            assertEquals(actual, ap, encoded);
+            assertPartialEquals(actual, ap, encoded);
 
             // mix reads of variously-sized arrays with one-byte reads
             bais = new ByteArrayInputStream(plain);
@@ -410,11 +418,12 @@
                     }
                 }
             }
-            assertEquals(actual, ap, encoded);
+            assertPartialEquals(actual, ap, encoded);
         }
     }
 
     /** http://b/3026478 */
+    @Test
     public void testSingleByteReads() throws IOException {
         InputStream in = new Base64InputStream(
                 new ByteArrayInputStream("/v8=".getBytes()), Base64.DEFAULT);
@@ -426,6 +435,7 @@
      * Tests that Base64OutputStream produces exactly the same results
      * as calling Base64.encode/.decode on an in-memory array.
      */
+    @Test
     public void testOutputStream() throws Exception {
         int[] flagses = { Base64.DEFAULT,
                           Base64.NO_PADDING,
@@ -456,7 +466,7 @@
             b64os.write(plain);
             b64os.close();
             actual = baos.toByteArray();
-            assertEquals(encoded, actual);
+            assertArrayEquals(encoded, actual);
 
             // many calls to write(int)
             baos = new ByteArrayOutputStream();
@@ -466,7 +476,7 @@
             }
             b64os.close();
             actual = baos.toByteArray();
-            assertEquals(encoded, actual);
+            assertArrayEquals(encoded, actual);
 
             // intermixed sequences of write(int) with
             // write(byte[],int,int) of various lengths.
@@ -489,7 +499,7 @@
             }
             b64os.close();
             actual = baos.toByteArray();
-            assertEquals(encoded, actual);
+            assertArrayEquals(encoded, actual);
 
             // ----- test decoding ("encoded" -> "plain") -----
 
@@ -499,7 +509,7 @@
             b64os.write(encoded);
             b64os.close();
             actual = baos.toByteArray();
-            assertEquals(plain, actual);
+            assertArrayEquals(plain, actual);
 
             // many calls to write(int)
             baos = new ByteArrayOutputStream();
@@ -509,7 +519,7 @@
             }
             b64os.close();
             actual = baos.toByteArray();
-            assertEquals(plain, actual);
+            assertArrayEquals(plain, actual);
 
             // intermixed sequences of write(int) with
             // write(byte[],int,int) of various lengths.
@@ -532,10 +542,11 @@
             }
             b64os.close();
             actual = baos.toByteArray();
-            assertEquals(plain, actual);
+            assertArrayEquals(plain, actual);
         }
     }
 
+    @Test
     public void testOutputStream_ioExceptionDuringClose() {
         OutputStream out = new OutputStream() {
             @Override public void write(int b) throws IOException { }
@@ -551,6 +562,7 @@
         }
     }
 
+    @Test
     public void testOutputStream_ioExceptionDuringCloseAndWrite() {
         OutputStream out = new OutputStream() {
             @Override public void write(int b) throws IOException {
@@ -583,6 +595,7 @@
         }
     }
 
+    @Test
     public void testOutputStream_ioExceptionDuringWrite() {
         OutputStream out = new OutputStream() {
             @Override public void write(int b) throws IOException {
diff --git a/core/tests/coretests/src/android/util/CharsetUtilsTest.java b/core/tests/coretests/src/android/util/CharsetUtilsTest.java
index c295451..fbbe311 100644
--- a/core/tests/coretests/src/android/util/CharsetUtilsTest.java
+++ b/core/tests/coretests/src/android/util/CharsetUtilsTest.java
@@ -18,6 +18,9 @@
 
 import static org.junit.Assert.assertEquals;
 
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
+
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.util.HexDump;
@@ -25,18 +28,25 @@
 import dalvik.system.VMRuntime;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 @RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = CharsetUtils.class)
 public class CharsetUtilsTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     private byte[] dest;
     private long destPtr;
 
     @Before
     public void setUp() {
-        dest = (byte[]) VMRuntime.getRuntime().newNonMovableArray(byte.class, 8);
-        destPtr = VMRuntime.getRuntime().addressOf(dest);
+        if (!RavenwoodRule.isUnderRavenwood()) {
+            dest = (byte[]) VMRuntime.getRuntime().newNonMovableArray(byte.class, 8);
+            destPtr = VMRuntime.getRuntime().addressOf(dest);
+        }
     }
 
     @Test
diff --git a/core/tests/coretests/src/android/util/CloseGuardTest.java b/core/tests/coretests/src/android/util/CloseGuardTest.java
index d86c7b7..15c57b1 100644
--- a/core/tests/coretests/src/android/util/CloseGuardTest.java
+++ b/core/tests/coretests/src/android/util/CloseGuardTest.java
@@ -16,6 +16,9 @@
 
 package android.util;
 
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
+
 import libcore.dalvik.system.CloseGuardSupport;
 
 import org.junit.Rule;
@@ -23,10 +26,21 @@
 import org.junit.rules.TestRule;
 
 /** Unit tests for {@link android.util.CloseGuard} */
+@IgnoreUnderRavenwood(blockedBy = CloseGuard.class)
 public class CloseGuardTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
 
     @Rule
-    public final TestRule rule = CloseGuardSupport.getRule();
+    public final TestRule rule;
+
+    public CloseGuardTest() {
+        if (!RavenwoodRule.isUnderRavenwood()) {
+            rule = CloseGuardSupport.getRule();
+        } else {
+            rule = null;
+        }
+    }
 
     @Test
     public void testEnabled_NotOpen() throws Throwable {
diff --git a/core/tests/coretests/src/android/util/DayOfMonthCursorTest.java b/core/tests/coretests/src/android/util/DayOfMonthCursorTest.java
index 572e9b0..72bd578 100644
--- a/core/tests/coretests/src/android/util/DayOfMonthCursorTest.java
+++ b/core/tests/coretests/src/android/util/DayOfMonthCursorTest.java
@@ -16,30 +16,40 @@
 
 package android.util;
 
-import androidx.test.filters.SmallTest;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
-import junit.framework.TestCase;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.util.Calendar;
 
 /**
  * Unit tests for {@link DayOfMonthCursor}.
  */
-public class DayOfMonthCursorTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+public class DayOfMonthCursorTest {
 
+    @Test
     @SmallTest
     public void testMonthRows() {
         DayOfMonthCursor mc = new DayOfMonthCursor(2007,
                 Calendar.SEPTEMBER, 11, Calendar.SUNDAY);
 
-        assertArraysEqual(new int[]{26, 27, 28, 29, 30, 31, 1},
+        assertArrayEquals(new int[]{26, 27, 28, 29, 30, 31, 1},
                 mc.getDigitsForRow(0));
-        assertArraysEqual(new int[]{2, 3, 4, 5, 6, 7, 8},
+        assertArrayEquals(new int[]{2, 3, 4, 5, 6, 7, 8},
                 mc.getDigitsForRow(1));
-        assertArraysEqual(new int[]{30, 1, 2, 3, 4, 5, 6},
+        assertArrayEquals(new int[]{30, 1, 2, 3, 4, 5, 6},
                 mc.getDigitsForRow(5));
     }
 
+    @Test
     @SmallTest
     public void testMoveLeft() {
         DayOfMonthCursor mc = new DayOfMonthCursor(2007,
@@ -70,6 +80,7 @@
         assertEquals(5, mc.getSelectedColumn());
     }
 
+    @Test
     @SmallTest
     public void testMoveRight() {
         DayOfMonthCursor mc = new DayOfMonthCursor(2007,
@@ -100,6 +111,7 @@
         assertEquals(1, mc.getSelectedColumn());
     }
 
+    @Test
     @SmallTest
     public void testMoveUp() {
         DayOfMonthCursor mc = new DayOfMonthCursor(2007,
@@ -124,6 +136,7 @@
         assertEquals(4, mc.getSelectedColumn());
     }
 
+    @Test
     @SmallTest
     public void testMoveDown() {
         DayOfMonthCursor mc = new DayOfMonthCursor(2007,
@@ -147,12 +160,4 @@
         assertEquals(1, mc.getSelectedRow());
         assertEquals(0, mc.getSelectedColumn());
     }
-
-    private void assertArraysEqual(int[] expected, int[] actual) {
-        assertEquals("array length", expected.length, actual.length);
-        for (int i = 0; i < expected.length; i++) {
-            assertEquals("index " + i,
-                    expected[i], actual[i]);
-        }
-    }
 }
diff --git a/core/tests/coretests/src/android/util/HashedStringCacheTest.java b/core/tests/coretests/src/android/util/HashedStringCacheTest.java
index 2292473..08c85ac 100644
--- a/core/tests/coretests/src/android/util/HashedStringCacheTest.java
+++ b/core/tests/coretests/src/android/util/HashedStringCacheTest.java
@@ -26,28 +26,37 @@
 import android.content.SharedPreferences;
 import android.os.Environment;
 import android.os.storage.StorageManager;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 
 import androidx.test.InstrumentationRegistry;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 
 import java.io.File;
 
-
 /**
  * Unit tests for {@link HashedStringCache}.
  */
+@IgnoreUnderRavenwood(blockedBy = HashedStringCache.class)
 public class HashedStringCacheTest {
     private static final String TAG = "HashedStringCacheTest";
     private Context mContext;
     private static final String TEST_STRING = "test_string";
 
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     @Before
     public void setup() {
-        mContext = null;
-        mContext = InstrumentationRegistry.getContext();
-        clearSharedPreferences();
+        if (!RavenwoodRule.isUnderRavenwood()) {
+            mContext = InstrumentationRegistry.getContext();
+            clearSharedPreferences();
+        } else {
+            mContext = null;
+        }
     }
 
     @Test
diff --git a/core/tests/coretests/src/android/util/LogNullabilityTest.java b/core/tests/coretests/src/android/util/LogNullabilityTest.java
index 370885d..475e347 100644
--- a/core/tests/coretests/src/android/util/LogNullabilityTest.java
+++ b/core/tests/coretests/src/android/util/LogNullabilityTest.java
@@ -19,6 +19,8 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.fail;
 
+import android.platform.test.ravenwood.RavenwoodRule;
+
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
@@ -35,8 +37,10 @@
         Log.i(null, "");
         Log.w(null, "");
         Log.e(null, "");
-        Log.wtf(null, "");
-        Log.wtfStack(null, "");
+        if (!RavenwoodRule.isUnderRavenwood()) {
+            Log.wtf(null, "");
+            Log.wtfStack(null, "");
+        }
         Log.println(Log.INFO, null, "");
 
         // Implicit assertions of not crashing.
@@ -49,7 +53,9 @@
         Log.i(null, "", new Throwable());
         Log.w(null, "", new Throwable());
         Log.e(null, "", new Throwable());
-        Log.wtf(null, "", new Throwable());
+        if (!RavenwoodRule.isUnderRavenwood()) {
+            Log.wtf(null, "", new Throwable());
+        }
         Log.printlns(Log.LOG_ID_MAIN, Log.INFO, null, "", new Throwable());
 
         // Implicit assertions of not crashing.
@@ -84,8 +90,10 @@
         } catch (NullPointerException expected) {
         }
 
-        Log.wtf("", (String) null);
-        Log.wtfStack("", (String) null);
+        if (!RavenwoodRule.isUnderRavenwood()) {
+            Log.wtf("", (String) null);
+            Log.wtfStack("", (String) null);
+        }
 
         // Implicit assertion of not crashing.
 
@@ -103,15 +111,10 @@
         Log.i("", null, new Throwable());
         Log.w("", null, new Throwable());
         Log.e("", null, new Throwable());
-        Log.wtf("", null, new Throwable());
-
-        // Implicit assertions of not crashing.
-
-        try {
-            Log.printlns(Log.LOG_ID_MAIN, Log.INFO, "", null, new Throwable());
-            fail();
-        } catch (NullPointerException expected) {
+        if (!RavenwoodRule.isUnderRavenwood()) {
+            Log.wtf("", null, new Throwable());
         }
+        Log.printlns(Log.LOG_ID_MAIN, Log.INFO, "", null, new Throwable());
     }
 
     @Test
@@ -121,7 +124,9 @@
         Log.i("", "", null);
         Log.w("", "", null);
         Log.e("", "", null);
-        Log.wtf("", "", null);
+        if (!RavenwoodRule.isUnderRavenwood()) {
+            Log.wtf("", "", null);
+        }
 
         // Warning has its own (String, Throwable) overload.
         Log.w("", (Throwable) null);
@@ -131,10 +136,12 @@
         // Implicit assertions of not crashing.
 
         // WTF has its own (String, Throwable) overload with different behavior.
-        try {
-            Log.wtf("", (Throwable) null);
-            fail();
-        } catch (NullPointerException expected) {
+        if (!RavenwoodRule.isUnderRavenwood()) {
+            try {
+                Log.wtf("", (Throwable) null);
+                fail();
+            } catch (NullPointerException expected) {
+            }
         }
     }
 
@@ -145,15 +152,10 @@
         Log.i("", null, null);
         Log.w("", null, null);
         Log.e("", null, null);
-        Log.wtf("", null, null);
-
-        // Implicit assertions of not crashing.
-
-        try {
-            Log.printlns(Log.LOG_ID_MAIN, Log.INFO, "", null, null);
-            fail();
-        } catch (NullPointerException expected) {
+        if (!RavenwoodRule.isUnderRavenwood()) {
+            Log.wtf("", null, null);
         }
+        Log.printlns(Log.LOG_ID_MAIN, Log.INFO, "", null, null);
     }
 
     @Test
diff --git a/core/tests/coretests/src/android/util/LogTest.java b/core/tests/coretests/src/android/util/LogTest.java
index d783c12..f9966a1 100644
--- a/core/tests/coretests/src/android/util/LogTest.java
+++ b/core/tests/coretests/src/android/util/LogTest.java
@@ -20,23 +20,24 @@
 import android.test.PerformanceTestCase;
 
 import androidx.test.filters.Suppress;
+import androidx.test.runner.AndroidJUnit4;
 
 import junit.framework.TestCase;
 
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 //This is an empty TestCase.
 @Suppress
-public class LogTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+public class LogTest {
     private static final String PROPERTY_TAG = "log.tag.LogTest";
     private static final String LOG_TAG = "LogTest";
 
-
-    // TODO: remove this test once we uncomment out the following test.
-    public void testLogTestDummy() {
-      return;
-    }
-
-
-    /* TODO: This test is commented out because we will not be able to set properities. Fix the test.
+    @Test
+    @Ignore
     public void testIsLoggable() {
         // First clear any SystemProperty setting for our test key.
         SystemProperties.set(PROPERTY_TAG, null);
@@ -129,8 +130,7 @@
         Assert.assertFalse(Log.isLoggable(LOG_TAG, Log.ERROR));
         Assert.assertFalse(Log.isLoggable(LOG_TAG, Log.ASSERT));
     }
-    */
-    
+
     public static class PerformanceTest extends TestCase implements PerformanceTestCase {
         private static final int ITERATIONS = 1000;
 
diff --git a/core/tests/coretests/src/android/util/LongSparseLongArrayTest.java b/core/tests/coretests/src/android/util/LongSparseLongArrayTest.java
index a1d48e6..9dbaae0d 100644
--- a/core/tests/coretests/src/android/util/LongSparseLongArrayTest.java
+++ b/core/tests/coretests/src/android/util/LongSparseLongArrayTest.java
@@ -16,9 +16,13 @@
 
 package android.util;
 
-import androidx.test.filters.LargeTest;
+import static org.junit.Assert.assertEquals;
 
-import junit.framework.TestCase;
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.util.HashMap;
 import java.util.Iterator;
@@ -29,9 +33,11 @@
  * Tests for {@link LongSparseLongArray}.
  */
 @LargeTest
-public class LongSparseLongArrayTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+public class LongSparseLongArrayTest {
     private static final String TAG = "LongSparseLongArrayTest";
 
+    @Test
     public void testSimplePut() throws Exception {
         final LongSparseLongArray array = new LongSparseLongArray(5);
         for (int i = 0; i < 48; i++) {
@@ -45,6 +51,7 @@
         }
     }
 
+    @Test
     public void testSimplePutBackwards() throws Exception {
         final LongSparseLongArray array = new LongSparseLongArray(5);
         for (int i = 47; i >= 0; i--) {
@@ -58,6 +65,7 @@
         }
     }
 
+    @Test
     public void testMiddleInsert() throws Exception {
         final LongSparseLongArray array = new LongSparseLongArray(5);
         for (int i = 0; i < 48; i++) {
@@ -74,6 +82,7 @@
         assertEquals(1024, array.get(special, -1));
     }
 
+    @Test
     public void testFuzz() throws Exception {
         final Random r = new Random();
 
diff --git a/core/tests/coretests/src/android/util/LruCacheTest.java b/core/tests/coretests/src/android/util/LruCacheTest.java
index 1928bfd..10e8308 100644
--- a/core/tests/coretests/src/android/util/LruCacheTest.java
+++ b/core/tests/coretests/src/android/util/LruCacheTest.java
@@ -16,7 +16,14 @@
 
 package android.util;
 
-import junit.framework.TestCase;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.fail;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -24,13 +31,15 @@
 import java.util.List;
 import java.util.Map;
 
-public final class LruCacheTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+public final class LruCacheTest {
     private int expectedCreateCount;
     private int expectedPutCount;
     private int expectedHitCount;
     private int expectedMissCount;
     private int expectedEvictionCount;
 
+    @Test
     public void testStatistics() {
         LruCache<String, String> cache = new LruCache<String, String>(3);
         assertStatistics(cache);
@@ -80,6 +89,7 @@
         assertSnapshot(cache, "e", "E", "b", "B", "c", "C");
     }
 
+    @Test
     public void testStatisticsWithCreate() {
         LruCache<String, String> cache = newCreatingCache();
         assertStatistics(cache);
@@ -104,18 +114,21 @@
         assertSnapshot(cache, "cc", "created-cc", "dd", "created-dd", "aa", "created-aa");
     }
 
+    @Test
     public void testCreateOnCacheMiss() {
         LruCache<String, String> cache = newCreatingCache();
         String created = cache.get("aa");
         assertEquals("created-aa", created);
     }
 
+    @Test
     public void testNoCreateOnCacheHit() {
         LruCache<String, String> cache = newCreatingCache();
         cache.put("aa", "put-aa");
         assertEquals("put-aa", cache.get("aa"));
     }
 
+    @Test
     public void testConstructorDoesNotAllowZeroCacheSize() {
         try {
             new LruCache<String, String>(0);
@@ -124,6 +137,7 @@
         }
     }
 
+    @Test
     public void testCannotPutNullKey() {
         LruCache<String, String> cache = new LruCache<String, String>(3);
         try {
@@ -133,6 +147,7 @@
         }
     }
 
+    @Test
     public void testCannotPutNullValue() {
         LruCache<String, String> cache = new LruCache<String, String>(3);
         try {
@@ -142,6 +157,7 @@
         }
     }
 
+    @Test
     public void testToString() {
         LruCache<String, String> cache = new LruCache<String, String>(3);
         assertEquals("LruCache[maxSize=3,hits=0,misses=0,hitRate=0%]", cache.toString());
@@ -160,6 +176,7 @@
         assertEquals("LruCache[maxSize=3,hits=3,misses=2,hitRate=60%]", cache.toString());
     }
 
+    @Test
     public void testEvictionWithSingletonCache() {
         LruCache<String, String> cache = new LruCache<String, String>(1);
         cache.put("a", "A");
@@ -167,6 +184,7 @@
         assertSnapshot(cache, "b", "B");
     }
 
+    @Test
     public void testEntryEvictedWhenFull() {
         List<String> log = new ArrayList<String>();
         LruCache<String, String> cache = newRemovalLogCache(log);
@@ -184,6 +202,7 @@
      * Replacing the value for a key doesn't cause an eviction but it does bring
      * the replaced entry to the front of the queue.
      */
+    @Test
     public void testPutCauseEviction() {
         List<String> log = new ArrayList<String>();
         LruCache<String, String> cache = newRemovalLogCache(log);
@@ -196,6 +215,7 @@
         assertSnapshot(cache, "a", "A", "c", "C", "b", "B2");
     }
 
+    @Test
     public void testCustomSizesImpactsSize() {
         LruCache<String, String> cache = new LruCache<String, String>(10) {
             @Override protected int sizeOf(String key, String value) {
@@ -212,6 +232,7 @@
         assertEquals(6, cache.size());
     }
 
+    @Test
     public void testEvictionWithCustomSizes() {
         LruCache<String, String> cache = new LruCache<String, String>(4) {
             @Override protected int sizeOf(String key, String value) {
@@ -241,6 +262,7 @@
         assertSnapshot(cache, "j", "JJJ");
     }
 
+    @Test
     public void testEvictionThrowsWhenSizesAreInconsistent() {
         LruCache<String, int[]> cache = new LruCache<String, int[]>(4) {
             @Override protected int sizeOf(String key, int[] value) {
@@ -263,6 +285,7 @@
         }
     }
 
+    @Test
     public void testEvictionThrowsWhenSizesAreNegative() {
         LruCache<String, String> cache = new LruCache<String, String>(4) {
             @Override protected int sizeOf(String key, String value) {
@@ -282,6 +305,7 @@
      * because evicting a small element may be insufficient to make room for a
      * large element.
      */
+    @Test
     public void testDifferentElementSizes() {
         LruCache<String, String> cache = new LruCache<String, String>(10) {
             @Override protected int sizeOf(String key, String value) {
@@ -299,6 +323,7 @@
         assertSnapshot(cache, "e", "12345678");
     }
 
+    @Test
     public void testEvictAll() {
         List<String> log = new ArrayList<String>();
         LruCache<String, String> cache = newRemovalLogCache(log);
@@ -310,6 +335,7 @@
         assertEquals(Arrays.asList("a=A", "b=B", "c=C"), log);
     }
 
+    @Test
     public void testEvictAllEvictsSizeZeroElements() {
         LruCache<String, String> cache = new LruCache<String, String>(10) {
             @Override protected int sizeOf(String key, String value) {
@@ -323,6 +349,7 @@
         assertSnapshot(cache);
     }
 
+    @Test
     public void testRemoveWithCustomSizes() {
         LruCache<String, String> cache = new LruCache<String, String>(10) {
             @Override protected int sizeOf(String key, String value) {
@@ -335,6 +362,7 @@
         assertEquals(4, cache.size());
     }
 
+    @Test
     public void testRemoveAbsentElement() {
         LruCache<String, String> cache = new LruCache<String, String>(10);
         cache.put("a", "A");
@@ -343,6 +371,7 @@
         assertEquals(2, cache.size());
     }
 
+    @Test
     public void testRemoveNullThrows() {
         LruCache<String, String> cache = new LruCache<String, String>(10);
         try {
@@ -352,6 +381,7 @@
         }
     }
 
+    @Test
     public void testRemoveCallsEntryRemoved() {
         List<String> log = new ArrayList<String>();
         LruCache<String, String> cache = newRemovalLogCache(log);
@@ -360,6 +390,7 @@
         assertEquals(Arrays.asList("a=A>null"), log);
     }
 
+    @Test
     public void testPutCallsEntryRemoved() {
         List<String> log = new ArrayList<String>();
         LruCache<String, String> cache = newRemovalLogCache(log);
@@ -368,6 +399,7 @@
         assertEquals(Arrays.asList("a=A>A2"), log);
     }
 
+    @Test
     public void testEntryRemovedIsCalledWithoutSynchronization() {
         LruCache<String, String> cache = new LruCache<String, String>(3) {
             @Override protected void entryRemoved(
@@ -385,6 +417,7 @@
         cache.evictAll();     // multiple eviction
     }
 
+    @Test
     public void testCreateIsCalledWithoutSynchronization() {
         LruCache<String, String> cache = new LruCache<String, String>(3) {
             @Override protected String create(String key) {
@@ -401,6 +434,7 @@
      * working. The map value should be returned by get(), and the created value
      * should be released with entryRemoved().
      */
+    @Test
     public void testCreateWithConcurrentPut() {
         final List<String> log = new ArrayList<String>();
         LruCache<String, String> cache = new LruCache<String, String>(3) {
@@ -423,6 +457,7 @@
      * the first create to return is returned by both gets. The other created
      * values should be released with entryRemove().
      */
+    @Test
     public void testCreateWithConcurrentCreate() {
         final List<String> log = new ArrayList<String>();
         LruCache<String, Integer> cache = new LruCache<String, Integer>(3) {
diff --git a/core/tests/coretests/src/android/util/MonthDisplayHelperTest.java b/core/tests/coretests/src/android/util/MonthDisplayHelperTest.java
index 30d5f77..06f970f 100644
--- a/core/tests/coretests/src/android/util/MonthDisplayHelperTest.java
+++ b/core/tests/coretests/src/android/util/MonthDisplayHelperTest.java
@@ -16,18 +16,26 @@
 
 package android.util;
 
-import androidx.test.filters.SmallTest;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
-import junit.framework.TestCase;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.util.Calendar;
 
 /**
  * Unit tests for {@link MonthDisplayHelper}.
  */
-public class MonthDisplayHelperTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+public class MonthDisplayHelperTest {
 
 
+    @Test
     @SmallTest
     public void testFirstDayOfMonth() {
 
@@ -40,12 +48,14 @@
                 new MonthDisplayHelper(2007, Calendar.SEPTEMBER).getFirstDayOfMonth());
     }
 
+    @Test
     @SmallTest
     public void testNumberOfDaysInCurrentMonth() {
         assertEquals(30,
                 new MonthDisplayHelper(2007, Calendar.SEPTEMBER).getNumberOfDaysInMonth());
     }
 
+    @Test
     @SmallTest
     public void testMonthRows() {
         MonthDisplayHelper helper = new MonthDisplayHelper(2007, Calendar.SEPTEMBER);
@@ -59,6 +69,7 @@
 
     }
 
+    @Test
     @SmallTest
     public void testMonthRowsWeekStartsMonday() {
         MonthDisplayHelper helper = new MonthDisplayHelper(2007,
@@ -74,6 +85,7 @@
                 helper.getDigitsForRow(5));
     }
 
+    @Test
     @SmallTest
     public void testMonthRowsWeekStartsSaturday() {
         MonthDisplayHelper helper = new MonthDisplayHelper(2007,
@@ -98,6 +110,7 @@
                 helper.getDigitsForRow(4));
     }
 
+    @Test
     @SmallTest
     public void testGetDayAt() {
         MonthDisplayHelper helper = new MonthDisplayHelper(2007,
@@ -109,6 +122,7 @@
         assertEquals(2, helper.getDayAt(5, 2));
     }
 
+    @Test
     @SmallTest
     public void testPrevMonth() {
         MonthDisplayHelper helper = new MonthDisplayHelper(2007,
@@ -124,6 +138,7 @@
                 helper.getDigitsForRow(0));
     }
 
+    @Test
     @SmallTest
     public void testPrevMonthRollOver() {
         MonthDisplayHelper helper = new MonthDisplayHelper(2007,
@@ -135,6 +150,7 @@
         assertEquals(Calendar.DECEMBER, helper.getMonth());
     }
 
+    @Test
     @SmallTest
     public void testNextMonth() {
         MonthDisplayHelper helper = new MonthDisplayHelper(2007,
@@ -150,6 +166,7 @@
                 helper.getDigitsForRow(0));
     }
 
+    @Test
     @SmallTest
     public void testGetRowOf() {
         MonthDisplayHelper helper = new MonthDisplayHelper(2007,
@@ -162,6 +179,7 @@
         assertEquals(3, helper.getRowOf(19));
     }
 
+    @Test
     @SmallTest
     public void testGetColumnOf() {
         MonthDisplayHelper helper = new MonthDisplayHelper(2007,
@@ -174,6 +192,7 @@
         assertEquals(0, helper.getColumnOf(26));
     }
 
+    @Test
     @SmallTest
     public void testWithinCurrentMonth() {
         MonthDisplayHelper helper = new MonthDisplayHelper(2007,
diff --git a/core/tests/coretests/src/android/util/NtpTrustedTimeTest.java b/core/tests/coretests/src/android/util/NtpTrustedTimeTest.java
index 4de27c3..ce1eabc 100644
--- a/core/tests/coretests/src/android/util/NtpTrustedTimeTest.java
+++ b/core/tests/coretests/src/android/util/NtpTrustedTimeTest.java
@@ -31,10 +31,15 @@
 import static java.util.Arrays.asList;
 
 import android.net.Network;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
 
+import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.InOrder;
@@ -51,7 +56,10 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = NtpTrustedTime.class)
 public class NtpTrustedTimeTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
 
     private static final Duration VALID_TIMEOUT = Duration.ofSeconds(5);
 
diff --git a/core/tests/coretests/src/android/util/PatternsTest.java b/core/tests/coretests/src/android/util/PatternsTest.java
index dd8f73f..a180ec3 100644
--- a/core/tests/coretests/src/android/util/PatternsTest.java
+++ b/core/tests/coretests/src/android/util/PatternsTest.java
@@ -16,17 +16,25 @@
 
 package android.util;
 
-import androidx.test.filters.SmallTest;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
-import junit.framework.TestCase;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-public class PatternsTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+public class PatternsTest {
 
     // Tests for Patterns.TOP_LEVEL_DOMAIN
 
+    @Test
     @SmallTest
     public void testTldPattern() throws Exception {
         boolean t;
@@ -58,36 +66,42 @@
 
     // Tests for Patterns.IANA_TOP_LEVEL_DOMAINS
 
+    @Test
     @SmallTest
     public void testIanaTopLevelDomains_matchesValidTld() throws Exception {
         Pattern pattern = Pattern.compile(Patterns.IANA_TOP_LEVEL_DOMAINS);
         assertTrue("Should match 'com'", pattern.matcher("com").matches());
     }
 
+    @Test
     @SmallTest
     public void testIanaTopLevelDomains_matchesValidNewTld() throws Exception {
         Pattern pattern = Pattern.compile(Patterns.IANA_TOP_LEVEL_DOMAINS);
         assertTrue("Should match 'me'", pattern.matcher("me").matches());
     }
 
+    @Test
     @SmallTest
     public void testIanaTopLevelDomains_matchesPunycodeTld() throws Exception {
         Pattern pattern = Pattern.compile(Patterns.IANA_TOP_LEVEL_DOMAINS);
         assertTrue("Should match Punycode TLD", pattern.matcher("xn--qxam").matches());
     }
 
+    @Test
     @SmallTest
     public void testIanaTopLevelDomains_matchesIriTLD() throws Exception {
         Pattern pattern = Pattern.compile(Patterns.IANA_TOP_LEVEL_DOMAINS);
         assertTrue("Should match IRI TLD", pattern.matcher("\uD55C\uAD6D").matches());
     }
 
+    @Test
     @SmallTest
     public void testIanaTopLevelDomains_doesNotMatchWrongTld() throws Exception {
         Pattern pattern = Pattern.compile(Patterns.IANA_TOP_LEVEL_DOMAINS);
         assertFalse("Should not match 'mem'", pattern.matcher("mem").matches());
     }
 
+    @Test
     @SmallTest
     public void testIanaTopLevelDomains_doesNotMatchWrongPunycodeTld() throws Exception {
         Pattern pattern = Pattern.compile(Patterns.IANA_TOP_LEVEL_DOMAINS);
@@ -96,6 +110,7 @@
 
     // Tests for Patterns.WEB_URL
 
+    @Test
     @SmallTest
     public void testWebUrl_matchesValidUrlWithSchemeAndHostname() throws Exception {
         String url = "http://www.android.com";
@@ -103,6 +118,7 @@
                 Patterns.WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testWebUrl_matchesValidUrlWithSchemeHostnameAndNewTld() throws Exception {
         String url = "http://www.android.me";
@@ -110,6 +126,7 @@
                 Patterns.WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testWebUrl_matchesValidUrlWithHostnameAndNewTld() throws Exception {
         String url = "android.me";
@@ -117,6 +134,7 @@
                 Patterns.WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testWebUrl_matchesChinesePunycodeUrlWithProtocol() throws Exception {
         String url = "http://xn--fsqu00a.xn--0zwm56d";
@@ -124,6 +142,7 @@
                 Patterns.WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testWebUrl_matchesChinesePunycodeUrlWithoutProtocol() throws Exception {
         String url = "xn--fsqu00a.xn--0zwm56d";
@@ -131,6 +150,7 @@
                 Patterns.WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testWebUrl_matchesArabicPunycodeUrlWithProtocol() throws Exception {
         String url = "http://xn--4gbrim.xn----rmckbbajlc6dj7bxne2c.xn--wgbh1c/ar/default.aspx";
@@ -138,6 +158,7 @@
                 Patterns.WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testWebUrl_matchesArabicPunycodeUrlWithoutProtocol() throws Exception {
         String url = "xn--4gbrim.xn----rmckbbajlc6dj7bxne2c.xn--wgbh1c/ar/default.aspx";
@@ -145,6 +166,7 @@
                 Patterns.WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testWebUrl_matchesUrlWithUnicodeDomainNameWithProtocol() throws Exception {
         String url = "http://\uD604\uAE08\uC601\uC218\uC99D.kr";
@@ -152,6 +174,7 @@
                 Patterns.WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testWebUrl_matchesUrlWithUnicodeDomainNameWithoutProtocol() throws Exception {
         String url = "\uD604\uAE08\uC601\uC218\uC99D.kr";
@@ -159,6 +182,7 @@
                 Patterns.WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testWebUrl_matchesUrlWithUnicodeTld() throws Exception {
         String url = "\uB3C4\uBA54\uC778.\uD55C\uAD6D";
@@ -166,6 +190,7 @@
                 Patterns.WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testWebUrl_matchesUrlWithUnicodePath() throws Exception {
         String url = "http://brainstormtech.blogs.fortune.cnn.com/2010/03/11/" +
@@ -174,19 +199,22 @@
                 Patterns.WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testWebUrl_doesNotMatchValidUrlWithInvalidProtocol() throws Exception {
-        String url = "ftp://www.example.com";
+        String url = "invalid://www.example.com";
         assertFalse("Should not match URL with invalid protocol",
                 Patterns.WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testWebUrl_matchesValidUrlWithPort() throws Exception {
         String url = "http://www.example.com:8080";
         assertTrue("Should match URL with port", Patterns.WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testWebUrl_matchesUrlWithPortAndQuery() throws Exception {
         String url = "http://www.example.com:8080/?foo=bar";
@@ -194,12 +222,14 @@
                 Patterns.WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testWebUrl_matchesUrlWithTilde() throws Exception {
         String url = "http://www.example.com:8080/~user/?foo=bar";
         assertTrue("Should match URL with tilde", Patterns.WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testWebUrl_matchesProtocolCaseInsensitive() throws Exception {
         String url = "hTtP://android.com";
@@ -207,6 +237,7 @@
                 Patterns.WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testWebUrl_matchesDomainNameWithDash() throws Exception {
         String url = "http://a-nd.r-oid.com";
@@ -218,6 +249,7 @@
                 Patterns.WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testWebUrl_matchesDomainNameWithUnderscore() throws Exception {
         String url = "http://a_nd.r_oid.com";
@@ -229,6 +261,7 @@
                 Patterns.WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testWebUrl_matchesPathAndQueryWithDollarSign() throws Exception {
         String url = "http://android.com/path$?v=$val";
@@ -240,6 +273,7 @@
                 Patterns.WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testWebUrl_matchesEmptyPathWithQueryParams() throws Exception {
         String url = "http://android.com?q=v";
@@ -261,6 +295,7 @@
 
     // Tests for Patterns.AUTOLINK_WEB_URL
 
+    @Test
     @SmallTest
     public void testAutoLinkWebUrl_matchesValidUrlWithSchemeAndHostname() throws Exception {
         String url = "http://www.android.com";
@@ -268,6 +303,7 @@
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkWebUrl_matchesValidUrlWithSchemeHostnameAndNewTld() throws Exception {
         String url = "http://www.android.me";
@@ -275,6 +311,7 @@
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkWebUrl_matchesValidUrlWithHostnameAndNewTld() throws Exception {
         String url = "android.me";
@@ -286,6 +323,7 @@
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkWebUrl_matchesChinesePunycodeUrlWithProtocol() throws Exception {
         String url = "http://xn--fsqu00a.xn--0zwm56d";
@@ -293,6 +331,7 @@
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkWebUrl_matchesChinesePunycodeUrlWithoutProtocol() throws Exception {
         String url = "xn--fsqu00a.xn--0zwm56d";
@@ -300,6 +339,7 @@
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkWebUrl_matchesArabicPunycodeUrlWithProtocol() throws Exception {
         String url = "http://xn--4gbrim.xn--rmckbbajlc6dj7bxne2c.xn--wgbh1c/ar/default.aspx";
@@ -307,6 +347,7 @@
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkWebUrl_matchesArabicPunycodeUrlWithoutProtocol() throws Exception {
         String url = "xn--4gbrim.xn--rmckbbajlc6dj7bxne2c.xn--wgbh1c/ar/default.aspx";
@@ -314,6 +355,7 @@
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkWebUrl_doesNotMatchPunycodeTldThatStartsWithDash() throws Exception {
         String url = "http://xn--fsqu00a.-xn--0zwm56d";
@@ -321,6 +363,7 @@
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkWebUrl_doesNotMatchPunycodeTldThatEndsWithDash() throws Exception {
         String url = "http://xn--fsqu00a.xn--0zwm56d-";
@@ -328,6 +371,7 @@
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkWebUrl_matchesUrlWithUnicodeDomainName() throws Exception {
         String url = "http://\uD604\uAE08\uC601\uC218\uC99D.kr";
@@ -339,6 +383,7 @@
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkWebUrl_matchesUrlWithUnicodeTld() throws Exception {
         String url = "\uB3C4\uBA54\uC778.\uD55C\uAD6D";
@@ -346,6 +391,7 @@
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkWebUrl_matchesUrlWithUnicodePath() throws Exception {
         String url = "http://brainstormtech.blogs.fortune.cnn.com/2010/03/11/" +
@@ -354,13 +400,15 @@
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkWebUrl_doesNotMatchValidUrlWithInvalidProtocol() throws Exception {
-        String url = "ftp://www.example.com";
+        String url = "invalid://www.example.com";
         assertFalse("Should not match URL with invalid protocol",
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkWebUrl_matchesValidUrlWithPort() throws Exception {
         String url = "http://www.example.com:8080";
@@ -368,6 +416,7 @@
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkWebUrl_matchesUrlWithPortAndQuery() throws Exception {
         String url = "http://www.example.com:8080/?foo=bar";
@@ -375,6 +424,7 @@
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkWebUrl_matchesUrlWithTilde() throws Exception {
         String url = "http://www.example.com:8080/~user/?foo=bar";
@@ -382,6 +432,7 @@
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkWebUrl_matchesProtocolCaseInsensitive() throws Exception {
         String url = "hTtP://android.com";
@@ -389,6 +440,7 @@
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkWebUrl_matchesUrlStartingWithHttpAndDoesNotHaveTld() throws Exception {
         String url = "http://android/#notld///a/n/d/r/o/i/d&p1=1&p2=2";
@@ -396,6 +448,7 @@
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkWebUrl_doesNotMatchUrlsWithoutProtocolAndWithUnknownTld()
             throws Exception {
@@ -405,13 +458,15 @@
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkWebUrl_doesNotPartiallyMatchUnknownProtocol() throws Exception {
-        String url = "ftp://foo.bar/baz";
+        String url = "invalid://foo.bar/baz";
         assertFalse("Should not partially match URL with unknown protocol",
                 Patterns.AUTOLINK_WEB_URL.matcher(url).find());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkWebUrl_matchesValidUrlWithEmoji() throws Exception {
         String url = "Thank\u263A.com";
@@ -419,6 +474,7 @@
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkWebUrl_doesNotMatchUrlsWithEmojiWithoutProtocolAndWithoutKnownTld()
             throws Exception {
@@ -427,6 +483,7 @@
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkWebUrl_doesNotMatchEmailAddress()
             throws Exception {
@@ -435,6 +492,7 @@
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkWebUrl_matchesDomainNameWithSurrogatePairs() throws Exception {
         String url = "android\uD83C\uDF38.com";
@@ -442,6 +500,7 @@
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkWebUrl_matchesTldWithSurrogatePairs() throws Exception {
         String url = "http://android.\uD83C\uDF38com";
@@ -449,6 +508,7 @@
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkWebUrl_matchesPathWithSurrogatePairs() throws Exception {
         String url = "http://android.com/path-with-\uD83C\uDF38?v=\uD83C\uDF38";
@@ -456,6 +516,7 @@
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkWebUrl_doesNotMatchUrlWithExcludedSurrogate() throws Exception {
         String url = "http://android\uD83F\uDFFE.com";
@@ -463,6 +524,7 @@
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkWebUrl_doesNotMatchUnicodeSpaces() throws Exception {
         String part1 = "http://and";
@@ -493,6 +555,7 @@
         }
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkWebUrl_matchesDomainNameWithDash() throws Exception {
         String url = "http://a-nd.r-oid.com";
@@ -504,6 +567,7 @@
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkWebUrl_matchesDomainNameWithUnderscore() throws Exception {
         String url = "http://a_nd.r_oid.com";
@@ -515,6 +579,7 @@
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkWebUrl_matchesPathAndQueryWithDollarSign() throws Exception {
         String url = "http://android.com/path$?v=$val";
@@ -526,6 +591,7 @@
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkWebUrl_matchesEmptyPathWithQueryParams() throws Exception {
         String url = "http://android.com?q=v";
@@ -547,6 +613,7 @@
 
     // Tests for Patterns.IP_ADDRESS
 
+    @Test
     @SmallTest
     public void testIpPattern() throws Exception {
         boolean t;
@@ -560,6 +627,7 @@
 
     // Tests for Patterns.DOMAIN_NAME
 
+    @Test
     @SmallTest
     public void testDomain_matchesPunycodeTld() throws Exception {
         String domain = "xn--fsqu00a.xn--0zwm56d";
@@ -567,6 +635,7 @@
                 Patterns.DOMAIN_NAME.matcher(domain).matches());
     }
 
+    @Test
     @SmallTest
     public void testDomain_doesNotMatchPunycodeThatStartsWithDash() throws Exception {
         String domain = "xn--fsqu00a.-xn--0zwm56d";
@@ -574,6 +643,7 @@
                 Patterns.DOMAIN_NAME.matcher(domain).matches());
     }
 
+    @Test
     @SmallTest
     public void testDomain_doesNotMatchPunycodeThatEndsWithDash() throws Exception {
         String domain = "xn--fsqu00a.xn--0zwm56d-";
@@ -581,6 +651,7 @@
                 Patterns.DOMAIN_NAME.matcher(domain).matches());
     }
 
+    @Test
     @SmallTest
     public void testDomain_doesNotMatchPunycodeLongerThanAllowed() throws Exception {
         String tld = "xn--";
@@ -592,6 +663,7 @@
                 Patterns.DOMAIN_NAME.matcher(domain).matches());
     }
 
+    @Test
     @SmallTest
     public void testDomain_matchesObsoleteTld() throws Exception {
         String domain = "test.yu";
@@ -599,6 +671,7 @@
                 Patterns.DOMAIN_NAME.matcher(domain).matches());
     }
 
+    @Test
     @SmallTest
     public void testDomain_matchesWithSubDomain() throws Exception {
         String domain = "mail.example.com";
@@ -606,6 +679,7 @@
                 Patterns.DOMAIN_NAME.matcher(domain).matches());
     }
 
+    @Test
     @SmallTest
     public void testDomain_matchesWithoutSubDomain() throws Exception {
         String domain = "android.me";
@@ -613,6 +687,7 @@
                 Patterns.DOMAIN_NAME.matcher(domain).matches());
     }
 
+    @Test
     @SmallTest
     public void testDomain_matchesUnicodeDomainNames() throws Exception {
         String domain = "\uD604\uAE08\uC601\uC218\uC99D.kr";
@@ -620,6 +695,7 @@
                 Patterns.DOMAIN_NAME.matcher(domain).matches());
     }
 
+    @Test
     @SmallTest
     public void testDomain_doesNotMatchInvalidDomain() throws Exception {
         String domain = "__+&42.xer";
@@ -627,6 +703,7 @@
                 Patterns.DOMAIN_NAME.matcher(domain).matches());
     }
 
+    @Test
     @SmallTest
     public void testDomain_matchesPunycodeArabicDomainName() throws Exception {
         String domain = "xn--4gbrim.xn----rmckbbajlc6dj7bxne2c.xn--wgbh1c";
@@ -634,6 +711,7 @@
                 Patterns.DOMAIN_NAME.matcher(domain).matches());
     }
 
+    @Test
     @SmallTest
     public void testDomain_matchesDomainNameWithDash() throws Exception {
         String url = "http://a-nd.r-oid.com";
@@ -645,6 +723,7 @@
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
     }
 
+    @Test
     @SmallTest
     public void testDomain_matchesDomainNameWithUnderscore() throws Exception {
         String url = "http://a_nd.r_oid.com";
@@ -658,6 +737,7 @@
 
     // Tests for Patterns.AUTOLINK_EMAIL_ADDRESS
 
+    @Test
     @SmallTest
     public void testAutoLinkEmailAddress_matchesShortValidEmail() throws Exception {
         String email = "a@a.co";
@@ -665,6 +745,7 @@
                 Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkEmailAddress_matchesRegularEmail() throws Exception {
         String email = "email@android.com";
@@ -672,6 +753,7 @@
                 Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkEmailAddress_matchesEmailWithMultipleSubdomains() throws Exception {
         String email = "email@e.somelongdomainnameforandroid.abc.uk";
@@ -679,6 +761,7 @@
                 Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkEmailAddress_matchesLocalPartWithDot() throws Exception {
         String email = "e.mail@android.com";
@@ -686,6 +769,7 @@
                 Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkEmailAddress_matchesLocalPartWithPlus() throws Exception {
         String email = "e+mail@android.com";
@@ -693,6 +777,7 @@
                 Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkEmailAddress_matchesLocalPartWithUnderscore() throws Exception {
         String email = "e_mail@android.com";
@@ -700,6 +785,7 @@
                 Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkEmailAddress_matchesLocalPartWithDash() throws Exception {
         String email = "e-mail@android.com";
@@ -707,6 +793,7 @@
                 Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkEmailAddress_matchesLocalPartWithApostrophe() throws Exception {
         String email = "e'mail@android.com";
@@ -714,6 +801,7 @@
                 Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkEmailAddress_matchesLocalPartWithDigits() throws Exception {
         String email = "123@android.com";
@@ -721,6 +809,7 @@
                 Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkEmailAddress_matchesUnicodeLocalPart() throws Exception {
         String email = "\uD604\uAE08\uC601\uC218\uC99D@android.kr";
@@ -728,6 +817,7 @@
                 Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkEmailAddress_matchesLocalPartWithEmoji() throws Exception {
         String email = "smiley\u263A@android.com";
@@ -735,6 +825,7 @@
                 Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkEmailAddress_matchesLocalPartWithSurrogatePairs() throws Exception {
         String email = "\uD83C\uDF38@android.com";
@@ -742,6 +833,7 @@
                 Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkEmailAddress_matchesDomainWithDash() throws Exception {
         String email = "email@an-droid.com";
@@ -749,6 +841,7 @@
                 Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkEmailAddress_matchesUnicodeDomain() throws Exception {
         String email = "email@\uD604\uAE08\uC601\uC218\uC99D.kr";
@@ -756,6 +849,7 @@
                 Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkEmailAddress_matchesUnicodeLocalPartAndDomain() throws Exception {
         String email = "\uD604\uAE08\uC601\uC218\uC99D@\uD604\uAE08\uC601\uC218\uC99D.kr";
@@ -763,6 +857,7 @@
                 Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkEmailAddress_matchesDomainWithEmoji() throws Exception {
         String email = "smiley@\u263Aandroid.com";
@@ -770,6 +865,7 @@
                 Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkEmailAddress_matchesDomainWithSurrogatePairs() throws Exception {
         String email = "email@\uD83C\uDF38android.com";
@@ -777,6 +873,7 @@
                 Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkEmailAddress_matchesLocalPartAndDomainWithSurrogatePairs()
             throws Exception {
@@ -785,6 +882,7 @@
                 Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkEmailAddress_doesNotMatchStringWithoutAtSign() throws Exception {
         String email = "android.com";
@@ -792,6 +890,7 @@
                 Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkEmailAddress_doesNotMatchPlainString() throws Exception {
         String email = "email";
@@ -799,6 +898,7 @@
                 Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkEmailAddress_doesNotMatchStringWithMultipleAtSigns() throws Exception {
         String email = "email@android@android.com";
@@ -806,6 +906,7 @@
                 Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkEmailAddress_doesNotMatchEmailWithoutTld() throws Exception {
         String email = "email@android";
@@ -813,6 +914,7 @@
                 Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkEmailAddress_doesNotMatchLocalPartEndingWithDot() throws Exception {
         String email = "email.@android.com";
@@ -820,6 +922,7 @@
                 Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkEmailAddress_doesNotMatchLocalPartStartingWithDot() throws Exception {
         String email = ".email@android.com";
@@ -827,6 +930,7 @@
                 Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkEmailAddress_doesNotMatchDomainStartingWithDash() throws Exception {
         String email = "email@-android.com";
@@ -834,6 +938,7 @@
                 Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkEmailAddress_doesNotMatchDomainWithConsecutiveDots() throws Exception {
         String email = "email@android..com";
@@ -841,6 +946,7 @@
                 Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkEmailAddress_doesNotMatchEmailWithIpAsDomain() throws Exception {
         String email = "email@127.0.0.1";
@@ -848,6 +954,7 @@
                 Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkEmailAddress_doesNotMatchEmailWithInvalidTld() throws Exception {
         String email = "email@android.c";
@@ -855,6 +962,7 @@
                 Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkEmailAddress_matchesLocalPartUpTo64Chars() throws Exception {
         String localPart = "";
@@ -871,6 +979,7 @@
                 Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkEmailAddress_matchesSubdomainUpTo63Chars() throws Exception {
         String subdomain = "";
@@ -888,6 +997,7 @@
                 Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
     }
 
+    @Test
     @SmallTest
     public void testAutoLinkEmailAddress_matchesDomainUpTo255Chars() throws Exception {
         String longDomain = "";
@@ -909,6 +1019,7 @@
 
     // Tests for Patterns.PHONE
 
+    @Test
     @SmallTest
     public void testPhonePattern() throws Exception {
         boolean t;
diff --git a/core/tests/coretests/src/android/util/RecurrenceRuleTest.java b/core/tests/coretests/src/android/util/RecurrenceRuleTest.java
index caa1208..32548b4 100644
--- a/core/tests/coretests/src/android/util/RecurrenceRuleTest.java
+++ b/core/tests/coretests/src/android/util/RecurrenceRuleTest.java
@@ -16,9 +16,17 @@
 
 package android.util;
 
-import androidx.test.filters.SmallTest;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
-import junit.framework.TestCase;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.time.Clock;
 import java.time.Instant;
@@ -28,19 +36,18 @@
 import java.util.Iterator;
 
 @SmallTest
-public class RecurrenceRuleTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+public class RecurrenceRuleTest {
 
     static Clock sOriginalClock;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @Before
+    public void setUp() throws Exception {
         sOriginalClock = RecurrenceRule.sClock;
     }
 
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
+    @After
+    public void tearDown() throws Exception {
         RecurrenceRule.sClock = sOriginalClock;
     }
 
@@ -48,6 +55,7 @@
         RecurrenceRule.sClock = Clock.fixed(instant, ZoneId.systemDefault());
     }
 
+    @Test
     public void testSimpleMonth() throws Exception {
         setClock(Instant.parse("2015-11-20T10:15:30.00Z"));
         final RecurrenceRule r = new RecurrenceRule(
@@ -68,6 +76,7 @@
                 ZonedDateTime.parse("2015-11-14T00:00:00.00Z")), it.next());
     }
 
+    @Test
     public void testSimpleDays() throws Exception {
         setClock(Instant.parse("2015-01-01T10:15:30.00Z"));
         final RecurrenceRule r = new RecurrenceRule(
@@ -89,6 +98,7 @@
         assertFalse(it.hasNext());
     }
 
+    @Test
     public void testNotRecurring() throws Exception {
         setClock(Instant.parse("2015-01-01T10:15:30.00Z"));
         final RecurrenceRule r = new RecurrenceRule(
@@ -106,6 +116,7 @@
         assertFalse(it.hasNext());
     }
 
+    @Test
     public void testNever() throws Exception {
         setClock(Instant.parse("2015-01-01T10:15:30.00Z"));
         final RecurrenceRule r = RecurrenceRule.buildNever();
@@ -116,6 +127,7 @@
         assertFalse(it.hasNext());
     }
 
+    @Test
     public void testSane() throws Exception {
         final RecurrenceRule r = new RecurrenceRule(
                 ZonedDateTime.parse("1980-01-31T00:00:00.000Z"),
diff --git a/core/tests/coretests/src/android/util/SparseSetArrayTest.java b/core/tests/coretests/src/android/util/SparseSetArrayTest.java
index 3c17486a..1c72185 100644
--- a/core/tests/coretests/src/android/util/SparseSetArrayTest.java
+++ b/core/tests/coretests/src/android/util/SparseSetArrayTest.java
@@ -17,9 +17,13 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
+
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -29,7 +33,11 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class SparseSetArrayTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     @Test
+    @IgnoreUnderRavenwood(reason = "Flaky test, b/315872700")
     public void testAddAll() {
         final SparseSetArray<Integer> sparseSetArray = new SparseSetArray<>();
 
@@ -51,6 +59,7 @@
     }
 
     @Test
+    @IgnoreUnderRavenwood(reason = "b/315036461")
     public void testCopyConstructor() {
         final SparseSetArray<Integer> sparseSetArray = new SparseSetArray<>();
 
diff --git a/core/tests/coretests/src/android/util/StateSetTest.java b/core/tests/coretests/src/android/util/StateSetTest.java
index b5d6270..dfd1523 100644
--- a/core/tests/coretests/src/android/util/StateSetTest.java
+++ b/core/tests/coretests/src/android/util/StateSetTest.java
@@ -16,16 +16,29 @@
 
 package android.util;
 
-import androidx.test.filters.SmallTest;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
-import junit.framework.TestCase;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 /**
  * Tests for {@link StateSet}
  */
+@RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = StateSet.class)
+public class StateSetTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
 
-public class StateSetTest extends TestCase {
-    
+    @Test
     @SmallTest
     public void testStateSetPositiveMatches() throws Exception {
          int[] stateSpec = new int[2];
@@ -48,6 +61,7 @@
          assertTrue(StateSet.stateSetMatches(stateSpec, stateSet));
      }
 
+     @Test
      @SmallTest
      public void testStatesSetMatchMixEmUp() throws Exception {
          int[] stateSpec = new int[2];
@@ -70,6 +84,7 @@
          assertTrue(StateSet.stateSetMatches(stateSpec, stateSet));
      }
 
+     @Test
      @SmallTest
      public void testStateSetNegativeMatches() throws Exception {
          int[] stateSpec = new int[2];
@@ -92,6 +107,7 @@
          assertFalse(StateSet.stateSetMatches(stateSpec, stateSet));
      }
 
+     @Test
      @SmallTest
      public void testEmptySetMatchesNegtives() throws Exception {
          int[] stateSpec = {-12345, -6789};
@@ -101,6 +117,7 @@
          assertTrue(StateSet.stateSetMatches(stateSpec, stateSet2));
      }
 
+     @Test
      @SmallTest
      public void testEmptySetFailsPositives() throws Exception {
          int[] stateSpec = {12345};
@@ -110,6 +127,7 @@
          assertFalse(StateSet.stateSetMatches(stateSpec, stateSet2));
      }
 
+     @Test
      @SmallTest
      public void testEmptySetMatchesWildcard() throws Exception {
          int[] stateSpec = StateSet.WILD_CARD;
@@ -119,6 +137,7 @@
          assertTrue(StateSet.stateSetMatches(stateSpec, stateSet2));
      }
 
+     @Test
      @SmallTest
      public void testSingleStatePositiveMatches() throws Exception {
          int[] stateSpec = new int[2];
@@ -135,6 +154,7 @@
          assertFalse(StateSet.stateSetMatches(stateSpec, state));
      }
 
+     @Test
      @SmallTest
      public void testSingleStateNegativeMatches() throws Exception {
          int[] stateSpec = new int[2];
@@ -151,6 +171,7 @@
          assertTrue(StateSet.stateSetMatches(stateSpec, state));
      }
 
+     @Test
      @SmallTest
      public void testZeroStateOnlyMatchesDefault() throws Exception {
          int[] stateSpec = new int[3];
@@ -166,6 +187,7 @@
          assertTrue(StateSet.stateSetMatches(stateSpec, state));
      }
 
+     @Test
      @SmallTest
      public void testNullStateOnlyMatchesDefault() throws Exception {
          int[] stateSpec = new int[3];
diff --git a/core/tests/coretests/src/android/util/apk/SourceStampVerifierTest.java b/core/tests/coretests/src/android/util/apk/SourceStampVerifierTest.java
index e0c583d..48e76f7 100644
--- a/core/tests/coretests/src/android/util/apk/SourceStampVerifierTest.java
+++ b/core/tests/coretests/src/android/util/apk/SourceStampVerifierTest.java
@@ -26,12 +26,16 @@
 import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
 
 import android.content.Context;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 
 import androidx.test.core.app.ApplicationProvider;
 
 import libcore.io.Streams;
 
 import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -48,13 +52,21 @@
 
 /** Unit test for {@link android.util.apk.SourceStampVerifier} */
 @RunWith(JUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = SourceStampVerifier.class)
 public class SourceStampVerifierTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
 
-    private final Context mContext = ApplicationProvider.getApplicationContext();
+    private Context mContext;
 
     private File mPrimaryApk;
     private File mSecondaryApk;
 
+    @Before
+    public void setUp() throws Exception {
+        mContext = ApplicationProvider.getApplicationContext();
+    }
+
     @After
     public void tearDown() throws Exception {
         if (mPrimaryApk != null) {
diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java
index 6172622..b30a0c8 100644
--- a/core/tests/coretests/src/android/view/ViewRootImplTest.java
+++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java
@@ -472,6 +472,7 @@
      * Test the value of the frame rate cateogry based on the visibility of a view
      * Invsible: FRAME_RATE_CATEGORY_NO_PREFERENCE
      * Visible: FRAME_RATE_CATEGORY_NORMAL
+     * Also, mIsFrameRateBoosting should be true when the visibility becomes visible
      */
     @Test
     @RequiresFlagsEnabled(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
@@ -485,6 +486,7 @@
             assertEquals(viewRootImpl.getPreferredFrameRateCategory(),
                     FRAME_RATE_CATEGORY_NO_PREFERENCE);
         });
+        sInstrumentation.waitForIdleSync();
 
         sInstrumentation.runOnMainSync(() -> {
             view.setVisibility(View.VISIBLE);
@@ -492,6 +494,11 @@
             assertEquals(viewRootImpl.getPreferredFrameRateCategory(),
                     FRAME_RATE_CATEGORY_NORMAL);
         });
+        sInstrumentation.waitForIdleSync();
+
+        sInstrumentation.runOnMainSync(() -> {
+            assertEquals(viewRootImpl.getIsFrameRateBoosting(), true);
+        });
     }
 
     /**
diff --git a/core/tests/coretests/src/android/view/inputmethod/InputMethodInfoTest.java b/core/tests/coretests/src/android/view/inputmethod/InputMethodInfoTest.java
index 7bef55e..909af7b 100644
--- a/core/tests/coretests/src/android/view/inputmethod/InputMethodInfoTest.java
+++ b/core/tests/coretests/src/android/view/inputmethod/InputMethodInfoTest.java
@@ -26,6 +26,7 @@
 import android.content.pm.ServiceInfo;
 import android.os.Bundle;
 import android.os.Parcel;
+import android.platform.test.flag.junit.SetFlagsRule;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
@@ -33,6 +34,7 @@
 
 import com.android.frameworks.coretests.R;
 
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -40,6 +42,10 @@
 @RunWith(AndroidJUnit4.class)
 public class InputMethodInfoTest {
 
+    @Rule
+    public SetFlagsRule mSetFlagsRule =
+            new SetFlagsRule(SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT);
+
     @Test
     public void testEqualsAndHashCode() throws Exception {
         final InputMethodInfo imi = buildInputMethodForTest(R.xml.ime_meta);
@@ -111,6 +117,19 @@
         assertThat(clone.isVrOnly(), is(true));
     }
 
+    @Test
+    public void testIsVirtualDeviceOnly() throws Exception {
+        mSetFlagsRule.enableFlags(android.companion.virtual.flags.Flags.FLAG_VDM_CUSTOM_IME);
+
+        final InputMethodInfo imi = buildInputMethodForTest(R.xml.ime_meta_virtual_device_only);
+
+        assertThat(imi.isVirtualDeviceOnly(), is(true));
+
+        final InputMethodInfo clone = cloneViaParcel(imi);
+
+        assertThat(clone.isVirtualDeviceOnly(), is(true));
+    }
+
     private InputMethodInfo buildInputMethodForTest(final @XmlRes int metaDataRes)
             throws Exception {
         final Context context = InstrumentationRegistry.getContext();
diff --git a/core/tests/coretests/src/android/view/menu/MenuScenario.java b/core/tests/coretests/src/android/view/menu/MenuScenario.java
index 668aec4..a1615af 100644
--- a/core/tests/coretests/src/android/view/menu/MenuScenario.java
+++ b/core/tests/coretests/src/android/view/menu/MenuScenario.java
@@ -18,7 +18,7 @@
 
 import android.app.Activity;
 import android.os.Bundle;
-import android.util.ListScenario;
+import android.widget.ListScenario;
 import android.util.SparseArray;
 import android.view.Menu;
 import android.view.MenuItem;
diff --git a/core/tests/coretests/src/android/util/GridScenario.java b/core/tests/coretests/src/android/widget/GridScenario.java
similarity index 99%
rename from core/tests/coretests/src/android/util/GridScenario.java
rename to core/tests/coretests/src/android/widget/GridScenario.java
index e7ee1cd..d740808 100644
--- a/core/tests/coretests/src/android/util/GridScenario.java
+++ b/core/tests/coretests/src/android/widget/GridScenario.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.util;
+package android.widget;
 
 import android.app.Activity;
 import android.os.Bundle;
diff --git a/core/tests/coretests/src/android/util/InternalSelectionView.java b/core/tests/coretests/src/android/widget/InternalSelectionView.java
similarity index 98%
rename from core/tests/coretests/src/android/util/InternalSelectionView.java
rename to core/tests/coretests/src/android/widget/InternalSelectionView.java
index 4a1baef..f2d3182 100644
--- a/core/tests/coretests/src/android/util/InternalSelectionView.java
+++ b/core/tests/coretests/src/android/widget/InternalSelectionView.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.util;
+package android.widget;
 
 import android.content.Context;
 import android.content.res.TypedArray;
@@ -22,6 +22,7 @@
 import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.Rect;
+import android.util.AttributeSet;
 import android.view.KeyEvent;
 import android.view.View;
 
diff --git a/core/tests/coretests/src/android/util/ListScenario.java b/core/tests/coretests/src/android/widget/ListScenario.java
similarity index 98%
rename from core/tests/coretests/src/android/util/ListScenario.java
rename to core/tests/coretests/src/android/widget/ListScenario.java
index 74dc4b4..589d90d 100644
--- a/core/tests/coretests/src/android/util/ListScenario.java
+++ b/core/tests/coretests/src/android/widget/ListScenario.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 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.
@@ -14,20 +14,15 @@
  * limitations under the License.
  */
 
-package android.util;
+package android.widget;
 
 import android.app.Activity;
 import android.graphics.Rect;
 import android.os.Bundle;
+import android.util.ListItemFactory;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.Window;
-import android.widget.AdapterView;
-import android.widget.BaseAdapter;
-import android.widget.EditText;
-import android.widget.LinearLayout;
-import android.widget.ListView;
-import android.widget.TextView;
 
 import com.google.android.collect.Maps;
 
diff --git a/core/tests/coretests/src/android/util/ScrollViewScenario.java b/core/tests/coretests/src/android/widget/ScrollViewScenario.java
similarity index 98%
rename from core/tests/coretests/src/android/util/ScrollViewScenario.java
rename to core/tests/coretests/src/android/widget/ScrollViewScenario.java
index ab1a642..ff2ab05 100644
--- a/core/tests/coretests/src/android/util/ScrollViewScenario.java
+++ b/core/tests/coretests/src/android/widget/ScrollViewScenario.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.util;
+package android.widget;
 
 import android.app.Activity;
 import android.content.Context;
@@ -23,6 +23,7 @@
 import android.view.ViewGroup;
 import android.view.Window;
 import android.widget.Button;
+import android.widget.InternalSelectionView;
 import android.widget.LinearLayout;
 import android.widget.ScrollView;
 import android.widget.TextView;
diff --git a/core/tests/coretests/src/android/widget/focus/AdjacentVerticalRectLists.java b/core/tests/coretests/src/android/widget/focus/AdjacentVerticalRectLists.java
index 85a4509..7e2f293 100644
--- a/core/tests/coretests/src/android/widget/focus/AdjacentVerticalRectLists.java
+++ b/core/tests/coretests/src/android/widget/focus/AdjacentVerticalRectLists.java
@@ -18,7 +18,7 @@
 
 import android.app.Activity;
 import android.os.Bundle;
-import android.util.InternalSelectionView;
+import android.widget.InternalSelectionView;
 import android.view.ViewGroup;
 import android.widget.LinearLayout;
 
@@ -30,7 +30,7 @@
  * rectangle of the previously focused view.  The view taking focus can use this
  * to set an internal selection more appropriate using this rect.
  *
- * This Activity excercises that behavior using three adjacent {@link android.util.InternalSelectionView}
+ * This Activity excercises that behavior using three adjacent {@link InternalSelectionView}
  * that report interesting rects when giving up focus, and use interesting rects
  * when taking focus to best select the internal row to show as selected.
  */
diff --git a/core/tests/coretests/src/android/widget/focus/FocusChangeWithInterestingRectHintTest.java b/core/tests/coretests/src/android/widget/focus/FocusChangeWithInterestingRectHintTest.java
index 26dc233..16a0b35 100644
--- a/core/tests/coretests/src/android/widget/focus/FocusChangeWithInterestingRectHintTest.java
+++ b/core/tests/coretests/src/android/widget/focus/FocusChangeWithInterestingRectHintTest.java
@@ -17,7 +17,7 @@
 package android.widget.focus;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.util.InternalSelectionView;
+import android.widget.InternalSelectionView;
 import android.view.KeyEvent;
 
 import androidx.test.filters.LargeTest;
@@ -31,7 +31,7 @@
  * rectangle of the previously focused view.  The view taking focus can use this
  * to set an internal selection more appropriate using this rect.
  *
- * This tests that behavior using three adjacent {@link android.util.InternalSelectionView}
+ * This tests that behavior using three adjacent {@link InternalSelectionView}
  * that report interesting rects when giving up focus, and use interesting rects
  * when taking focus to best select the internal row to show as selected.
  *
diff --git a/core/tests/coretests/src/android/widget/focus/ListOfInternalSelectionViews.java b/core/tests/coretests/src/android/widget/focus/ListOfInternalSelectionViews.java
index c5e69b6..4231b40 100644
--- a/core/tests/coretests/src/android/widget/focus/ListOfInternalSelectionViews.java
+++ b/core/tests/coretests/src/android/widget/focus/ListOfInternalSelectionViews.java
@@ -18,7 +18,7 @@
 
 import android.app.Activity;
 import android.os.Bundle;
-import android.util.InternalSelectionView;
+import android.widget.InternalSelectionView;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.BaseAdapter;
diff --git a/core/tests/coretests/src/android/widget/focus/ScrollingThroughListOfFocusablesTest.java b/core/tests/coretests/src/android/widget/focus/ScrollingThroughListOfFocusablesTest.java
index e6e76cc..46190c4 100644
--- a/core/tests/coretests/src/android/widget/focus/ScrollingThroughListOfFocusablesTest.java
+++ b/core/tests/coretests/src/android/widget/focus/ScrollingThroughListOfFocusablesTest.java
@@ -18,7 +18,7 @@
 
 import android.graphics.Rect;
 import android.test.InstrumentationTestCase;
-import android.util.InternalSelectionView;
+import android.widget.InternalSelectionView;
 import android.view.KeyEvent;
 import android.widget.ListView;
 
diff --git a/core/tests/coretests/src/android/widget/gridview/GridDelete.java b/core/tests/coretests/src/android/widget/gridview/GridDelete.java
index b040f69..5f4326c 100644
--- a/core/tests/coretests/src/android/widget/gridview/GridDelete.java
+++ b/core/tests/coretests/src/android/widget/gridview/GridDelete.java
@@ -16,7 +16,7 @@
 
 package android.widget.gridview;
 
-import android.util.GridScenario;
+import android.widget.GridScenario;
 import android.view.KeyEvent;
 import android.view.View;
 import android.view.ViewGroup;
diff --git a/core/tests/coretests/src/android/widget/gridview/GridSetSelection.java b/core/tests/coretests/src/android/widget/gridview/GridSetSelection.java
index a3cda3b..140dd7b 100644
--- a/core/tests/coretests/src/android/widget/gridview/GridSetSelection.java
+++ b/core/tests/coretests/src/android/widget/gridview/GridSetSelection.java
@@ -16,7 +16,7 @@
 
 package android.widget.gridview;
 
-import android.util.GridScenario;
+import android.widget.GridScenario;
 
 /**
  * Basic stacking from top scenario, nothing fancy. Items do not
diff --git a/core/tests/coretests/src/android/widget/gridview/GridSetSelectionBaseTest.java b/core/tests/coretests/src/android/widget/gridview/GridSetSelectionBaseTest.java
index db4f2dc..1428fea 100644
--- a/core/tests/coretests/src/android/widget/gridview/GridSetSelectionBaseTest.java
+++ b/core/tests/coretests/src/android/widget/gridview/GridSetSelectionBaseTest.java
@@ -18,7 +18,7 @@
 
 import android.test.ActivityInstrumentationTestCase;
 import android.test.ViewAsserts;
-import android.util.GridScenario;
+import android.widget.GridScenario;
 import android.widget.GridView;
 
 import androidx.test.filters.MediumTest;
diff --git a/core/tests/coretests/src/android/widget/gridview/GridSetSelectionMany.java b/core/tests/coretests/src/android/widget/gridview/GridSetSelectionMany.java
index a6d481f..7176619 100644
--- a/core/tests/coretests/src/android/widget/gridview/GridSetSelectionMany.java
+++ b/core/tests/coretests/src/android/widget/gridview/GridSetSelectionMany.java
@@ -16,7 +16,7 @@
 
 package android.widget.gridview;
 
-import android.util.GridScenario;
+import android.widget.GridScenario;
 
 /**
  * Basic stacking from top scenario, nothing fancy. Items do
diff --git a/core/tests/coretests/src/android/widget/gridview/GridSetSelectionStackFromBottom.java b/core/tests/coretests/src/android/widget/gridview/GridSetSelectionStackFromBottom.java
index dfcd5fc..01bb2be 100644
--- a/core/tests/coretests/src/android/widget/gridview/GridSetSelectionStackFromBottom.java
+++ b/core/tests/coretests/src/android/widget/gridview/GridSetSelectionStackFromBottom.java
@@ -16,7 +16,7 @@
 
 package android.widget.gridview;
 
-import android.util.GridScenario;
+import android.widget.GridScenario;
 
 /**
  * Basic stacking from bottom scenario, nothing fancy. Items do not
diff --git a/core/tests/coretests/src/android/widget/gridview/GridSetSelectionStackFromBottomMany.java b/core/tests/coretests/src/android/widget/gridview/GridSetSelectionStackFromBottomMany.java
index 26a567e..d79ee88 100644
--- a/core/tests/coretests/src/android/widget/gridview/GridSetSelectionStackFromBottomMany.java
+++ b/core/tests/coretests/src/android/widget/gridview/GridSetSelectionStackFromBottomMany.java
@@ -16,7 +16,7 @@
 
 package android.widget.gridview;
 
-import android.util.GridScenario;
+import android.widget.GridScenario;
 
 /**
  * Basic stacking from bottom scenario, nothing fancy. Items do
diff --git a/core/tests/coretests/src/android/widget/gridview/GridSimple.java b/core/tests/coretests/src/android/widget/gridview/GridSimple.java
index 67bb751..6ca7eaa 100644
--- a/core/tests/coretests/src/android/widget/gridview/GridSimple.java
+++ b/core/tests/coretests/src/android/widget/gridview/GridSimple.java
@@ -18,7 +18,7 @@
 
 import android.graphics.drawable.PaintDrawable;
 import android.os.Bundle;
-import android.util.GridScenario;
+import android.widget.GridScenario;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.TextView;
diff --git a/core/tests/coretests/src/android/widget/gridview/GridSingleColumn.java b/core/tests/coretests/src/android/widget/gridview/GridSingleColumn.java
index 566e71b..aaed9ba 100644
--- a/core/tests/coretests/src/android/widget/gridview/GridSingleColumn.java
+++ b/core/tests/coretests/src/android/widget/gridview/GridSingleColumn.java
@@ -16,7 +16,7 @@
 
 package android.widget.gridview;
 
-import android.util.GridScenario;
+import android.widget.GridScenario;
 import android.widget.GridView;
 
 /**
diff --git a/core/tests/coretests/src/android/widget/gridview/GridStackFromBottom.java b/core/tests/coretests/src/android/widget/gridview/GridStackFromBottom.java
index 2f0a88f..457b00d 100644
--- a/core/tests/coretests/src/android/widget/gridview/GridStackFromBottom.java
+++ b/core/tests/coretests/src/android/widget/gridview/GridStackFromBottom.java
@@ -16,7 +16,7 @@
 
 package android.widget.gridview;
 
-import android.util.GridScenario;
+import android.widget.GridScenario;
 
 /**
  * Basic bottom stacking from bottom scenario, nothing fancy. Items do not
diff --git a/core/tests/coretests/src/android/widget/gridview/GridStackFromBottomMany.java b/core/tests/coretests/src/android/widget/gridview/GridStackFromBottomMany.java
index 33a9592..9029bc5 100644
--- a/core/tests/coretests/src/android/widget/gridview/GridStackFromBottomMany.java
+++ b/core/tests/coretests/src/android/widget/gridview/GridStackFromBottomMany.java
@@ -16,7 +16,7 @@
 
 package android.widget.gridview;
 
-import android.util.GridScenario;
+import android.widget.GridScenario;
 
 /**
  * Basic bottom stacking from bottom scenario, nothing fancy. The grid items do not fit on the
diff --git a/core/tests/coretests/src/android/widget/gridview/GridVerticalSpacing.java b/core/tests/coretests/src/android/widget/gridview/GridVerticalSpacing.java
index 0d01d30..6aa864f 100644
--- a/core/tests/coretests/src/android/widget/gridview/GridVerticalSpacing.java
+++ b/core/tests/coretests/src/android/widget/gridview/GridVerticalSpacing.java
@@ -16,7 +16,7 @@
 
 package android.widget.gridview;
 
-import android.util.GridScenario;
+import android.widget.GridScenario;
 
 /**
  * A grid with vertical spacing between rows
diff --git a/core/tests/coretests/src/android/widget/gridview/GridVerticalSpacingStackFromBottom.java b/core/tests/coretests/src/android/widget/gridview/GridVerticalSpacingStackFromBottom.java
index bd68680..25ef682 100644
--- a/core/tests/coretests/src/android/widget/gridview/GridVerticalSpacingStackFromBottom.java
+++ b/core/tests/coretests/src/android/widget/gridview/GridVerticalSpacingStackFromBottom.java
@@ -16,7 +16,7 @@
 
 package android.widget.gridview;
 
-import android.util.GridScenario;
+import android.widget.GridScenario;
 
 /**
  * A grid with vertical spacing between rows that stacks from the bottom
diff --git a/core/tests/coretests/src/android/widget/listview/AdjacentListsWithAdjacentISVsInside.java b/core/tests/coretests/src/android/widget/listview/AdjacentListsWithAdjacentISVsInside.java
index 62b93d6..1e57d69 100644
--- a/core/tests/coretests/src/android/widget/listview/AdjacentListsWithAdjacentISVsInside.java
+++ b/core/tests/coretests/src/android/widget/listview/AdjacentListsWithAdjacentISVsInside.java
@@ -18,7 +18,7 @@
 
 import android.app.Activity;
 import android.os.Bundle;
-import android.util.InternalSelectionView;
+import android.widget.InternalSelectionView;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.BaseAdapter;
diff --git a/core/tests/coretests/src/android/widget/listview/ListBottomGravity.java b/core/tests/coretests/src/android/widget/listview/ListBottomGravity.java
index cd76d70..5d319c5 100644
--- a/core/tests/coretests/src/android/widget/listview/ListBottomGravity.java
+++ b/core/tests/coretests/src/android/widget/listview/ListBottomGravity.java
@@ -16,7 +16,7 @@
 
 package android.widget.listview;
 
-import android.util.ListScenario;
+import android.widget.ListScenario;
 
 /**
  * Basic bottom gravity scenario, nothing fancy. Items do not
diff --git a/core/tests/coretests/src/android/widget/listview/ListBottomGravityMany.java b/core/tests/coretests/src/android/widget/listview/ListBottomGravityMany.java
index e048e3e..331fd12 100644
--- a/core/tests/coretests/src/android/widget/listview/ListBottomGravityMany.java
+++ b/core/tests/coretests/src/android/widget/listview/ListBottomGravityMany.java
@@ -16,7 +16,7 @@
 
 package android.widget.listview;
 
-import android.util.ListScenario;
+import android.widget.ListScenario;
 
 /**
  * Basic bottom gravity scenario, nothing fancy. There are
diff --git a/core/tests/coretests/src/android/widget/listview/ListButtonsDiagonalAcrossItems.java b/core/tests/coretests/src/android/widget/listview/ListButtonsDiagonalAcrossItems.java
index 8640741..bc7c19f 100644
--- a/core/tests/coretests/src/android/widget/listview/ListButtonsDiagonalAcrossItems.java
+++ b/core/tests/coretests/src/android/widget/listview/ListButtonsDiagonalAcrossItems.java
@@ -19,7 +19,7 @@
 import static android.util.ListItemFactory.Slot;
 
 import android.util.ListItemFactory;
-import android.util.ListScenario;
+import android.widget.ListScenario;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.Button;
diff --git a/core/tests/coretests/src/android/widget/listview/ListEndingWithMultipleSeparators.java b/core/tests/coretests/src/android/widget/listview/ListEndingWithMultipleSeparators.java
index 85f9924..834f0d1 100644
--- a/core/tests/coretests/src/android/widget/listview/ListEndingWithMultipleSeparators.java
+++ b/core/tests/coretests/src/android/widget/listview/ListEndingWithMultipleSeparators.java
@@ -16,7 +16,7 @@
 
 package android.widget.listview;
 
-import android.util.ListScenario;
+import android.widget.ListScenario;
 
 public class ListEndingWithMultipleSeparators extends ListScenario {
 
diff --git a/core/tests/coretests/src/android/widget/listview/ListGetSelectedView.java b/core/tests/coretests/src/android/widget/listview/ListGetSelectedView.java
index 5639195..abd5d2e 100644
--- a/core/tests/coretests/src/android/widget/listview/ListGetSelectedView.java
+++ b/core/tests/coretests/src/android/widget/listview/ListGetSelectedView.java
@@ -16,7 +16,7 @@
 
 package android.widget.listview;
 
-import android.util.ListScenario;
+import android.widget.ListScenario;
 
 /**
  * Basic top gravity scenario. This test is made to check that getSelectedView() will return
diff --git a/core/tests/coretests/src/android/widget/listview/ListHeterogeneous.java b/core/tests/coretests/src/android/widget/listview/ListHeterogeneous.java
index 74eda3b..fd24d61 100644
--- a/core/tests/coretests/src/android/widget/listview/ListHeterogeneous.java
+++ b/core/tests/coretests/src/android/widget/listview/ListHeterogeneous.java
@@ -17,7 +17,7 @@
 package android.widget.listview;
 
 import android.util.ListItemFactory;
-import android.util.ListScenario;
+import android.widget.ListScenario;
 import android.view.View;
 import android.view.ViewGroup;
 
diff --git a/core/tests/coretests/src/android/widget/listview/ListHorizontalFocusWithinItemWins.java b/core/tests/coretests/src/android/widget/listview/ListHorizontalFocusWithinItemWins.java
index e98de9c..7ce5ee3 100644
--- a/core/tests/coretests/src/android/widget/listview/ListHorizontalFocusWithinItemWins.java
+++ b/core/tests/coretests/src/android/widget/listview/ListHorizontalFocusWithinItemWins.java
@@ -20,7 +20,7 @@
 
 import android.content.Context;
 import android.util.ListItemFactory;
-import android.util.ListScenario;
+import android.widget.ListScenario;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.Button;
diff --git a/core/tests/coretests/src/android/widget/listview/ListInterleaveFocusables.java b/core/tests/coretests/src/android/widget/listview/ListInterleaveFocusables.java
index 0ec7a24..b613741 100644
--- a/core/tests/coretests/src/android/widget/listview/ListInterleaveFocusables.java
+++ b/core/tests/coretests/src/android/widget/listview/ListInterleaveFocusables.java
@@ -17,7 +17,7 @@
 package android.widget.listview;
 
 import android.util.ListItemFactory;
-import android.util.ListScenario;
+import android.widget.ListScenario;
 import android.view.View;
 import android.view.ViewGroup;
 
diff --git a/core/tests/coretests/src/android/widget/listview/ListItemFocusableAboveUnfocusable.java b/core/tests/coretests/src/android/widget/listview/ListItemFocusableAboveUnfocusable.java
index 3159e53..dc40f5f 100644
--- a/core/tests/coretests/src/android/widget/listview/ListItemFocusableAboveUnfocusable.java
+++ b/core/tests/coretests/src/android/widget/listview/ListItemFocusableAboveUnfocusable.java
@@ -17,7 +17,7 @@
 package android.widget.listview;
 
 import android.util.ListItemFactory;
-import android.util.ListScenario;
+import android.widget.ListScenario;
 import android.view.View;
 import android.view.ViewGroup;
 
diff --git a/core/tests/coretests/src/android/widget/listview/ListItemFocusablesClose.java b/core/tests/coretests/src/android/widget/listview/ListItemFocusablesClose.java
index 861e2a91..d21d234 100644
--- a/core/tests/coretests/src/android/widget/listview/ListItemFocusablesClose.java
+++ b/core/tests/coretests/src/android/widget/listview/ListItemFocusablesClose.java
@@ -17,7 +17,7 @@
 package android.widget.listview;
 
 import android.util.ListItemFactory;
-import android.util.ListScenario;
+import android.widget.ListScenario;
 import android.view.View;
 import android.view.ViewGroup;
 
diff --git a/core/tests/coretests/src/android/widget/listview/ListItemFocusablesFarApart.java b/core/tests/coretests/src/android/widget/listview/ListItemFocusablesFarApart.java
index e9c9c1d..0bb080b 100644
--- a/core/tests/coretests/src/android/widget/listview/ListItemFocusablesFarApart.java
+++ b/core/tests/coretests/src/android/widget/listview/ListItemFocusablesFarApart.java
@@ -17,7 +17,7 @@
 package android.widget.listview;
 
 import android.util.ListItemFactory;
-import android.util.ListScenario;
+import android.widget.ListScenario;
 import android.view.View;
 import android.view.ViewGroup;
 
diff --git a/core/tests/coretests/src/android/widget/listview/ListItemISVAndButton.java b/core/tests/coretests/src/android/widget/listview/ListItemISVAndButton.java
index 2a0e013..cbe07cc 100644
--- a/core/tests/coretests/src/android/widget/listview/ListItemISVAndButton.java
+++ b/core/tests/coretests/src/android/widget/listview/ListItemISVAndButton.java
@@ -17,8 +17,8 @@
 package android.widget.listview;
 
 import android.content.Context;
-import android.util.InternalSelectionView;
-import android.util.ListScenario;
+import android.widget.InternalSelectionView;
+import android.widget.ListScenario;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.Button;
diff --git a/core/tests/coretests/src/android/widget/listview/ListItemsExpandOnSelection.java b/core/tests/coretests/src/android/widget/listview/ListItemsExpandOnSelection.java
index d80fd90..240119e 100644
--- a/core/tests/coretests/src/android/widget/listview/ListItemsExpandOnSelection.java
+++ b/core/tests/coretests/src/android/widget/listview/ListItemsExpandOnSelection.java
@@ -17,7 +17,7 @@
 package android.widget.listview;
 
 import android.content.Context;
-import android.util.ListScenario;
+import android.widget.ListScenario;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.AbsListView;
diff --git a/core/tests/coretests/src/android/widget/listview/ListLastItemPartiallyVisible.java b/core/tests/coretests/src/android/widget/listview/ListLastItemPartiallyVisible.java
index d733749..48c70d6 100644
--- a/core/tests/coretests/src/android/widget/listview/ListLastItemPartiallyVisible.java
+++ b/core/tests/coretests/src/android/widget/listview/ListLastItemPartiallyVisible.java
@@ -16,7 +16,7 @@
 
 package android.widget.listview;
 
-import android.util.ListScenario;
+import android.widget.ListScenario;
 
 /**
  * A list where the very last item is partially visible, but still requires scrolling
diff --git a/core/tests/coretests/src/android/widget/listview/ListOfItemsShorterThanScreen.java b/core/tests/coretests/src/android/widget/listview/ListOfItemsShorterThanScreen.java
index 46decfa..55af8d4 100644
--- a/core/tests/coretests/src/android/widget/listview/ListOfItemsShorterThanScreen.java
+++ b/core/tests/coretests/src/android/widget/listview/ListOfItemsShorterThanScreen.java
@@ -16,7 +16,7 @@
 
 package android.widget.listview;
 
-import android.util.ListScenario;
+import android.widget.ListScenario;
 
 public class ListOfItemsShorterThanScreen extends ListScenario {
 
diff --git a/core/tests/coretests/src/android/widget/listview/ListOfItemsTallerThanScreen.java b/core/tests/coretests/src/android/widget/listview/ListOfItemsTallerThanScreen.java
index 0d88993..2b619e9 100644
--- a/core/tests/coretests/src/android/widget/listview/ListOfItemsTallerThanScreen.java
+++ b/core/tests/coretests/src/android/widget/listview/ListOfItemsTallerThanScreen.java
@@ -16,7 +16,7 @@
 
 package android.widget.listview;
 
-import android.util.ListScenario;
+import android.widget.ListScenario;
 
 public class ListOfItemsTallerThanScreen extends ListScenario {
 
diff --git a/core/tests/coretests/src/android/widget/listview/ListOfShortShortTallShortShort.java b/core/tests/coretests/src/android/widget/listview/ListOfShortShortTallShortShort.java
index 1639aa4..09f56b3 100644
--- a/core/tests/coretests/src/android/widget/listview/ListOfShortShortTallShortShort.java
+++ b/core/tests/coretests/src/android/widget/listview/ListOfShortShortTallShortShort.java
@@ -16,7 +16,7 @@
 
 package android.widget.listview;
 
-import android.util.ListScenario;
+import android.widget.ListScenario;
 
 /**
  * Exposes fading in and out multiple items.
diff --git a/core/tests/coretests/src/android/widget/listview/ListOfShortTallShort.java b/core/tests/coretests/src/android/widget/listview/ListOfShortTallShort.java
index 960e129..8ad8fff 100644
--- a/core/tests/coretests/src/android/widget/listview/ListOfShortTallShort.java
+++ b/core/tests/coretests/src/android/widget/listview/ListOfShortTallShort.java
@@ -16,7 +16,7 @@
 
 package android.widget.listview;
 
-import android.util.ListScenario;
+import android.widget.ListScenario;
 
 /**
  * Two short items separated by one that is taller than the screen.
diff --git a/core/tests/coretests/src/android/widget/listview/ListOfThinItems.java b/core/tests/coretests/src/android/widget/listview/ListOfThinItems.java
index 007479f..3f703af 100644
--- a/core/tests/coretests/src/android/widget/listview/ListOfThinItems.java
+++ b/core/tests/coretests/src/android/widget/listview/ListOfThinItems.java
@@ -16,7 +16,7 @@
 
 package android.widget.listview;
 
-import android.util.ListScenario;
+import android.widget.ListScenario;
 
 public class ListOfThinItems extends ListScenario {
 
diff --git a/core/tests/coretests/src/android/widget/listview/ListOfTouchables.java b/core/tests/coretests/src/android/widget/listview/ListOfTouchables.java
index 70b9081..f1dcdad 100644
--- a/core/tests/coretests/src/android/widget/listview/ListOfTouchables.java
+++ b/core/tests/coretests/src/android/widget/listview/ListOfTouchables.java
@@ -16,7 +16,7 @@
 
 package android.widget.listview;
 
-import android.util.ListScenario;
+import android.widget.ListScenario;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.Button;
diff --git a/core/tests/coretests/src/android/widget/listview/ListSetSelection.java b/core/tests/coretests/src/android/widget/listview/ListSetSelection.java
index af8e899..a107117 100644
--- a/core/tests/coretests/src/android/widget/listview/ListSetSelection.java
+++ b/core/tests/coretests/src/android/widget/listview/ListSetSelection.java
@@ -17,7 +17,7 @@
 package android.widget.listview;
 
 import android.os.Bundle;
-import android.util.ListScenario;
+import android.widget.ListScenario;
 import android.view.KeyEvent;
 import android.view.View;
 import android.widget.Button;
diff --git a/core/tests/coretests/src/android/widget/listview/ListSimple.java b/core/tests/coretests/src/android/widget/listview/ListSimple.java
index f53638e..9b3a98f 100644
--- a/core/tests/coretests/src/android/widget/listview/ListSimple.java
+++ b/core/tests/coretests/src/android/widget/listview/ListSimple.java
@@ -17,7 +17,7 @@
 package android.widget.listview;
 
 import android.os.Bundle;
-import android.util.ListScenario;
+import android.widget.ListScenario;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.TextView;
diff --git a/core/tests/coretests/src/android/widget/listview/ListTopGravity.java b/core/tests/coretests/src/android/widget/listview/ListTopGravity.java
index 31339e9..67ef6d1 100644
--- a/core/tests/coretests/src/android/widget/listview/ListTopGravity.java
+++ b/core/tests/coretests/src/android/widget/listview/ListTopGravity.java
@@ -16,7 +16,7 @@
 
 package android.widget.listview;
 
-import android.util.ListScenario;
+import android.widget.ListScenario;
 
 /**
  * Basic top gravity scenario, nothing fancy. Items do not
diff --git a/core/tests/coretests/src/android/widget/listview/ListTopGravityMany.java b/core/tests/coretests/src/android/widget/listview/ListTopGravityMany.java
index 5592ad9..9618c81 100644
--- a/core/tests/coretests/src/android/widget/listview/ListTopGravityMany.java
+++ b/core/tests/coretests/src/android/widget/listview/ListTopGravityMany.java
@@ -16,7 +16,7 @@
 
 package android.widget.listview;
 
-import android.util.ListScenario;
+import android.widget.ListScenario;
 
 /**
  * Basic top gravity scenario, nothing fancy. There are
diff --git a/core/tests/coretests/src/android/widget/listview/ListWithEditTextHeader.java b/core/tests/coretests/src/android/widget/listview/ListWithEditTextHeader.java
index 5303faf..1a204a2 100644
--- a/core/tests/coretests/src/android/widget/listview/ListWithEditTextHeader.java
+++ b/core/tests/coretests/src/android/widget/listview/ListWithEditTextHeader.java
@@ -16,7 +16,7 @@
 
 package android.widget.listview;
 
-import android.util.ListScenario;
+import android.widget.ListScenario;
 
 /**
  * A list view with a single edit text in a header.
diff --git a/core/tests/coretests/src/android/widget/listview/ListWithFirstScreenUnSelectable.java b/core/tests/coretests/src/android/widget/listview/ListWithFirstScreenUnSelectable.java
index 5261283..d6e7c6f 100644
--- a/core/tests/coretests/src/android/widget/listview/ListWithFirstScreenUnSelectable.java
+++ b/core/tests/coretests/src/android/widget/listview/ListWithFirstScreenUnSelectable.java
@@ -16,7 +16,7 @@
 
 package android.widget.listview;
 
-import android.util.ListScenario;
+import android.widget.ListScenario;
 
 /**
  * The first item is unselectable, and takes up the whole screen.
diff --git a/core/tests/coretests/src/android/widget/listview/ListWithHeaders.java b/core/tests/coretests/src/android/widget/listview/ListWithHeaders.java
index 6030582..fa2832e 100644
--- a/core/tests/coretests/src/android/widget/listview/ListWithHeaders.java
+++ b/core/tests/coretests/src/android/widget/listview/ListWithHeaders.java
@@ -17,7 +17,7 @@
 package android.widget.listview;
 
 import android.os.Bundle;
-import android.util.ListScenario;
+import android.widget.ListScenario;
 import android.widget.Button;
 import android.widget.ListAdapter;
 import android.widget.ListView;
diff --git a/core/tests/coretests/src/android/widget/listview/ListWithNoFadingEdge.java b/core/tests/coretests/src/android/widget/listview/ListWithNoFadingEdge.java
index b870fc8..f8b4f78 100644
--- a/core/tests/coretests/src/android/widget/listview/ListWithNoFadingEdge.java
+++ b/core/tests/coretests/src/android/widget/listview/ListWithNoFadingEdge.java
@@ -16,7 +16,7 @@
 
 package android.widget.listview;
 
-import android.util.ListScenario;
+import android.widget.ListScenario;
 
 public class ListWithNoFadingEdge extends ListScenario {
 
diff --git a/core/tests/coretests/src/android/widget/listview/ListWithOffScreenNextSelectable.java b/core/tests/coretests/src/android/widget/listview/ListWithOffScreenNextSelectable.java
index 2e65bd0..b8f14d2 100644
--- a/core/tests/coretests/src/android/widget/listview/ListWithOffScreenNextSelectable.java
+++ b/core/tests/coretests/src/android/widget/listview/ListWithOffScreenNextSelectable.java
@@ -16,7 +16,7 @@
 
 package android.widget.listview;
 
-import android.util.ListScenario;
+import android.widget.ListScenario;
 
 /**
  * Pressing down from position 0 requires looking past positions 1, 2 and 3 to
diff --git a/core/tests/coretests/src/android/widget/listview/ListWithOnItemSelectedAction.java b/core/tests/coretests/src/android/widget/listview/ListWithOnItemSelectedAction.java
index 13e770c..afc4c3b 100644
--- a/core/tests/coretests/src/android/widget/listview/ListWithOnItemSelectedAction.java
+++ b/core/tests/coretests/src/android/widget/listview/ListWithOnItemSelectedAction.java
@@ -16,7 +16,7 @@
 
 package android.widget.listview;
 
-import android.util.ListScenario;
+import android.widget.ListScenario;
 import android.widget.TextView;
 
 /**
diff --git a/core/tests/coretests/src/android/widget/listview/ListWithScreenOfNoSelectables.java b/core/tests/coretests/src/android/widget/listview/ListWithScreenOfNoSelectables.java
index 108ac4d..fe33bf0 100644
--- a/core/tests/coretests/src/android/widget/listview/ListWithScreenOfNoSelectables.java
+++ b/core/tests/coretests/src/android/widget/listview/ListWithScreenOfNoSelectables.java
@@ -16,7 +16,7 @@
 
 package android.widget.listview;
 
-import android.util.ListScenario;
+import android.widget.ListScenario;
 
 public class ListWithScreenOfNoSelectables extends ListScenario {
 
diff --git a/core/tests/coretests/src/android/widget/listview/ListWithSeparators.java b/core/tests/coretests/src/android/widget/listview/ListWithSeparators.java
index 0f4f2d8..1a3955a 100644
--- a/core/tests/coretests/src/android/widget/listview/ListWithSeparators.java
+++ b/core/tests/coretests/src/android/widget/listview/ListWithSeparators.java
@@ -16,7 +16,7 @@
 
 package android.widget.listview;
 
-import android.util.ListScenario;
+import android.widget.ListScenario;
 
 /**
  * Basic separator scenario, nothing fancy.
diff --git a/core/tests/coretests/src/android/widget/listview/focus/AdjacentListsWithAdjacentISVsInsideTest.java b/core/tests/coretests/src/android/widget/listview/focus/AdjacentListsWithAdjacentISVsInsideTest.java
index e9baabf..09c140e 100644
--- a/core/tests/coretests/src/android/widget/listview/focus/AdjacentListsWithAdjacentISVsInsideTest.java
+++ b/core/tests/coretests/src/android/widget/listview/focus/AdjacentListsWithAdjacentISVsInsideTest.java
@@ -17,7 +17,7 @@
 package android.widget.listview.focus;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.util.InternalSelectionView;
+import android.widget.InternalSelectionView;
 import android.view.KeyEvent;
 import android.widget.ListView;
 import android.widget.listview.AdjacentListsWithAdjacentISVsInside;
diff --git a/core/tests/coretests/src/android/widget/scroll/ButtonAboveTallInternalSelectionView.java b/core/tests/coretests/src/android/widget/scroll/ButtonAboveTallInternalSelectionView.java
index a30985b..30f5c67 100644
--- a/core/tests/coretests/src/android/widget/scroll/ButtonAboveTallInternalSelectionView.java
+++ b/core/tests/coretests/src/android/widget/scroll/ButtonAboveTallInternalSelectionView.java
@@ -16,8 +16,8 @@
 
 package android.widget.scroll;
 
-import android.util.InternalSelectionView;
-import android.util.ScrollViewScenario;
+import android.widget.InternalSelectionView;
+import android.widget.ScrollViewScenario;
 import android.widget.Button;
 
 /**
diff --git a/core/tests/coretests/src/android/widget/scroll/ButtonAboveTallInternalSelectionViewTest.java b/core/tests/coretests/src/android/widget/scroll/ButtonAboveTallInternalSelectionViewTest.java
index 825aa1a..d977ab4 100644
--- a/core/tests/coretests/src/android/widget/scroll/ButtonAboveTallInternalSelectionViewTest.java
+++ b/core/tests/coretests/src/android/widget/scroll/ButtonAboveTallInternalSelectionViewTest.java
@@ -17,7 +17,7 @@
 package android.widget.scroll;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.util.InternalSelectionView;
+import android.widget.InternalSelectionView;
 import android.view.KeyEvent;
 
 import androidx.test.filters.MediumTest;
diff --git a/core/tests/coretests/src/android/widget/scroll/ButtonsWithTallTextViewInBetween.java b/core/tests/coretests/src/android/widget/scroll/ButtonsWithTallTextViewInBetween.java
index 47d36dd..5149fd4 100644
--- a/core/tests/coretests/src/android/widget/scroll/ButtonsWithTallTextViewInBetween.java
+++ b/core/tests/coretests/src/android/widget/scroll/ButtonsWithTallTextViewInBetween.java
@@ -16,7 +16,7 @@
 
 package android.widget.scroll;
 
-import android.util.ScrollViewScenario;
+import android.widget.ScrollViewScenario;
 import android.widget.Button;
 import android.widget.LinearLayout;
 import android.widget.TextView;
diff --git a/core/tests/coretests/src/android/widget/scroll/ShortButtons.java b/core/tests/coretests/src/android/widget/scroll/ShortButtons.java
index 90ede7d..01d3b53 100644
--- a/core/tests/coretests/src/android/widget/scroll/ShortButtons.java
+++ b/core/tests/coretests/src/android/widget/scroll/ShortButtons.java
@@ -16,7 +16,7 @@
 
 package android.widget.scroll;
 
-import android.util.ScrollViewScenario;
+import android.widget.ScrollViewScenario;
 import android.widget.Button;
 import android.widget.LinearLayout;
 
diff --git a/core/tests/coretests/src/android/widget/scroll/TallTextAboveButton.java b/core/tests/coretests/src/android/widget/scroll/TallTextAboveButton.java
index 4096fe9..bf800c0 100644
--- a/core/tests/coretests/src/android/widget/scroll/TallTextAboveButton.java
+++ b/core/tests/coretests/src/android/widget/scroll/TallTextAboveButton.java
@@ -16,7 +16,7 @@
 
 package android.widget.scroll;
 
-import android.util.ScrollViewScenario;
+import android.widget.ScrollViewScenario;
 
 /**
  * An (unfocusable) text view that takes up more than the height
diff --git a/core/tests/coretests/src/android/widget/scroll/arrowscroll/MultiPageTextWithPadding.java b/core/tests/coretests/src/android/widget/scroll/arrowscroll/MultiPageTextWithPadding.java
index 7d5a8d8..6febdf9 100644
--- a/core/tests/coretests/src/android/widget/scroll/arrowscroll/MultiPageTextWithPadding.java
+++ b/core/tests/coretests/src/android/widget/scroll/arrowscroll/MultiPageTextWithPadding.java
@@ -16,7 +16,7 @@
 
 package android.widget.scroll.arrowscroll;
 
-import android.util.ScrollViewScenario;
+import android.widget.ScrollViewScenario;
 
 /**
  * One TextView with a text covering several pages. Padding is added
diff --git a/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutChooserActivityTest.java
index 6374e5d..60a436e 100644
--- a/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutChooserActivityTest.java
@@ -42,8 +42,8 @@
 
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.app.AlertDialog;
+import android.app.Dialog;
 import android.app.KeyguardManager;
-import android.app.UiAutomation;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -52,7 +52,6 @@
 import android.content.pm.ParceledListSlice;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
-import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.Handler;
 import android.platform.test.annotations.RequiresFlagsDisabled;
@@ -66,9 +65,9 @@
 import android.view.View;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityManager;
-import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.Flags;
 import android.view.accessibility.IAccessibilityManager;
+import android.widget.Button;
 
 import androidx.lifecycle.Lifecycle;
 import androidx.test.core.app.ActivityScenario;
@@ -108,7 +107,6 @@
     private static final ComponentName TEST_COMPONENT_NAME = new ComponentName(TEST_PACKAGE,
             "class");
     private static final long UI_TIMEOUT_MS = 1000;
-    private UiAutomation mUiAutomation;
     private UiDevice mDevice;
     private ActivityScenario<TestAccessibilityShortcutChooserActivity> mScenario;
     private TestAccessibilityShortcutChooserActivity mActivity;
@@ -142,7 +140,6 @@
         assumeFalse("AccessibilityShortcutChooserActivity not supported on watch",
                 pm.hasSystemFeature(PackageManager.FEATURE_WATCH));
 
-        mUiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
         mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
         mDevice.wakeUp();
         when(mAccessibilityServiceInfo.getResolveInfo()).thenReturn(mResolveInfo);
@@ -170,6 +167,12 @@
         if (mScenario != null) {
             mScenario.close();
         }
+        if (mActivity != null) {
+            Dialog permissionDialog = mActivity.getPermissionDialog();
+            if (permissionDialog != null && permissionDialog.isShowing()) {
+                permissionDialog.dismiss();
+            }
+        }
     }
 
     @Test
@@ -193,10 +196,8 @@
         openShortcutsList();
 
         mDevice.findObject(By.text(TEST_LABEL)).clickAndWait(Until.newWindow(), UI_TIMEOUT_MS);
-        clickSystemDialogButton(ALLOW_LABEL);
+        clickPermissionDialogButton(R.id.accessibility_permission_enable_allow_button);
 
-        assertThat(mDevice.wait(Until.hasObject(By.textStartsWith(LIST_TITLE_LABEL)),
-                UI_TIMEOUT_MS)).isTrue();
         assertThat(mDevice.wait(Until.hasObject(By.checked(true)), UI_TIMEOUT_MS)).isTrue();
     }
 
@@ -207,10 +208,8 @@
         openShortcutsList();
 
         mDevice.findObject(By.text(TEST_LABEL)).clickAndWait(Until.newWindow(), UI_TIMEOUT_MS);
-        clickSystemDialogButton(DENY_LABEL);
+        clickPermissionDialogButton(R.id.accessibility_permission_enable_deny_button);
 
-        assertThat(mDevice.wait(Until.hasObject(By.textStartsWith(LIST_TITLE_LABEL)),
-                UI_TIMEOUT_MS)).isTrue();
         assertThat(mDevice.wait(Until.hasObject(By.checked(true)), UI_TIMEOUT_MS)).isFalse();
     }
 
@@ -221,11 +220,9 @@
         openShortcutsList();
 
         mDevice.findObject(By.text(TEST_LABEL)).clickAndWait(Until.newWindow(), UI_TIMEOUT_MS);
-        clickSystemDialogButton(UNINSTALL_LABEL);
+        clickPermissionDialogButton(R.id.accessibility_permission_enable_uninstall_button);
 
         verify(mPackageInstaller).uninstall(eq(TEST_PACKAGE), any());
-        assertThat(mDevice.wait(Until.hasObject(By.textStartsWith(LIST_TITLE_LABEL)),
-                UI_TIMEOUT_MS)).isTrue();
         assertThat(mDevice.wait(Until.hasObject(By.textStartsWith(TEST_LABEL)),
                 UI_TIMEOUT_MS)).isFalse();
     }
@@ -353,16 +350,13 @@
         mDevice.wait(Until.hasObject(By.textStartsWith(LIST_TITLE_LABEL)), UI_TIMEOUT_MS);
     }
 
-    private void clickSystemDialogButton(String dialogButtonText) {
-        // Use UiAutomation to find the button because UiDevice struggles to find
-        // a UI element in a system dialog.
-        final AccessibilityNodeInfo button =
-                mUiAutomation.getRootInActiveWindow()
-                        .findAccessibilityNodeInfosByText(dialogButtonText).stream()
-                        .filter(AccessibilityNodeInfo::isClickable).findFirst().get();
-        final Rect bounds = new Rect();
-        button.getBoundsInScreen(bounds);
-        mDevice.click(bounds.centerX(), bounds.centerY());
+    private void clickPermissionDialogButton(int buttonId) {
+        Button button = mActivity.getPermissionDialog().findViewById(buttonId);
+        mActivity.runOnUiThread(button::performClick);
+        // Wait for the dialog to go away by waiting for the shortcut chooser
+        // to become visible again.
+        assertThat(mDevice.wait(Until.hasObject(By.textStartsWith(LIST_TITLE_LABEL)),
+                UI_TIMEOUT_MS)).isTrue();
     }
 
     /**
@@ -402,6 +396,10 @@
         public Object getSystemService(String name) {
             if (Context.ACCESSIBILITY_SERVICE.equals(name)
                     && sAccessibilityManagerService != null) {
+                // Warning: This new AccessibilityManager complicates UI inspection
+                // because it breaks the expected "singleton per process" quality of
+                // AccessibilityManager. Debug here if observing unexpected issues
+                // with UI inspection or interaction.
                 return new AccessibilityManager(this, new Handler(getMainLooper()),
                         sAccessibilityManagerService, /* userId= */ 0, /* serviceConnect= */ true);
             }
diff --git a/core/tests/coretests/src/com/android/internal/jank/CujTest.java b/core/tests/coretests/src/com/android/internal/jank/CujTest.java
new file mode 100644
index 0000000..bf35ed0
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/jank/CujTest.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.jank;
+
+import static android.text.TextUtils.formatSimple;
+
+import static com.android.internal.jank.Cuj.getNameOfCuj;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.util.FrameworkStatsLog;
+
+import com.google.common.truth.Expect;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+@SmallTest
+public class CujTest {
+    private static final String ENUM_NAME_PREFIX =
+            "UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__";
+    private static final Set<String> DEPRECATED_VALUES = new HashSet<>() {
+        {
+            add(ENUM_NAME_PREFIX + "IME_INSETS_ANIMATION");
+        }
+    };
+    private static final Map<Integer, String> ENUM_NAME_EXCEPTION_MAP = new HashMap<>() {
+        {
+            put(Cuj.CUJ_NOTIFICATION_ADD, getEnumName("SHADE_NOTIFICATION_ADD"));
+            put(Cuj.CUJ_NOTIFICATION_HEADS_UP_APPEAR, getEnumName("SHADE_HEADS_UP_APPEAR"));
+            put(Cuj.CUJ_NOTIFICATION_APP_START, getEnumName("SHADE_APP_LAUNCH"));
+            put(Cuj.CUJ_NOTIFICATION_HEADS_UP_DISAPPEAR, getEnumName("SHADE_HEADS_UP_DISAPPEAR"));
+            put(Cuj.CUJ_NOTIFICATION_REMOVE, getEnumName("SHADE_NOTIFICATION_REMOVE"));
+            put(Cuj.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, getEnumName("NOTIFICATION_SHADE_SWIPE"));
+            put(Cuj.CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE, getEnumName("SHADE_QS_EXPAND_COLLAPSE"));
+            put(Cuj.CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE, getEnumName("SHADE_QS_SCROLL_SWIPE"));
+            put(Cuj.CUJ_NOTIFICATION_SHADE_ROW_EXPAND, getEnumName("SHADE_ROW_EXPAND"));
+            put(Cuj.CUJ_NOTIFICATION_SHADE_ROW_SWIPE, getEnumName("SHADE_ROW_SWIPE"));
+            put(Cuj.CUJ_NOTIFICATION_SHADE_SCROLL_FLING, getEnumName("SHADE_SCROLL_FLING"));
+        }
+    };
+
+    @Rule
+    public final Expect mExpect = Expect.create();
+
+    @Test
+    public void testCujNameLimit() {
+        getCujConstants().forEach(f -> {
+            final int cuj = getIntFieldChecked(f);
+            mExpect.withMessage(formatSimple("Too long CUJ(%d) name: %s", cuj, getNameOfCuj(cuj)))
+                    .that(getNameOfCuj(cuj).length())
+                    .isAtMost(Cuj.MAX_LENGTH_OF_CUJ_NAME);
+        });
+    }
+
+    @Test
+    public void testCujTypeEnumCorrectlyDefined() throws Exception {
+        List<Field> cujEnumFields = getCujConstants().toList();
+
+        HashSet<Integer> allValues = new HashSet<>();
+        for (Field field : cujEnumFields) {
+            int fieldValue = field.getInt(null);
+            assertWithMessage("All CujType values must be unique. Field %s repeats existing value.",
+                    field.getName())
+                    .that(allValues.add(fieldValue))
+                    .isTrue();
+            assertWithMessage("Field %s must have a value <= LAST_CUJ", field.getName())
+                    .that(fieldValue)
+                    .isAtMost(Cuj.LAST_CUJ);
+            assertWithMessage("Field %s must have a statsd mapping.", field.getName())
+                    .that(Cuj.logToStatsd(fieldValue))
+                    .isTrue();
+        }
+    }
+
+    @Test
+    public void testCujsMapToEnumsCorrectly() {
+        List<Field> cujs = getCujConstants().toList();
+
+        Map<Integer, String> enumsMap = Arrays.stream(FrameworkStatsLog.class.getDeclaredFields())
+                .filter(f -> f.getName().startsWith(ENUM_NAME_PREFIX)
+                        && !DEPRECATED_VALUES.contains(f.getName())
+                        && Modifier.isStatic(f.getModifiers())
+                        && f.getType() == int.class)
+                .collect(Collectors.toMap(CujTest::getIntFieldChecked, Field::getName));
+
+        assertThat(enumsMap.size() - 1).isEqualTo(cujs.size());
+
+        cujs.forEach(f -> {
+            final int cuj = getIntFieldChecked(f);
+            final String cujName = f.getName();
+            final String expectedEnumName =
+                    ENUM_NAME_EXCEPTION_MAP.getOrDefault(cuj, getEnumName(cujName.substring(4)));
+            final int enumKey = Cuj.getStatsdInteractionType(cuj);
+            final String enumName = enumsMap.get(enumKey);
+            final String expectedNameOfCuj = formatSimple("CUJ_%s", getNameOfCuj(cuj));
+
+            mExpect.withMessage(
+                    formatSimple("%s (%d) not matches %s (%d)", cujName, cuj, enumName, enumKey))
+                    .that(expectedEnumName.equals(enumName))
+                    .isTrue();
+            mExpect.withMessage(
+                    formatSimple("getNameOfCuj(%d) not matches: %s, expected=%s",
+                            cuj, cujName, expectedNameOfCuj))
+                    .that(cujName.equals(expectedNameOfCuj))
+                    .isTrue();
+        });
+    }
+
+    private static String getEnumName(String name) {
+        return formatSimple("%s%s", ENUM_NAME_PREFIX, name);
+    }
+
+    private static int getIntFieldChecked(Field field) {
+        try {
+            return field.getInt(null);
+        } catch (IllegalAccessException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    private static Stream<Field> getCujConstants() {
+        return Arrays.stream(Cuj.class.getDeclaredFields())
+                .filter(f -> f.getName().startsWith("CUJ_")
+                        && Modifier.isStatic(f.getModifiers())
+                        && f.getType() == int.class);
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java b/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
index 1b9717a..1a7117e 100644
--- a/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
+++ b/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
@@ -22,9 +22,8 @@
 
 import static com.android.internal.jank.FrameTracker.SurfaceControlWrapper;
 import static com.android.internal.jank.FrameTracker.ViewRootWrapper;
-import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE;
-import static com.android.internal.jank.InteractionJankMonitor.CUJ_TO_STATSD_INTERACTION_TYPE;
-import static com.android.internal.jank.InteractionJankMonitor.CUJ_WALLPAPER_TRANSITION;
+import static com.android.internal.jank.Cuj.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE;
+import static com.android.internal.jank.Cuj.CUJ_WALLPAPER_TRANSITION;
 import static com.android.internal.util.FrameworkStatsLog.UI_INTERACTION_FRAME_INFO_REPORTED;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -49,15 +48,14 @@
 import android.view.View;
 import android.view.ViewAttachTestActivity;
 
+import androidx.test.ext.junit.rules.ActivityScenarioRule;
 import androidx.test.filters.SmallTest;
-import androidx.test.rule.ActivityTestRule;
 
 import com.android.internal.jank.FrameTracker.ChoreographerWrapper;
 import com.android.internal.jank.FrameTracker.FrameMetricsWrapper;
 import com.android.internal.jank.FrameTracker.StatsLogWrapper;
 import com.android.internal.jank.FrameTracker.ThreadedRendererWrapper;
 import com.android.internal.jank.InteractionJankMonitor.Configuration;
-import com.android.internal.jank.InteractionJankMonitor.Session;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -69,14 +67,14 @@
 
 @SmallTest
 public class FrameTrackerTest {
-    private static final String CUJ_POSTFIX = "";
+    private static final String SESSION_NAME = "SessionName";
     private static final long FRAME_TIME_60Hz = (long) 1e9 / 60;
 
     private ViewAttachTestActivity mActivity;
 
     @Rule
-    public ActivityTestRule<ViewAttachTestActivity> mRule =
-            new ActivityTestRule<>(ViewAttachTestActivity.class);
+    public ActivityScenarioRule<ViewAttachTestActivity> mRule =
+            new ActivityScenarioRule<>(ViewAttachTestActivity.class);
 
     private ThreadedRendererWrapper mRenderer;
     private FrameMetricsWrapper mWrapper;
@@ -86,12 +84,13 @@
     private StatsLogWrapper mStatsLog;
     private ArgumentCaptor<OnJankDataListener> mListenerCapture;
     private SurfaceControl mSurfaceControl;
+    private FrameTracker.FrameTrackerListener mTrackerListener;
     private ArgumentCaptor<Runnable> mRunnableArgumentCaptor;
 
     @Before
     public void setup() {
         // Prepare an activity for getting ThreadedRenderer later.
-        mActivity = mRule.getActivity();
+        mRule.getScenario().onActivity(activity -> mActivity = activity);
         View view = mActivity.getWindow().getDecorView();
         assertThat(view.isAttachedToWindow()).isTrue();
 
@@ -116,36 +115,38 @@
         mChoreographer = mock(ChoreographerWrapper.class);
         mStatsLog = mock(StatsLogWrapper.class);
         mRunnableArgumentCaptor = ArgumentCaptor.forClass(Runnable.class);
+        mTrackerListener = mock(FrameTracker.FrameTrackerListener.class);
     }
 
-    private FrameTracker spyFrameTracker(int cuj, String postfix, boolean surfaceOnly) {
-        InteractionJankMonitor monitor = mock(InteractionJankMonitor.class);
-        Handler handler = mRule.getActivity().getMainThreadHandler();
-        Session session = new Session(cuj, postfix);
+    private FrameTracker spyFrameTracker(boolean surfaceOnly) {
+        Handler handler = mActivity.getMainThreadHandler();
         Configuration config = mock(Configuration.class);
+        when(config.getSessionName()).thenReturn(SESSION_NAME);
         when(config.isSurfaceOnly()).thenReturn(surfaceOnly);
         when(config.getSurfaceControl()).thenReturn(mSurfaceControl);
         when(config.shouldDeferMonitor()).thenReturn(true);
         when(config.getDisplayId()).thenReturn(42);
-        View view = mRule.getActivity().getWindow().getDecorView();
+        View view = mActivity.getWindow().getDecorView();
         Handler spyHandler = spy(new Handler(handler.getLooper()));
         when(config.getView()).thenReturn(surfaceOnly ? null : view);
         when(config.getHandler()).thenReturn(spyHandler);
+        when(config.logToStatsd()).thenReturn(true);
+        when(config.getStatsdInteractionType()).thenReturn(surfaceOnly
+                ? Cuj.getStatsdInteractionType(CUJ_WALLPAPER_TRANSITION)
+                : Cuj.getStatsdInteractionType(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE));
         FrameTracker frameTracker = Mockito.spy(
-                new FrameTracker(monitor, session, spyHandler, mRenderer, mViewRootWrapper,
+                new FrameTracker(config, mRenderer, mViewRootWrapper,
                         mSurfaceControlWrapper, mChoreographer, mWrapper, mStatsLog,
                         /* traceThresholdMissedFrames= */ 1,
                         /* traceThresholdFrameTimeMillis= */ -1,
-                        /* FrameTrackerListener= */ null, config));
-        doNothing().when(frameTracker).triggerPerfetto();
+                        mTrackerListener));
         doNothing().when(frameTracker).postTraceStartMarker(mRunnableArgumentCaptor.capture());
         return frameTracker;
     }
 
     @Test
     public void testOnlyFirstWindowFrameOverThreshold() {
-        FrameTracker tracker = spyFrameTracker(
-                CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, CUJ_POSTFIX, /* surfaceOnly= */ false);
+        FrameTracker tracker = spyFrameTracker(/* surfaceOnly= */ false);
 
         // Just provide current timestamp anytime mWrapper asked for VSYNC_TIMESTAMP
         when(mWrapper.getMetric(FrameMetrics.VSYNC_TIMESTAMP))
@@ -169,11 +170,11 @@
         sendFrame(tracker, 500, JANK_APP_DEADLINE_MISSED, 103L);
 
         verify(tracker).removeObservers();
-        verify(tracker, never()).triggerPerfetto();
+        verify(mTrackerListener, never()).triggerPerfetto(any());
         verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED),
                 eq(42), /* displayId */
                 eq(DisplayRefreshRate.REFRESH_RATE_60_HZ),
-                eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE]),
+                eq(Cuj.getStatsdInteractionType(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)),
                 eq(2L) /* totalFrames */,
                 eq(0L) /* missedFrames */,
                 eq(5000000L) /* maxFrameTimeNanos */,
@@ -184,8 +185,7 @@
 
     @Test
     public void testSfJank() {
-        FrameTracker tracker = spyFrameTracker(
-                CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, CUJ_POSTFIX, /* surfaceOnly= */ false);
+        FrameTracker tracker = spyFrameTracker(/* surfaceOnly= */ false);
 
         when(mChoreographer.getVsyncId()).thenReturn(100L);
         tracker.begin();
@@ -206,12 +206,12 @@
         verify(tracker).removeObservers();
 
         // We detected a janky frame - trigger Perfetto
-        verify(tracker).triggerPerfetto();
+        verify(mTrackerListener).triggerPerfetto(any());
 
         verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED),
                 eq(42), /* displayId */
                 eq(DisplayRefreshRate.REFRESH_RATE_60_HZ),
-                eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE]),
+                eq(Cuj.getStatsdInteractionType(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)),
                 eq(2L) /* totalFrames */,
                 eq(1L) /* missedFrames */,
                 eq(40000000L) /* maxFrameTimeNanos */,
@@ -222,8 +222,7 @@
 
     @Test
     public void testFirstFrameJankyNoTrigger() {
-        FrameTracker tracker = spyFrameTracker(
-                CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, CUJ_POSTFIX, /* surfaceOnly= */ false);
+        FrameTracker tracker = spyFrameTracker(/* surfaceOnly= */ false);
 
         when(mChoreographer.getVsyncId()).thenReturn(100L);
         tracker.begin();
@@ -243,13 +242,12 @@
 
         verify(tracker).removeObservers();
 
-        // We detected a janky frame - trigger Perfetto
-        verify(tracker, never()).triggerPerfetto();
+        verify(mTrackerListener, never()).triggerPerfetto(any());
 
         verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED),
                 eq(42), /* displayId */
                 eq(DisplayRefreshRate.REFRESH_RATE_60_HZ),
-                eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE]),
+                eq(Cuj.getStatsdInteractionType(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)),
                 eq(2L) /* totalFrames */,
                 eq(0L) /* missedFrames */,
                 eq(4000000L) /* maxFrameTimeNanos */,
@@ -260,8 +258,7 @@
 
     @Test
     public void testOtherFrameOverThreshold() {
-        FrameTracker tracker = spyFrameTracker(
-                CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, CUJ_POSTFIX, /* surfaceOnly= */ false);
+        FrameTracker tracker = spyFrameTracker(/* surfaceOnly= */ false);
 
         when(mChoreographer.getVsyncId()).thenReturn(100L);
         tracker.begin();
@@ -282,12 +279,12 @@
         verify(tracker).removeObservers();
 
         // We detected a janky frame - trigger Perfetto
-        verify(tracker).triggerPerfetto();
+        verify(mTrackerListener).triggerPerfetto(any());
 
         verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED),
                 eq(42), /* displayId */
                 eq(DisplayRefreshRate.REFRESH_RATE_60_HZ),
-                eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE]),
+                eq(Cuj.getStatsdInteractionType(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)),
                 eq(2L) /* totalFrames */,
                 eq(1L) /* missedFrames */,
                 eq(40000000L) /* maxFrameTimeNanos */,
@@ -298,8 +295,7 @@
 
     @Test
     public void testLastFrameOverThresholdBeforeEnd() {
-        FrameTracker tracker = spyFrameTracker(
-                CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, CUJ_POSTFIX, /* surfaceOnly= */ false);
+        FrameTracker tracker = spyFrameTracker(/* surfaceOnly= */ false);
 
         when(mChoreographer.getVsyncId()).thenReturn(100L);
         tracker.begin();
@@ -323,12 +319,12 @@
         verify(tracker).removeObservers();
 
         // We detected a janky frame - trigger Perfetto
-        verify(tracker).triggerPerfetto();
+        verify(mTrackerListener).triggerPerfetto(any());
 
         verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED),
                 eq(42), /* displayId */
                 eq(DisplayRefreshRate.REFRESH_RATE_60_HZ),
-                eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE]),
+                eq(Cuj.getStatsdInteractionType(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)),
                 eq(2L) /* totalFrames */,
                 eq(1L) /* missedFrames */,
                 eq(50000000L) /* maxFrameTimeNanos */,
@@ -342,8 +338,7 @@
      */
     @Test
     public void testNoOvercountingAfterEnd() {
-        FrameTracker tracker = spyFrameTracker(
-                CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, CUJ_POSTFIX, /* surfaceOnly= */ false);
+        FrameTracker tracker = spyFrameTracker(/* surfaceOnly= */ false);
 
         when(mChoreographer.getVsyncId()).thenReturn(100L);
         tracker.begin();
@@ -367,11 +362,11 @@
         sendFrame(tracker, 50, JANK_APP_DEADLINE_MISSED, 103L);
 
         verify(tracker).removeObservers();
-        verify(tracker, never()).triggerPerfetto();
+        verify(mTrackerListener, never()).triggerPerfetto(any());
         verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED),
                 eq(42), /* displayId */
                 eq(DisplayRefreshRate.REFRESH_RATE_60_HZ),
-                eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE]),
+                eq(Cuj.getStatsdInteractionType(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)),
                 eq(2L) /* totalFrames */,
                 eq(0L) /* missedFrames */,
                 eq(4000000L) /* maxFrameTimeNanos */,
@@ -382,8 +377,7 @@
 
     @Test
     public void testBeginCancel() {
-        FrameTracker tracker = spyFrameTracker(
-                CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, CUJ_POSTFIX, /* surfaceOnly= */ false);
+        FrameTracker tracker = spyFrameTracker(/* surfaceOnly= */ false);
 
         when(mChoreographer.getVsyncId()).thenReturn(100L);
         tracker.begin();
@@ -402,13 +396,12 @@
         tracker.cancel(FrameTracker.REASON_CANCEL_NORMAL);
         verify(tracker).removeObservers();
         // Since the tracker has been cancelled, shouldn't trigger perfetto.
-        verify(tracker, never()).triggerPerfetto();
+        verify(mTrackerListener, never()).triggerPerfetto(any());
     }
 
     @Test
     public void testCancelIfEndVsyncIdEqualsToBeginVsyncId() {
-        FrameTracker tracker = spyFrameTracker(
-                CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, CUJ_POSTFIX, /* surfaceOnly= */ false);
+        FrameTracker tracker = spyFrameTracker(/* surfaceOnly= */ false);
 
         when(mChoreographer.getVsyncId()).thenReturn(100L);
         tracker.begin();
@@ -426,13 +419,12 @@
         verify(tracker).removeObservers();
 
         // Should never trigger Perfetto since it is a cancel.
-        verify(tracker, never()).triggerPerfetto();
+        verify(mTrackerListener, never()).triggerPerfetto(any());
     }
 
     @Test
     public void testCancelIfEndVsyncIdLessThanBeginVsyncId() {
-        FrameTracker tracker = spyFrameTracker(
-                CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, CUJ_POSTFIX, /* surfaceOnly= */ false);
+        FrameTracker tracker = spyFrameTracker(/* surfaceOnly= */ false);
 
         when(mChoreographer.getVsyncId()).thenReturn(100L);
         tracker.begin();
@@ -450,13 +442,12 @@
         verify(tracker).removeObservers();
 
         // Should never trigger Perfetto since it is a cancel.
-        verify(tracker, never()).triggerPerfetto();
+        verify(mTrackerListener, never()).triggerPerfetto(any());
     }
 
     @Test
     public void testCancelWhenSessionNeverBegun() {
-        FrameTracker tracker = spyFrameTracker(
-                CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, CUJ_POSTFIX, /* surfaceOnly= */ false);
+        FrameTracker tracker = spyFrameTracker(/* surfaceOnly= */ false);
 
         tracker.cancel(FrameTracker.REASON_CANCEL_NORMAL);
         verify(tracker).removeObservers();
@@ -464,8 +455,7 @@
 
     @Test
     public void testEndWhenSessionNeverBegun() {
-        FrameTracker tracker = spyFrameTracker(
-                CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, CUJ_POSTFIX, /* surfaceOnly= */ false);
+        FrameTracker tracker = spyFrameTracker(/* surfaceOnly= */ false);
 
         tracker.end(FrameTracker.REASON_END_NORMAL);
         verify(tracker).removeObservers();
@@ -473,8 +463,7 @@
 
     @Test
     public void testSurfaceOnlyOtherFrameJanky() {
-        FrameTracker tracker = spyFrameTracker(
-                CUJ_WALLPAPER_TRANSITION, CUJ_POSTFIX, /* surfaceOnly= */ true);
+        FrameTracker tracker = spyFrameTracker(/* surfaceOnly= */ true);
 
         when(mChoreographer.getVsyncId()).thenReturn(100L);
         tracker.begin();
@@ -495,12 +484,12 @@
         sendFrame(tracker, JANK_NONE, 103L);
 
         verify(mSurfaceControlWrapper).removeJankStatsListener(any());
-        verify(tracker).triggerPerfetto();
+        verify(mTrackerListener).triggerPerfetto(any());
 
         verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED),
                 eq(42), /* displayId */
                 eq(DisplayRefreshRate.REFRESH_RATE_60_HZ),
-                eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_WALLPAPER_TRANSITION]),
+                eq(Cuj.getStatsdInteractionType(CUJ_WALLPAPER_TRANSITION)),
                 eq(2L) /* totalFrames */,
                 eq(1L) /* missedFrames */,
                 eq(0L) /* maxFrameTimeNanos */,
@@ -511,8 +500,7 @@
 
     @Test
     public void testSurfaceOnlyFirstFrameJanky() {
-        FrameTracker tracker = spyFrameTracker(
-                CUJ_WALLPAPER_TRANSITION, CUJ_POSTFIX, /* surfaceOnly= */ true);
+        FrameTracker tracker = spyFrameTracker(/* surfaceOnly= */ true);
 
         when(mChoreographer.getVsyncId()).thenReturn(100L);
         tracker.begin();
@@ -533,12 +521,12 @@
         sendFrame(tracker, JANK_NONE, 103L);
 
         verify(mSurfaceControlWrapper).removeJankStatsListener(any());
-        verify(tracker, never()).triggerPerfetto();
+        verify(mTrackerListener, never()).triggerPerfetto(any());
 
         verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED),
                 eq(42), /* displayId */
                 eq(DisplayRefreshRate.REFRESH_RATE_60_HZ),
-                eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_WALLPAPER_TRANSITION]),
+                eq(Cuj.getStatsdInteractionType(CUJ_WALLPAPER_TRANSITION)),
                 eq(2L) /* totalFrames */,
                 eq(0L) /* missedFrames */,
                 eq(0L) /* maxFrameTimeNanos */,
@@ -549,8 +537,7 @@
 
     @Test
     public void testSurfaceOnlyLastFrameJanky() {
-        FrameTracker tracker = spyFrameTracker(
-                CUJ_WALLPAPER_TRANSITION, CUJ_POSTFIX, /* surfaceOnly= */ true);
+        FrameTracker tracker = spyFrameTracker(/* surfaceOnly= */ true);
 
         when(mChoreographer.getVsyncId()).thenReturn(100L);
         tracker.begin();
@@ -571,12 +558,12 @@
         sendFrame(tracker, JANK_APP_DEADLINE_MISSED, 103L);
 
         verify(mSurfaceControlWrapper).removeJankStatsListener(any());
-        verify(tracker, never()).triggerPerfetto();
+        verify(mTrackerListener, never()).triggerPerfetto(any());
 
         verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED),
                 eq(42), /* displayId */
                 eq(DisplayRefreshRate.REFRESH_RATE_60_HZ),
-                eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_WALLPAPER_TRANSITION]),
+                eq(Cuj.getStatsdInteractionType(CUJ_WALLPAPER_TRANSITION)),
                 eq(2L) /* totalFrames */,
                 eq(0L) /* missedFrames */,
                 eq(0L) /* maxFrameTimeNanos */,
@@ -587,8 +574,7 @@
 
     @Test
     public void testMaxSuccessiveMissedFramesCount() {
-        FrameTracker tracker = spyFrameTracker(
-                CUJ_WALLPAPER_TRANSITION, CUJ_POSTFIX, /* surfaceOnly= */ true);
+        FrameTracker tracker = spyFrameTracker(/* surfaceOnly= */ true);
         when(mChoreographer.getVsyncId()).thenReturn(100L);
         tracker.begin();
         mRunnableArgumentCaptor.getValue().run();
@@ -604,11 +590,11 @@
         sendFrame(tracker, JANK_SURFACEFLINGER_DEADLINE_MISSED, 106L);
         sendFrame(tracker, JANK_SURFACEFLINGER_DEADLINE_MISSED, 107L);
         verify(mSurfaceControlWrapper).removeJankStatsListener(any());
-        verify(tracker).triggerPerfetto();
+        verify(mTrackerListener).triggerPerfetto(any());
         verify(mStatsLog).write(eq(UI_INTERACTION_FRAME_INFO_REPORTED),
                 eq(42), /* displayId */
                 eq(DisplayRefreshRate.REFRESH_RATE_60_HZ),
-                eq(CUJ_TO_STATSD_INTERACTION_TYPE[CUJ_WALLPAPER_TRANSITION]),
+                eq(Cuj.getStatsdInteractionType(CUJ_WALLPAPER_TRANSITION)),
                 eq(6L) /* totalFrames */,
                 eq(5L) /* missedFrames */,
                 eq(0L) /* maxFrameTimeNanos */,
diff --git a/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java b/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java
index b61f995..68095e5 100644
--- a/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java
+++ b/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java
@@ -20,23 +20,9 @@
 
 import static com.android.internal.jank.FrameTracker.REASON_CANCEL_TIMEOUT;
 import static com.android.internal.jank.FrameTracker.REASON_END_NORMAL;
-import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_ADD;
-import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_APP_START;
-import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_HEADS_UP_APPEAR;
-import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_HEADS_UP_DISAPPEAR;
-import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_REMOVE;
-import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE;
-import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE;
-import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE;
-import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_ROW_EXPAND;
-import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_ROW_SWIPE;
-import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_SCROLL_FLING;
-import static com.android.internal.jank.InteractionJankMonitor.CUJ_TO_STATSD_INTERACTION_TYPE;
-import static com.android.internal.jank.InteractionJankMonitor.MAX_LENGTH_OF_CUJ_NAME;
-import static com.android.internal.jank.InteractionJankMonitor.getNameOfCuj;
+import static com.android.internal.jank.InteractionJankMonitor.Configuration.generateSessionName;
 
 import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -52,12 +38,11 @@
 import android.os.HandlerThread;
 import android.os.SystemClock;
 import android.provider.DeviceConfig;
-import android.util.SparseArray;
 import android.view.View;
 import android.view.ViewAttachTestActivity;
 
+import androidx.test.ext.junit.rules.ActivityScenarioRule;
 import androidx.test.filters.SmallTest;
-import androidx.test.rule.ActivityTestRule;
 
 import com.android.internal.jank.FrameTracker.ChoreographerWrapper;
 import com.android.internal.jank.FrameTracker.FrameMetricsWrapper;
@@ -66,101 +51,54 @@
 import com.android.internal.jank.FrameTracker.ThreadedRendererWrapper;
 import com.android.internal.jank.FrameTracker.ViewRootWrapper;
 import com.android.internal.jank.InteractionJankMonitor.Configuration;
-import com.android.internal.jank.InteractionJankMonitor.Session;
-import com.android.internal.util.FrameworkStatsLog;
 
 import com.google.common.truth.Expect;
 
 import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Rule;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
 
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
 
 @SmallTest
 public class InteractionJankMonitorTest {
-    private static final String CUJ_POSTFIX = "";
-    private static final SparseArray<String> ENUM_NAME_EXCEPTION_MAP = new SparseArray<>();
-    private static final String ENUM_NAME_PREFIX =
-            "UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__";
-
-    private static final ArrayList<String> DEPRECATED_VALUES = new ArrayList<>();
-
     private ViewAttachTestActivity mActivity;
     private View mView;
+    private Handler mHandler;
     private HandlerThread mWorker;
 
     @Rule
-    public ActivityTestRule<ViewAttachTestActivity> mRule =
-            new ActivityTestRule<>(ViewAttachTestActivity.class);
+    public ActivityScenarioRule<ViewAttachTestActivity> mRule =
+            new ActivityScenarioRule<>(ViewAttachTestActivity.class);
 
     @Rule
     public final Expect mExpect = Expect.create();
 
-    @BeforeClass
-    public static void initialize() {
-        ENUM_NAME_EXCEPTION_MAP.put(CUJ_NOTIFICATION_ADD, getEnumName("SHADE_NOTIFICATION_ADD"));
-        ENUM_NAME_EXCEPTION_MAP.put(CUJ_NOTIFICATION_APP_START, getEnumName("SHADE_APP_LAUNCH"));
-        ENUM_NAME_EXCEPTION_MAP.put(
-                CUJ_NOTIFICATION_HEADS_UP_APPEAR, getEnumName("SHADE_HEADS_UP_APPEAR"));
-        ENUM_NAME_EXCEPTION_MAP.put(
-                CUJ_NOTIFICATION_HEADS_UP_DISAPPEAR, getEnumName("SHADE_HEADS_UP_DISAPPEAR"));
-        ENUM_NAME_EXCEPTION_MAP.put(
-                CUJ_NOTIFICATION_REMOVE, getEnumName("SHADE_NOTIFICATION_REMOVE"));
-        ENUM_NAME_EXCEPTION_MAP.put(
-                CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, getEnumName("NOTIFICATION_SHADE_SWIPE"));
-        ENUM_NAME_EXCEPTION_MAP.put(
-                CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE, getEnumName("SHADE_QS_EXPAND_COLLAPSE"));
-        ENUM_NAME_EXCEPTION_MAP.put(
-                CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE, getEnumName("SHADE_QS_SCROLL_SWIPE"));
-        ENUM_NAME_EXCEPTION_MAP.put(
-                CUJ_NOTIFICATION_SHADE_ROW_EXPAND, getEnumName("SHADE_ROW_EXPAND"));
-        ENUM_NAME_EXCEPTION_MAP.put(
-                CUJ_NOTIFICATION_SHADE_ROW_SWIPE, getEnumName("SHADE_ROW_SWIPE"));
-        ENUM_NAME_EXCEPTION_MAP.put(
-                CUJ_NOTIFICATION_SHADE_SCROLL_FLING, getEnumName("SHADE_SCROLL_FLING"));
-        DEPRECATED_VALUES.add(ENUM_NAME_PREFIX + "IME_INSETS_ANIMATION");
-    }
-
-    private static String getEnumName(String name) {
-        return formatSimple("%s%s", ENUM_NAME_PREFIX, name);
-    }
-
     @Before
     public void setup() {
-        // Prepare an activity for getting ThreadedRenderer later.
-        mActivity = mRule.getActivity();
+        mRule.getScenario().onActivity(activity -> mActivity = activity);
         mView = mActivity.getWindow().getDecorView();
         assertThat(mView.isAttachedToWindow()).isTrue();
 
-        Handler handler = spy(new Handler(mActivity.getMainLooper()));
-        doReturn(true).when(handler).sendMessageAtTime(any(), anyLong());
+        mHandler = spy(new Handler(mActivity.getMainLooper()));
+        doReturn(true).when(mHandler).sendMessageAtTime(any(), anyLong());
         mWorker = mock(HandlerThread.class);
-        doReturn(handler).when(mWorker).getThreadHandler();
+        doReturn(mHandler).when(mWorker).getThreadHandler();
     }
 
     @Test
     public void testBeginEnd() {
         InteractionJankMonitor monitor = createMockedInteractionJankMonitor();
-        FrameTracker tracker = createMockedFrameTracker(monitor, null);
-        doReturn(tracker).when(monitor).createFrameTracker(any(), any());
+        FrameTracker tracker = createMockedFrameTracker();
+        doReturn(tracker).when(monitor).createFrameTracker(any());
         doNothing().when(tracker).begin();
         doReturn(true).when(tracker).end(anyInt());
 
         // Simulate a trace session and see if begin / end are invoked.
-        assertThat(monitor.begin(mView, CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isTrue();
+        assertThat(monitor.begin(mView, Cuj.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isTrue();
         verify(tracker).begin();
-        assertThat(monitor.end(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isTrue();
+        assertThat(monitor.end(Cuj.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isTrue();
         verify(tracker).end(REASON_END_NORMAL);
     }
 
@@ -172,10 +110,10 @@
         propertiesValues.put("enabled", "false");
         DeviceConfig.Properties properties = new DeviceConfig.Properties(
                 DeviceConfig.NAMESPACE_INTERACTION_JANK_MONITOR, propertiesValues);
-        monitor.getPropertiesChangedListener().onPropertiesChanged(properties);
+        monitor.updateProperties(properties);
 
-        assertThat(monitor.begin(mView, CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isFalse();
-        assertThat(monitor.end(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isFalse();
+        assertThat(monitor.begin(mView, Cuj.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isFalse();
+        assertThat(monitor.end(Cuj.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isFalse();
     }
 
     @Test
@@ -185,145 +123,57 @@
         assertThat(view.isAttachedToWindow()).isFalse();
 
         // Should return false if the view passed in is not attached to window yet.
-        assertThat(monitor.begin(view, CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isFalse();
-        assertThat(monitor.end(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isFalse();
+        assertThat(monitor.begin(view, Cuj.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isFalse();
+        assertThat(monitor.end(Cuj.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isFalse();
     }
 
     @Test
     public void testBeginTimeout() {
         ArgumentCaptor<Runnable> captor = ArgumentCaptor.forClass(Runnable.class);
         InteractionJankMonitor monitor = createMockedInteractionJankMonitor();
-        FrameTracker tracker = createMockedFrameTracker(monitor, null);
-        doReturn(tracker).when(monitor).createFrameTracker(any(), any());
+        FrameTracker tracker = createMockedFrameTracker();
+        doReturn(tracker).when(monitor).createFrameTracker(any());
         doNothing().when(tracker).begin();
         doReturn(true).when(tracker).cancel(anyInt());
 
-        assertThat(monitor.begin(mView, CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isTrue();
+        assertThat(monitor.begin(mView, Cuj.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isTrue();
         verify(tracker).begin();
-        verify(monitor).scheduleTimeoutAction(anyInt(), anyLong(), captor.capture());
+        verify(monitor).scheduleTimeoutAction(any(), captor.capture());
         Runnable runnable = captor.getValue();
         assertThat(runnable).isNotNull();
-        mWorker.getThreadHandler().removeCallbacks(runnable);
         runnable.run();
-        verify(monitor).cancel(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, REASON_CANCEL_TIMEOUT);
+        verify(monitor).cancel(Cuj.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, REASON_CANCEL_TIMEOUT);
         verify(tracker).cancel(REASON_CANCEL_TIMEOUT);
     }
 
     @Test
-    public void testCujTypeEnumCorrectlyDefined() throws Exception {
-        List<Field> cujEnumFields =
-                Arrays.stream(InteractionJankMonitor.class.getDeclaredFields())
-                        .filter(field -> field.getName().startsWith("CUJ_")
-                                && Modifier.isStatic(field.getModifiers())
-                                && field.getType() == int.class)
-                        .collect(Collectors.toList());
-
-        HashSet<Integer> allValues = new HashSet<>();
-        for (Field field : cujEnumFields) {
-            int fieldValue = field.getInt(null);
-            assertWithMessage(
-                    "Field %s must have a mapping to a value in CUJ_TO_STATSD_INTERACTION_TYPE",
-                    field.getName())
-                    .that(fieldValue < CUJ_TO_STATSD_INTERACTION_TYPE.length)
-                    .isTrue();
-            assertWithMessage("All CujType values must be unique. Field %s repeats existing value.",
-                    field.getName())
-                    .that(allValues.add(fieldValue))
-                    .isTrue();
-        }
-    }
-
-    @Test
-    public void testCujsMapToEnumsCorrectly() {
-        List<Field> cujs = Arrays.stream(InteractionJankMonitor.class.getDeclaredFields())
-                .filter(f -> f.getName().startsWith("CUJ_")
-                        && Modifier.isStatic(f.getModifiers())
-                        && f.getType() == int.class)
-                .collect(Collectors.toList());
-
-        Map<Integer, String> enumsMap = Arrays.stream(FrameworkStatsLog.class.getDeclaredFields())
-                .filter(f -> f.getName().startsWith(ENUM_NAME_PREFIX)
-                        && !DEPRECATED_VALUES.contains(f.getName())
-                        && Modifier.isStatic(f.getModifiers())
-                        && f.getType() == int.class)
-                .collect(Collectors.toMap(this::getIntFieldChecked, Field::getName));
-
-        assertThat(enumsMap.size() - 1).isEqualTo(cujs.size());
-
-        cujs.forEach(f -> {
-            final int cuj = getIntFieldChecked(f);
-            final String cujName = f.getName();
-            final String expectedEnumName = ENUM_NAME_EXCEPTION_MAP.contains(cuj)
-                    ? ENUM_NAME_EXCEPTION_MAP.get(cuj)
-                    : formatSimple("%s%s", ENUM_NAME_PREFIX, cujName.substring(4));
-            final int enumKey = CUJ_TO_STATSD_INTERACTION_TYPE[cuj];
-            final String enumName = enumsMap.get(enumKey);
-            final String expectedNameOfCuj = formatSimple("CUJ_%s", getNameOfCuj(cuj));
-
-            mExpect
-                    .withMessage(formatSimple(
-                            "%s (%d) not matches %s (%d)", cujName, cuj, enumName, enumKey))
-                    .that(expectedEnumName.equals(enumName))
-                    .isTrue();
-            mExpect
-                    .withMessage(
-                            formatSimple("getNameOfCuj(%d) not matches: %s, expected=%s",
-                                    cuj, cujName, expectedNameOfCuj))
-                    .that(cujName.equals(expectedNameOfCuj))
-                    .isTrue();
-        });
-    }
-
-    @Test
-    public void testCujNameLimit() {
-        Arrays.stream(InteractionJankMonitor.class.getDeclaredFields())
-                .filter(f -> f.getName().startsWith("CUJ_")
-                        && Modifier.isStatic(f.getModifiers())
-                        && f.getType() == int.class)
-                .forEach(f -> {
-                    final int cuj = getIntFieldChecked(f);
-                    mExpect
-                            .withMessage(formatSimple(
-                                    "Too long CUJ(%d) name: %s", cuj, getNameOfCuj(cuj)))
-                            .that(getNameOfCuj(cuj).length())
-                            .isAtMost(MAX_LENGTH_OF_CUJ_NAME);
-                });
-    }
-
-    @Test
     public void testSessionNameLengthLimit() {
-        final int cujType = CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE;
-        final String cujName = getNameOfCuj(cujType);
+        final int cujType = Cuj.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE;
+        final String cujName = Cuj.getNameOfCuj(cujType);
         final String cujTag = "ThisIsTheCujTag";
         final String tooLongTag = cujTag.repeat(10);
 
         // Normal case, no postfix.
-        Session noPostfix = new Session(cujType, "");
-        assertThat(noPostfix.getName()).isEqualTo(formatSimple("J<%s>", cujName));
+        assertThat(generateSessionName(cujName, "")).isEqualTo(formatSimple("J<%s>", cujName));
 
         // Normal case, with postfix.
-        Session withPostfix = new Session(cujType, cujTag);
-        assertThat(withPostfix.getName()).isEqualTo(formatSimple("J<%s::%s>", cujName, cujTag));
+        assertThat(generateSessionName(cujName, cujTag))
+                .isEqualTo(formatSimple("J<%s::%s>", cujName, cujTag));
 
         // Since the length of the cuj name is tested in another test, no need to test it here.
         // Too long postfix case, should trim the postfix and keep the cuj name completed.
         final String expectedTrimmedName = formatSimple("J<%s::%s>", cujName,
                 "ThisIsTheCujTagThisIsTheCujTagThisIsTheCujTagThisIsTheCujTagThi...");
-        Session longPostfix = new Session(cujType, tooLongTag);
-        assertThat(longPostfix.getName()).isEqualTo(expectedTrimmedName);
+        assertThat(generateSessionName(cujName, tooLongTag)).isEqualTo(expectedTrimmedName);
     }
 
     private InteractionJankMonitor createMockedInteractionJankMonitor() {
         InteractionJankMonitor monitor = spy(new InteractionJankMonitor(mWorker));
-        doReturn(true).when(monitor).shouldMonitor(anyInt());
+        doReturn(true).when(monitor).shouldMonitor();
         return monitor;
     }
 
-    private FrameTracker createMockedFrameTracker(InteractionJankMonitor monitor,
-            FrameTracker.FrameTrackerListener listener) {
-        Session session = spy(new Session(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, CUJ_POSTFIX));
-        doReturn(false).when(session).logToStatsd();
-
+    private FrameTracker createMockedFrameTracker() {
         ThreadedRendererWrapper threadedRenderer = mock(ThreadedRendererWrapper.class);
         doNothing().when(threadedRenderer).addObserver(any());
         doNothing().when(threadedRenderer).removeObserver(any());
@@ -342,27 +192,19 @@
         Configuration configuration = mock(Configuration.class);
         when(configuration.isSurfaceOnly()).thenReturn(false);
         when(configuration.getView()).thenReturn(mView);
-        when(configuration.getHandler()).thenReturn(mView.getHandler());
         when(configuration.getDisplayId()).thenReturn(42);
+        when(configuration.logToStatsd()).thenReturn(false);
+        when(configuration.getHandler()).thenReturn(mHandler);
 
-        FrameTracker tracker = spy(new FrameTracker(monitor, session, mWorker.getThreadHandler(),
+        FrameTracker tracker = spy(new FrameTracker(configuration,
                 threadedRenderer, viewRoot, surfaceControl, choreographer,
                 new FrameMetricsWrapper(), new StatsLogWrapper(null),
                 /* traceThresholdMissedFrames= */ 1,
-                /* traceThresholdFrameTimeMillis= */ -1, listener, configuration));
+                /* traceThresholdFrameTimeMillis= */ -1,
+                /* listener */ null));
 
         doNothing().when(tracker).postTraceStartMarker(any());
-        doNothing().when(tracker).triggerPerfetto();
-        doReturn(configuration.getHandler()).when(tracker).getHandler();
 
         return tracker;
     }
-
-    private int getIntFieldChecked(Field field) {
-        try {
-            return field.getInt(null);
-        } catch (IllegalAccessException ex) {
-            throw new RuntimeException(ex);
-        }
-    }
 }
diff --git a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
index 8207c9e..b70f290 100644
--- a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
@@ -29,7 +29,9 @@
 import android.os.Message;
 import android.os.Process;
 import android.os.SystemClock;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
 import android.platform.test.annotations.Presubmit;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.util.ArrayMap;
 import android.util.SparseArray;
 
@@ -39,6 +41,8 @@
 import com.android.internal.os.BinderInternal.CallSession;
 
 import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -55,13 +59,22 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 @Presubmit
+@IgnoreUnderRavenwood(blockedBy = BinderCallsStats.class)
 public class BinderCallsStatsTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     private static final int WORKSOURCE_UID = Process.FIRST_APPLICATION_UID;
     private static final int CALLING_UID = 2;
     private static final int REQUEST_SIZE = 2;
     private static final int REPLY_SIZE = 3;
     private final CachedDeviceState mDeviceState = new CachedDeviceState(false, true);
-    private final TestHandler mHandler = new TestHandler();
+    private TestHandler mHandler;
+
+    @Before
+    public void setUp() {
+        mHandler = new TestHandler();
+    }
 
     @Test
     public void testDetailedOff() {
diff --git a/core/tests/coretests/src/com/android/internal/os/BinderHeavyHitterTest.java b/core/tests/coretests/src/com/android/internal/os/BinderHeavyHitterTest.java
index e4597b5..a1b80d2 100644
--- a/core/tests/coretests/src/com/android/internal/os/BinderHeavyHitterTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BinderHeavyHitterTest.java
@@ -16,11 +16,19 @@
 
 package com.android.internal.os;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
 import android.os.Binder;
 
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.os.BinderCallHeavyHitterWatcher.HeavyHitterContainer;
 
-import junit.framework.TestCase;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -29,7 +37,8 @@
 /**
  * Tests for {@link BinderCallHeavyHitterWatcher}.
  */
-public final class BinderHeavyHitterTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+public final class BinderHeavyHitterTest {
 
     private boolean mListenerNotified = false;
 
@@ -114,6 +123,7 @@
         }
     }
 
+    @Test
     public void testPositive() throws Exception {
         BinderCallHeavyHitterWatcher watcher = BinderCallHeavyHitterWatcher.getInstance();
         try {
@@ -142,6 +152,7 @@
         }
     }
 
+    @Test
     public void testNegative() throws Exception {
         BinderCallHeavyHitterWatcher watcher = BinderCallHeavyHitterWatcher.getInstance();
         try {
diff --git a/core/tests/coretests/src/com/android/internal/os/BinderLatencyObserverTest.java b/core/tests/coretests/src/com/android/internal/os/BinderLatencyObserverTest.java
index 7bd53b9..31b55e6 100644
--- a/core/tests/coretests/src/com/android/internal/os/BinderLatencyObserverTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BinderLatencyObserverTest.java
@@ -23,7 +23,9 @@
 import static org.junit.Assert.assertEquals;
 
 import android.os.Binder;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
 import android.platform.test.annotations.Presubmit;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.util.ArrayMap;
 import android.util.proto.ProtoOutputStream;
 
@@ -36,6 +38,7 @@
 import com.android.internal.os.BinderLatencyProto.Dims;
 import com.android.internal.os.BinderLatencyProto.RepeatedApiStats;
 
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -47,7 +50,11 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 @Presubmit
+@IgnoreUnderRavenwood(blockedBy = BinderLatencyObserver.class)
 public class BinderLatencyObserverTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     @Test
     public void testLatencyCollectionWithMultipleClasses() {
         TestBinderLatencyObserver blo = new TestBinderLatencyObserver();
diff --git a/core/tests/coretests/src/com/android/internal/os/BinderfsStatsReaderTest.java b/core/tests/coretests/src/com/android/internal/os/BinderfsStatsReaderTest.java
index e9f6450..5f02f04 100644
--- a/core/tests/coretests/src/com/android/internal/os/BinderfsStatsReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BinderfsStatsReaderTest.java
@@ -20,11 +20,9 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 
-import android.content.Context;
 import android.os.FileUtils;
 import android.util.IntArray;
 
-import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
@@ -102,9 +100,8 @@
     private boolean mHasError;
 
     @Before
-    public void setUp() {
-        Context context = InstrumentationRegistry.getContext();
-        mStatsDirectory = context.getDir("binder_logs", Context.MODE_PRIVATE);
+    public void setUp() throws Exception {
+        mStatsDirectory = Files.createTempDirectory("BinderfsStatsReaderTest").toFile();
         mFreezerBinderAsyncThreshold = 1024;
         mValidPids = IntArray.fromArray(new int[]{14505, 14461, 542, 540}, 4);
         mStatsPids = new IntArray();
diff --git a/core/tests/coretests/src/com/android/internal/os/CpuScalingPolicyReaderTest.java b/core/tests/coretests/src/com/android/internal/os/CpuScalingPolicyReaderTest.java
index 7f054d1..2da3873 100644
--- a/core/tests/coretests/src/com/android/internal/os/CpuScalingPolicyReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/CpuScalingPolicyReaderTest.java
@@ -16,11 +16,8 @@
 
 package com.android.internal.os;
 
-import static androidx.test.InstrumentationRegistry.getContext;
-
 import static com.google.common.truth.Truth.assertThat;
 
-import android.content.Context;
 import android.os.FileUtils;
 
 import androidx.test.runner.AndroidJUnit4;
@@ -31,6 +28,7 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.nio.file.Files;
 
 @RunWith(AndroidJUnit4.class)
 public class CpuScalingPolicyReaderTest {
@@ -38,7 +36,7 @@
 
     @Before
     public void setup() throws IOException {
-        File testDir = getContext().getDir("test", Context.MODE_PRIVATE);
+        File testDir = Files.createTempDirectory("CpuScalingPolicyReaderTest").toFile();
         FileUtils.deleteContents(testDir);
 
         File policy0 = new File(testDir, "policy0");
diff --git a/core/tests/coretests/src/com/android/internal/os/DebugTest.java b/core/tests/coretests/src/com/android/internal/os/DebugTest.java
index 2a8a857..4371f26 100644
--- a/core/tests/coretests/src/com/android/internal/os/DebugTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/DebugTest.java
@@ -16,14 +16,22 @@
 
 package com.android.internal.os;
 
+import static org.junit.Assert.assertTrue;
+
 import android.os.Debug;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 
 import androidx.test.filters.SmallTest;
 
-import junit.framework.TestCase;
+import org.junit.Rule;
+import org.junit.Test;
 
 @SmallTest
-public class DebugTest extends TestCase {
+@IgnoreUnderRavenwood(reason = "Requires ART support")
+public class DebugTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
 
     private final static String EXPECTED_GET_CALLER =
             "com\\.android\\.internal\\.os\\.DebugTest\\.testGetCaller:\\d\\d";
@@ -39,6 +47,7 @@
         return Debug.getCaller();
     }
 
+    @Test
     public void testGetCaller() {
         assertTrue(callDepth0().matches(EXPECTED_GET_CALLER));
     }
@@ -62,6 +71,7 @@
         return callDepth2();
     }
 
+    @Test
     public void testGetCallers() {
         assertTrue(callDepth1().matches(EXPECTED_GET_CALLERS));
     }
@@ -69,6 +79,7 @@
     /**
      * Regression test for b/31943543. Note: must be run under CheckJNI to detect the issue.
      */
+    @Test
     public void testGetMemoryInfo() {
         Debug.MemoryInfo info = new Debug.MemoryInfo();
         Debug.getMemoryInfo(-1, info);
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuProcStringReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuProcStringReaderTest.java
index cbd2ba4..1d8628d 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelCpuProcStringReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuProcStringReaderTest.java
@@ -24,6 +24,8 @@
 import android.content.Context;
 import android.os.FileUtils;
 import android.os.SystemClock;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
@@ -31,6 +33,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -57,7 +60,11 @@
  */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(reason = "Needs kernel support")
 public class KernelCpuProcStringReaderTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     private File mRoot;
     private File mTestDir;
     private File mTestFile;
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderDiffTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderDiffTest.java
index b45f8d2..a57a400 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderDiffTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderDiffTest.java
@@ -24,13 +24,16 @@
 
 import static java.util.stream.Collectors.toList;
 
+import android.platform.test.annotations.IgnoreUnderRavenwood;
 import android.platform.test.annotations.Presubmit;
+import android.platform.test.ravenwood.RavenwoodRule;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -44,7 +47,10 @@
 @Presubmit
 @SmallTest
 @RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(reason = "Needs kernel support")
 public class KernelCpuThreadReaderDiffTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
 
     private MockitoSession mMockingSessions;
     @Mock KernelCpuThreadReader mMockReader;
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderEndToEndTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderEndToEndTest.java
index d43989c..8c5e3d0 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderEndToEndTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderEndToEndTest.java
@@ -22,6 +22,8 @@
 
 import android.os.Process;
 import android.os.SystemClock;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.LargeTest;
@@ -29,6 +31,7 @@
 import com.android.internal.os.KernelCpuThreadReader.ProcessCpuUsage;
 import com.android.internal.os.KernelCpuThreadReader.ThreadCpuUsage;
 
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -47,7 +50,10 @@
  */
 @RunWith(AndroidJUnit4.class)
 @LargeTest
+@IgnoreUnderRavenwood(reason = "Needs kernel support")
 public class KernelCpuThreadReaderEndToEndTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
 
     private static final int TIMED_NUM_SAMPLES = 5;
     private static final int TIMED_START_MILLIS = 500;
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderTest.java
index c3e4014..7eac2a3 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderTest.java
@@ -25,7 +25,9 @@
 
 import android.content.Context;
 import android.os.FileUtils;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
 import android.platform.test.annotations.Presubmit;
+import android.platform.test.ravenwood.RavenwoodRule;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
@@ -33,6 +35,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -48,7 +51,11 @@
 @Presubmit
 @SmallTest
 @RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(reason = "Needs kernel support")
 public class KernelCpuThreadReaderTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     private File mProcDirectory;
 
     @Before
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidActiveTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidActiveTimeReaderTest.java
index 2ccd74e..d35e0fc 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidActiveTimeReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidActiveTimeReaderTest.java
@@ -21,6 +21,8 @@
 
 import android.content.Context;
 import android.os.FileUtils;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.util.SparseArray;
 import android.util.SparseLongArray;
 
@@ -31,6 +33,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -51,7 +54,11 @@
  */
 @SmallTest
 @RunWith(Parameterized.class)
+@IgnoreUnderRavenwood(reason = "Needs kernel support")
 public class KernelCpuUidActiveTimeReaderTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     private File mTestDir;
     private File mTestFile;
     private KernelCpuUidActiveTimeReader mReader;
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidBpfMapReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidBpfMapReaderTest.java
index bda21c6..610e6ae 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidBpfMapReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidBpfMapReaderTest.java
@@ -23,11 +23,15 @@
 import static org.junit.Assert.assertTrue;
 
 import android.content.Context;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.util.SparseArray;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
 import org.junit.runner.RunWith;
 
 import com.android.internal.os.KernelCpuUidBpfMapReader.BpfMapIterator;
@@ -50,7 +54,11 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(reason = "Needs kernel support")
 public class KernelCpuUidBpfMapReaderTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     private Random mRand = new Random(12345);
     private KernelCpuUidTestBpfMapReader mReader;
 
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidClusterTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidClusterTimeReaderTest.java
index a0dab28..8807de0 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidClusterTimeReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidClusterTimeReaderTest.java
@@ -23,6 +23,8 @@
 
 import android.content.Context;
 import android.os.FileUtils;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.util.SparseArray;
 
 import androidx.test.InstrumentationRegistry;
@@ -32,6 +34,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -52,7 +55,11 @@
  */
 @SmallTest
 @RunWith(Parameterized.class)
+@IgnoreUnderRavenwood(reason = "Needs kernel support")
 public class KernelCpuUidClusterTimeReaderTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     private File mTestDir;
     private File mTestFile;
     private KernelCpuUidClusterTimeReader mReader;
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidFreqTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidFreqTimeReaderTest.java
index 783f264..b730344 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidFreqTimeReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidFreqTimeReaderTest.java
@@ -24,6 +24,8 @@
 
 import android.content.Context;
 import android.os.FileUtils;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.util.SparseArray;
 
 import androidx.test.InstrumentationRegistry;
@@ -33,6 +35,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -55,7 +58,11 @@
  */
 @SmallTest
 @RunWith(Parameterized.class)
+@IgnoreUnderRavenwood(reason = "Needs kernel support")
 public class KernelCpuUidFreqTimeReaderTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     private File mTestDir;
     private File mTestFile;
     private KernelCpuUidFreqTimeReader mReader;
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidUserSysTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidUserSysTimeReaderTest.java
index 1da1a90..6507226 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidUserSysTimeReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidUserSysTimeReaderTest.java
@@ -23,6 +23,8 @@
 
 import android.content.Context;
 import android.os.FileUtils;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.util.SparseArray;
 
 import androidx.test.InstrumentationRegistry;
@@ -33,6 +35,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -49,7 +52,11 @@
  */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(reason = "Needs kernel support")
 public class KernelCpuUidUserSysTimeReaderTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     private File mTestDir;
     private File mTestFile;
     private KernelCpuUidTimeReader.KernelCpuUidUserSysTimeReader mReader;
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelMemoryBandwidthStatsTest.java b/core/tests/coretests/src/com/android/internal/os/KernelMemoryBandwidthStatsTest.java
index 60dac85..ad5186e 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelMemoryBandwidthStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelMemoryBandwidthStatsTest.java
@@ -16,12 +16,18 @@
 
 package com.android.internal.os;
 
+import static org.junit.Assert.assertEquals;
+
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.util.LongSparseLongArray;
 
 import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
-import junit.framework.TestCase;
-
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.mockito.Mockito;
 
 import java.io.BufferedReader;
@@ -29,12 +35,17 @@
 /**
  * Tests for KernelMemoryBandwidthStats parsing and delta calculation, based on memory_state_time.
  */
-public class KernelMemoryBandwidthStatsTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(reason = "Needs kernel support")
+public class KernelMemoryBandwidthStatsTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
 
     /**
      * Standard example of parsing stats.
      * @throws Exception
      */
+    @Test
     @SmallTest
     public void testParseStandard() throws Exception {
         KernelMemoryBandwidthStats stats = new KernelMemoryBandwidthStats();
@@ -68,6 +79,7 @@
      * zero.
      * @throws Exception
      */
+    @Test
     @SmallTest
     public void testParseBackwards() throws Exception {
         KernelMemoryBandwidthStats zeroStats = new KernelMemoryBandwidthStats();
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelSingleProcessCpuThreadReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelSingleProcessCpuThreadReaderTest.java
index 2de800b..f42d26d 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelSingleProcessCpuThreadReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelSingleProcessCpuThreadReaderTest.java
@@ -19,9 +19,13 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
+
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -31,7 +35,10 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(reason = "Needs kernel support")
 public class KernelSingleProcessCpuThreadReaderTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
 
     @Test
     public void getProcessCpuUsage() throws IOException {
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelSingleUidTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelSingleUidTimeReaderTest.java
index 74ab644..120a4de 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelSingleUidTimeReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelSingleUidTimeReaderTest.java
@@ -23,6 +23,8 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.util.SparseArray;
 
 import androidx.test.filters.SmallTest;
@@ -30,6 +32,7 @@
 import com.android.internal.os.KernelSingleUidTimeReader.Injector;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -43,7 +46,11 @@
 
 @SmallTest
 @RunWith(Parameterized.class)
+@IgnoreUnderRavenwood(reason = "Needs kernel support")
 public class KernelSingleUidTimeReaderTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     private final static int TEST_UID = 2222;
     private final static int TEST_FREQ_COUNT = 5;
 
diff --git a/core/tests/coretests/src/com/android/internal/os/LoggingPrintStreamTest.java b/core/tests/coretests/src/com/android/internal/os/LoggingPrintStreamTest.java
index cb8a62c..632dce0 100644
--- a/core/tests/coretests/src/com/android/internal/os/LoggingPrintStreamTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/LoggingPrintStreamTest.java
@@ -16,9 +16,13 @@
 
 package com.android.internal.os;
 
-import androidx.test.filters.Suppress;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
-import junit.framework.TestCase;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
@@ -28,11 +32,12 @@
 import java.util.List;
 
 // this test causes a IllegalAccessError: superclass not accessible
-@Suppress
-public class LoggingPrintStreamTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+public class LoggingPrintStreamTest {
 
     TestPrintStream out = new TestPrintStream();
 
+    @Test
     public void testPrintException() {
         @SuppressWarnings("ThrowableInstanceNeverThrown")
         Throwable t = new Throwable("Ignore me.");
@@ -47,6 +52,7 @@
         assertEquals(Arrays.asList(lines), out.lines);
     }
 
+    @Test
     public void testPrintObject() {
         Object o = new Object();
         out.print(4);
@@ -56,6 +62,7 @@
         assertEquals(Arrays.asList("4" + o + "2"), out.lines);
     }
 
+    @Test
     public void testPrintlnObject() {
         Object o = new Object();
         out.print(4);
@@ -65,6 +72,7 @@
         assertEquals(Arrays.asList("4" + o, "2"), out.lines);
     }
 
+    @Test
     public void testPrintf() {
         out.printf("Name: %s\nEmployer: %s", "Bob", "Google");
         assertEquals(Arrays.asList("Name: Bob"), out.lines);
@@ -72,6 +80,7 @@
         assertEquals(Arrays.asList("Name: Bob", "Employer: Google"), out.lines);
     }
 
+    @Test
     public void testPrintInt() {
         out.print(4);
         out.print(2);
@@ -80,12 +89,14 @@
         assertEquals(Collections.singletonList("42"), out.lines);
     }
 
+    @Test
     public void testPrintlnInt() {
         out.println(4);
         out.println(2);
         assertEquals(Arrays.asList("4", "2"), out.lines);
     }
 
+    @Test
     public void testPrintCharArray() {
         out.print("Foo\nBar\nTee".toCharArray());
         assertEquals(Arrays.asList("Foo", "Bar"), out.lines);
@@ -93,6 +104,7 @@
         assertEquals(Arrays.asList("Foo", "Bar", "Tee"), out.lines);
     }
 
+    @Test
     public void testPrintString() {
         out.print("Foo\nBar\nTee");
         assertEquals(Arrays.asList("Foo", "Bar"), out.lines);
@@ -100,22 +112,26 @@
         assertEquals(Arrays.asList("Foo", "Bar", "Tee"), out.lines);
     }
 
+    @Test
     public void testPrintlnCharArray() {
         out.println("Foo\nBar\nTee".toCharArray());
         assertEquals(Arrays.asList("Foo", "Bar", "Tee"), out.lines);
     }
 
+    @Test
     public void testPrintlnString() {
         out.println("Foo\nBar\nTee");
         assertEquals(Arrays.asList("Foo", "Bar", "Tee"), out.lines);
     }
 
+    @Test
     public void testPrintlnStringWithBufferedData() {
         out.print(5);
         out.println("Foo\nBar\nTee");
         assertEquals(Arrays.asList("5Foo", "Bar", "Tee"), out.lines);
     }
 
+    @Test
     public void testAppend() {
         out.append("Foo\n")
             .append('4')
@@ -125,6 +141,7 @@
         assertEquals(Arrays.asList("Foo", "4", "a"), out.lines);
     }
 
+    @Test
     public void testMultiByteCharactersSpanningBuffers() throws Exception {
         // assume 3*1000 bytes won't fit in LoggingPrintStream's internal buffer
         StringBuilder builder = new StringBuilder();
@@ -138,6 +155,7 @@
         assertEquals(Arrays.asList(expected), out.lines);
     }
 
+    @Test
     public void testWriteOneByteAtATimeMultibyteCharacters() throws Exception {
         String expected = " \u20AC  \u20AC   \u20AC    \u20AC     ";
         for (byte b : expected.getBytes()) {
@@ -147,6 +165,7 @@
         assertEquals(Arrays.asList(expected), out.lines);
     }
 
+    @Test
     public void testWriteByteArrayAtATimeMultibyteCharacters() throws Exception {
         String expected = " \u20AC  \u20AC   \u20AC    \u20AC     ";
         out.write(expected.getBytes());
@@ -154,6 +173,7 @@
         assertEquals(Arrays.asList(expected), out.lines);
     }
 
+    @Test
     public void testWriteWithOffsetsMultibyteCharacters() throws Exception {
         String expected = " \u20AC  \u20AC   \u20AC    \u20AC     ";
         byte[] bytes = expected.getBytes();
@@ -167,6 +187,7 @@
         assertEquals(Arrays.asList(expected), out.lines);
     }
 
+    @Test
     public void testWriteFlushesOnNewlines() throws Exception {
         String a = " \u20AC  \u20AC ";
         String b = "  \u20AC    \u20AC  ";
diff --git a/core/tests/coretests/src/com/android/internal/os/LongArrayMultiStateCounterTest.java b/core/tests/coretests/src/com/android/internal/os/LongArrayMultiStateCounterTest.java
index faccf1a..c9536b9 100644
--- a/core/tests/coretests/src/com/android/internal/os/LongArrayMultiStateCounterTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/LongArrayMultiStateCounterTest.java
@@ -22,16 +22,22 @@
 
 import android.os.BadParcelableException;
 import android.os.Parcel;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
+@IgnoreUnderRavenwood(blockedBy = LongArrayMultiStateCounter.class)
 public class LongArrayMultiStateCounterTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
 
     @Test
     public void setStateAndUpdateValue() {
@@ -51,6 +57,16 @@
     }
 
     @Test
+    public void setValue() {
+        LongArrayMultiStateCounter counter = new LongArrayMultiStateCounter(2, 4);
+
+        counter.setValues(0, new long[]{1, 2, 3, 4});
+        counter.setValues(1, new long[]{5, 6, 7, 8});
+        assertCounts(counter, 0, new long[]{1, 2, 3, 4});
+        assertCounts(counter, 1, new long[]{5, 6, 7, 8});
+    }
+
+    @Test
     public void setEnabled() {
         LongArrayMultiStateCounter counter = new LongArrayMultiStateCounter(2, 4);
         counter.setState(0, 1000);
diff --git a/core/tests/coretests/src/com/android/internal/os/LongMultiStateCounterTest.java b/core/tests/coretests/src/com/android/internal/os/LongMultiStateCounterTest.java
index 3413753..e064e74 100644
--- a/core/tests/coretests/src/com/android/internal/os/LongMultiStateCounterTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/LongMultiStateCounterTest.java
@@ -22,16 +22,22 @@
 
 import android.os.BadParcelableException;
 import android.os.Parcel;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
+@IgnoreUnderRavenwood(blockedBy = LongMultiStateCounterTest.class)
 public class LongMultiStateCounterTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
 
     @Test
     public void setStateAndUpdateValue() {
diff --git a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
index 48baf09..dfb5cc3 100644
--- a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
@@ -23,6 +23,7 @@
 import android.os.Looper;
 import android.os.Message;
 import android.platform.test.annotations.Presubmit;
+import android.platform.test.ravenwood.RavenwoodRule;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
@@ -30,6 +31,7 @@
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -40,6 +42,9 @@
 @RunWith(AndroidJUnit4.class)
 @Presubmit
 public final class LooperStatsTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     private HandlerThread mThreadFirst;
     private HandlerThread mThreadSecond;
     private Handler mHandlerFirst;
diff --git a/core/tests/coretests/src/com/android/internal/os/MonotonicClockTest.java b/core/tests/coretests/src/com/android/internal/os/MonotonicClockTest.java
index 7951270..0742052 100644
--- a/core/tests/coretests/src/com/android/internal/os/MonotonicClockTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/MonotonicClockTest.java
@@ -43,14 +43,12 @@
         assertThat(monotonicClock.monotonicTime()).isEqualTo(1234);
 
         ByteArrayOutputStream out = new ByteArrayOutputStream();
-        monotonicClock.writeXml(out, Xml.newFastSerializer());
-        String xml = out.toString();
-        assertThat(xml).contains("timeshift=\"1234\"");
+        monotonicClock.writeXml(out, Xml.newBinarySerializer());
 
         mClock.realtime = 42;
         MonotonicClock newMonotonicClock = new MonotonicClock(0, mClock);
-        newMonotonicClock.readXml(new ByteArrayInputStream(out.toByteArray()),
-                Xml.newFastPullParser());
+        ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
+        newMonotonicClock.readXml(in, Xml.newBinaryPullParser());
 
         mClock.realtime = 2000;
         assertThat(newMonotonicClock.monotonicTime()).isEqualTo(1234 - 42 + 2000);
diff --git a/core/tests/coretests/src/com/android/internal/os/PowerProfileTest.java b/core/tests/coretests/src/com/android/internal/os/PowerProfileTest.java
index 77202d1..c0f0714 100644
--- a/core/tests/coretests/src/com/android/internal/os/PowerProfileTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/PowerProfileTest.java
@@ -27,6 +27,8 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
@@ -38,6 +40,7 @@
 
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -50,7 +53,10 @@
  */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = PowerProfile.class)
 public class PowerProfileTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
 
     static final String TAG_TEST_MODEM = "test-modem";
     static final String ATTR_NAME = "name";
diff --git a/core/tests/coretests/src/com/android/internal/os/PowerStatsTest.java b/core/tests/coretests/src/com/android/internal/os/PowerStatsTest.java
index 29da231..b99e202 100644
--- a/core/tests/coretests/src/com/android/internal/os/PowerStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/PowerStatsTest.java
@@ -21,17 +21,23 @@
 import android.os.BatteryConsumer;
 import android.os.Parcel;
 import android.os.PersistableBundle;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
+@IgnoreUnderRavenwood(reason = "Needs kernel support")
 public class PowerStatsTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
 
     private PowerStats.DescriptorRegistry mRegistry;
     private PowerStats.Descriptor mDescriptor;
diff --git a/core/tests/coretests/src/com/android/internal/os/ProcLocksReaderTest.java b/core/tests/coretests/src/com/android/internal/os/ProcLocksReaderTest.java
index c3d40eb..f61fc7c 100644
--- a/core/tests/coretests/src/com/android/internal/os/ProcLocksReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/ProcLocksReaderTest.java
@@ -18,11 +18,9 @@
 
 import static org.junit.Assert.assertTrue;
 
-import android.content.Context;
 import android.os.FileUtils;
 import android.util.IntArray;
 
-import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
@@ -45,9 +43,8 @@
     private ArrayList<int[]> mPids = new ArrayList<>();
 
     @Before
-    public void setUp() {
-        Context context = InstrumentationRegistry.getContext();
-        mProcDirectory = context.getDir("proc", Context.MODE_PRIVATE);
+    public void setUp() throws Exception {
+        mProcDirectory = Files.createTempDirectory("ProcLocksReaderTest").toFile();
     }
 
     @After
diff --git a/core/tests/coretests/src/com/android/internal/os/ProcStatsUtilTest.java b/core/tests/coretests/src/com/android/internal/os/ProcStatsUtilTest.java
index e97caf8..3e4f34d 100644
--- a/core/tests/coretests/src/com/android/internal/os/ProcStatsUtilTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/ProcStatsUtilTest.java
@@ -18,10 +18,8 @@
 
 import static org.junit.Assert.assertEquals;
 
-import android.content.Context;
 import android.os.FileUtils;
 
-import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
@@ -41,9 +39,8 @@
     private File mProcDirectory;
 
     @Before
-    public void setUp() {
-        Context context = InstrumentationRegistry.getContext();
-        mProcDirectory = context.getDir("proc", Context.MODE_PRIVATE);
+    public void setUp() throws Exception {
+        mProcDirectory = Files.createTempDirectory("ProcStatsUtilTest").toFile();
     }
 
     @After
diff --git a/core/tests/coretests/src/com/android/internal/os/ProcTimeInStateReaderTest.java b/core/tests/coretests/src/com/android/internal/os/ProcTimeInStateReaderTest.java
index 9db3f8a..a706350 100644
--- a/core/tests/coretests/src/com/android/internal/os/ProcTimeInStateReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/ProcTimeInStateReaderTest.java
@@ -20,15 +20,16 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.fail;
 
-import android.content.Context;
 import android.os.FileUtils;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 
-import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -39,14 +40,16 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = ProcTimeInStateReader.class)
 public class ProcTimeInStateReaderTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
 
     private File mProcDirectory;
 
     @Before
-    public void setUp() {
-        Context context = InstrumentationRegistry.getContext();
-        mProcDirectory = context.getDir("proc", Context.MODE_PRIVATE);
+    public void setUp() throws Exception {
+        mProcDirectory = Files.createTempDirectory("ProcTimeInStateReaderTest").toFile();
     }
 
     @After
diff --git a/core/tests/coretests/src/com/android/internal/os/ProcessCpuTrackerTest.java b/core/tests/coretests/src/com/android/internal/os/ProcessCpuTrackerTest.java
index 81cc9d8..d11c500 100644
--- a/core/tests/coretests/src/com/android/internal/os/ProcessCpuTrackerTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/ProcessCpuTrackerTest.java
@@ -18,15 +18,23 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
+
 import androidx.test.filters.SmallTest;
 
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
 @SmallTest
 @RunWith(JUnit4.class)
+@IgnoreUnderRavenwood(reason = "Needs kernel support")
 public class ProcessCpuTrackerTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     @Test
     public void testGetCpuTime() throws Exception {
         final ProcessCpuTracker tracker = new ProcessCpuTracker(false);
diff --git a/core/tests/coretests/src/com/android/internal/os/StoragedUidIoStatsReaderTest.java b/core/tests/coretests/src/com/android/internal/os/StoragedUidIoStatsReaderTest.java
index 85eafc5..84c93c2 100644
--- a/core/tests/coretests/src/com/android/internal/os/StoragedUidIoStatsReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/StoragedUidIoStatsReaderTest.java
@@ -20,10 +20,8 @@
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.verifyZeroInteractions;
 
-import android.content.Context;
 import android.os.FileUtils;
 
-import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
@@ -48,7 +46,6 @@
 @RunWith(AndroidJUnit4.class)
 public class StoragedUidIoStatsReaderTest {
 
-    private File mRoot;
     private File mTestDir;
     private File mTestFile;
     // private Random mRand = new Random();
@@ -57,15 +54,10 @@
     @Mock
     private StoragedUidIoStatsReader.Callback mCallback;
 
-    private Context getContext() {
-        return InstrumentationRegistry.getContext();
-    }
-
     @Before
-    public void setUp() {
+    public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
-        mTestDir = getContext().getDir("test", Context.MODE_PRIVATE);
-        mRoot = getContext().getFilesDir();
+        mTestDir = Files.createTempDirectory("StoragedUidIoStatsReaderTest").toFile();
         mTestFile = new File(mTestDir, "test.file");
         mStoragedUidIoStatsReader = new StoragedUidIoStatsReader(mTestFile.getAbsolutePath());
     }
@@ -73,10 +65,8 @@
     @After
     public void tearDown() throws Exception {
         FileUtils.deleteContents(mTestDir);
-        FileUtils.deleteContents(mRoot);
     }
 
-
     /**
      * Tests that reading will never call the callback.
      */
diff --git a/core/tests/coretests/src/com/android/internal/policy/PhoneWindowTest.java b/core/tests/coretests/src/com/android/internal/policy/PhoneWindowTest.java
index 916e2b5..6bdc06a 100644
--- a/core/tests/coretests/src/com/android/internal/policy/PhoneWindowTest.java
+++ b/core/tests/coretests/src/com/android/internal/policy/PhoneWindowTest.java
@@ -63,8 +63,13 @@
         createPhoneWindowWithTheme(R.style.LayoutInDisplayCutoutModeUnset);
         installDecor();
 
-        assertThat(mPhoneWindow.getAttributes().layoutInDisplayCutoutMode,
-                is(LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT));
+        if (mPhoneWindow.mDefaultEdgeToEdge && !mPhoneWindow.isFloating()) {
+            assertThat(mPhoneWindow.getAttributes().layoutInDisplayCutoutMode,
+                    is(LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS));
+        } else {
+            assertThat(mPhoneWindow.getAttributes().layoutInDisplayCutoutMode,
+                    is(LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT));
+        }
     }
 
     @Test
diff --git a/core/tests/coretests/src/com/android/internal/power/EnergyConsumerStatsTest.java b/core/tests/coretests/src/com/android/internal/power/EnergyConsumerStatsTest.java
index e09cfd2..ae2ef0cb 100644
--- a/core/tests/coretests/src/com/android/internal/power/EnergyConsumerStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/power/EnergyConsumerStatsTest.java
@@ -34,10 +34,13 @@
 import static org.junit.Assert.assertTrue;
 
 import android.os.Parcel;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.view.Display;
 
 import androidx.test.filters.SmallTest;
 
+import org.junit.Rule;
 import org.junit.Test;
 
 import java.util.Arrays;
@@ -46,7 +49,10 @@
  * Test class for {@link EnergyConsumerStats}.
  */
 @SmallTest
+@IgnoreUnderRavenwood(reason = "Needs kernel support")
 public class EnergyConsumerStatsTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
 
     @Test
     public void testConstruction() {
diff --git a/core/tests/coretests/src/com/android/internal/util/BitUtilsTest.java b/core/tests/coretests/src/com/android/internal/util/BitUtilsTest.java
index fdba811..fdde36a 100644
--- a/core/tests/coretests/src/com/android/internal/util/BitUtilsTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/BitUtilsTest.java
@@ -30,8 +30,8 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
-import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/com/android/internal/util/ContrastColorUtilTest.java b/core/tests/coretests/src/com/android/internal/util/ContrastColorUtilTest.java
index 5f5bf11..e6ebfef 100644
--- a/core/tests/coretests/src/com/android/internal/util/ContrastColorUtilTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/ContrastColorUtilTest.java
@@ -23,6 +23,8 @@
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.graphics.Color;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.text.Spannable;
 import android.text.SpannableString;
 import android.text.SpannableStringBuilder;
@@ -32,23 +34,21 @@
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.R;
 
-import junit.framework.TestCase;
-
-import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
-public class ContrastColorUtilTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = Color.class)
+public class ContrastColorUtilTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
 
-    private Context mContext;
-
-    @Before
-    public void setUp() {
-        mContext = InstrumentationRegistry.getContext();
-    }
-
+    @Test
     @SmallTest
     public void testEnsureTextContrastAgainstDark() {
         int darkBg = 0xFF35302A;
@@ -70,6 +70,7 @@
         assertContrastIsWithinRange(selfContrastColor, darkBg, 4.5, 4.75);
     }
 
+    @Test
     @SmallTest
     public void testEnsureTextContrastAgainstLight() {
         int lightBg = 0xFFFFF8F2;
@@ -91,13 +92,16 @@
         assertContrastIsWithinRange(selfContrastColor, lightBg, 4.5, 4.75);
     }
 
+    @Test
     public void testBuilder_ensureColorSpanContrast_removesAllFullLengthColorSpans() {
+        Context context = InstrumentationRegistry.getContext();
+
         Spannable text = new SpannableString("blue text with yellow and green");
         text.setSpan(new ForegroundColorSpan(Color.YELLOW), 15, 21,
                 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         text.setSpan(new ForegroundColorSpan(Color.BLUE), 0, text.length(),
                 Spanned.SPAN_INCLUSIVE_INCLUSIVE);
-        TextAppearanceSpan taSpan = new TextAppearanceSpan(mContext,
+        TextAppearanceSpan taSpan = new TextAppearanceSpan(context,
                 R.style.TextAppearance_DeviceDefault_Notification_Title);
         assertThat(taSpan.getTextColor()).isNotNull();  // it must be set to prove it is cleared.
         text.setSpan(taSpan, 0, text.length(),
@@ -123,6 +127,7 @@
         assertThat(((ForegroundColorSpan) spans[2]).getForegroundColor()).isEqualTo(Color.GREEN);
     }
 
+    @Test
     public void testBuilder_ensureColorSpanContrast_partialLength_adjusted() {
         int background = 0xFFFF0101;  // Slightly lighter red
         CharSequence text = new SpannableStringBuilder()
@@ -138,14 +143,17 @@
         assertContrastIsWithinRange(foregroundColor, background, 3, 3.2);
     }
 
+    @Test
     public void testBuilder_ensureColorSpanContrast_worksWithComplexInput() {
+        Context context = InstrumentationRegistry.getContext();
+
         Spannable text = new SpannableString("blue text with yellow and green and cyan");
         text.setSpan(new ForegroundColorSpan(Color.YELLOW), 15, 21,
                 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         text.setSpan(new ForegroundColorSpan(Color.BLUE), 0, text.length(),
                 Spanned.SPAN_INCLUSIVE_INCLUSIVE);
         // cyan TextAppearanceSpan
-        TextAppearanceSpan taSpan = new TextAppearanceSpan(mContext,
+        TextAppearanceSpan taSpan = new TextAppearanceSpan(context,
                 R.style.TextAppearance_DeviceDefault_Notification_Title);
         taSpan = new TextAppearanceSpan(taSpan.getFamily(), taSpan.getTextStyle(),
                 taSpan.getTextSize(), ColorStateList.valueOf(Color.CYAN), null);
diff --git a/core/tests/coretests/src/com/android/internal/util/DumpUtilsTest.java b/core/tests/coretests/src/com/android/internal/util/DumpUtilsTest.java
index 36c2a62..d2d3c13 100644
--- a/core/tests/coretests/src/com/android/internal/util/DumpUtilsTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/DumpUtilsTest.java
@@ -25,10 +25,16 @@
 
 import static com.google.common.truth.Truth.assertWithMessage;
 
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
 import android.content.ComponentName;
 import android.util.SparseArray;
 
-import junit.framework.TestCase;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
@@ -37,7 +43,8 @@
  * Run with:
  atest FrameworksCoreTests:DumpUtilsTest
  */
-public class DumpUtilsTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+public class DumpUtilsTest {
 
     private final StringWriter mStringWriter = new StringWriter();
     private final PrintWriter mPrintWriter = new PrintWriter(mStringWriter);
@@ -56,6 +63,7 @@
         return () -> cn(componentName);
     }
 
+    @Test
     public void testIsPlatformPackage() {
         assertTrue(isPlatformPackage("android"));
         assertTrue(isPlatformPackage("android.abc"));
@@ -79,6 +87,7 @@
         assertFalse(isPlatformPackage(wcn("com.google.def/abc")));
     }
 
+    @Test
     public void testIsNonPlatformPackage() {
         assertFalse(isNonPlatformPackage("android"));
         assertFalse(isNonPlatformPackage("android.abc"));
@@ -102,6 +111,7 @@
         assertTrue(isNonPlatformPackage(wcn("com.google.def/abc")));
     }
 
+    @Test
     public void testIsPlatformCriticalPackage() {
         for (final ComponentName componentName : CRITICAL_SECTION_COMPONENTS) {
             assertTrue(isPlatformCriticalPackage(() -> componentName));
@@ -115,6 +125,7 @@
         assertFalse(isPlatformCriticalPackage(null));
     }
 
+    @Test
     public void testIsPlatformNonCriticalPackage() {
         for (final ComponentName componentName : CRITICAL_SECTION_COMPONENTS) {
             assertFalse(isPlatformNonCriticalPackage(() -> componentName));
@@ -128,6 +139,7 @@
         assertFalse(isPlatformNonCriticalPackage(null));
     }
 
+    @Test
     public void testFilterRecord() {
         assertFalse(filterRecord(null).test(wcn("com.google.p/abc")));
         assertFalse(filterRecord(null).test(wcn("com.android.p/abc")));
@@ -178,6 +190,7 @@
                         wcn("com.google/.abc")));
     }
 
+    @Test
     public void testDumpSparseArray_empty() {
         SparseArray<String> array = new SparseArray<>();
 
@@ -188,6 +201,7 @@
         assertWithMessage("empty array dump").that(output).isEqualTo("...No whatevers\n");
     }
 
+    @Test
     public void testDumpSparseArray_oneElement() {
         SparseArray<String> array = new SparseArray<>();
         array.put(1, "uno");
@@ -201,6 +215,7 @@
                 + "..0: 1->uno\n");
     }
 
+    @Test
     public void testDumpSparseArray_oneNullElement() {
         SparseArray<String> array = new SparseArray<>();
         array.put(1, null);
@@ -214,6 +229,7 @@
                 + "..0: 1->(null)\n");
     }
 
+    @Test
     public void testDumpSparseArray_multipleElements() {
         SparseArray<String> array = new SparseArray<>();
         array.put(1, "uno");
@@ -231,6 +247,7 @@
                 + "..2: 42->(null)\n");
     }
 
+    @Test
     public void testDumpSparseArray_keyDumperOnly() {
         SparseArray<String> array = new SparseArray<>();
         array.put(1, "uno");
@@ -251,6 +268,7 @@
                 + "_2=42_(null)\n");
     }
 
+    @Test
     public void testDumpSparseArray_valueDumperOnly() {
         SparseArray<String> array = new SparseArray<>();
         array.put(1, "uno");
@@ -272,6 +290,7 @@
                 + "..2: 42->(null)\n");
     }
 
+    @Test
     public void testDumpSparseArray_keyAndValueDumpers() {
         SparseArray<String> array = new SparseArray<>();
         array.put(1, "uno");
@@ -295,6 +314,7 @@
                 + "_2=42_(null)\n");
     }
 
+    @Test
     public void testDumpSparseArrayValues() {
         SparseArray<String> array = new SparseArray<>();
         array.put(1, "uno");
@@ -306,7 +326,7 @@
         String output = flushPrintWriter();
 
         assertWithMessage("dump of %s", array).that(output).isEqualTo(""
-                + ".3 numbers:\n"
+                + ".3 number(s):\n"
                 + "..uno\n"
                 + "..duo\n"
                 + "..(null)\n");
diff --git a/core/tests/coretests/src/com/android/internal/util/DumpableContainerImplTest.java b/core/tests/coretests/src/com/android/internal/util/DumpableContainerImplTest.java
index 589e4f9..61d4e3d 100644
--- a/core/tests/coretests/src/com/android/internal/util/DumpableContainerImplTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/DumpableContainerImplTest.java
@@ -17,30 +17,32 @@
 
 import static com.google.common.truth.Truth.assertWithMessage;
 
-import static org.testng.Assert.assertThrows;
-
 import android.util.Dumpable;
 
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.util.dump.DumpableContainerImpl;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.concurrent.atomic.AtomicReference;
 
-public final class DumpableContainerImplTest {
+@RunWith(AndroidJUnit4.class)
+public class DumpableContainerImplTest {
 
     private final DumpableContainerImpl mImpl = new DumpableContainerImpl();
     private final StringWriter mSw = new StringWriter();
     private final PrintWriter mWriter = new PrintWriter(mSw);
 
-    @Test
+    @Test(expected = NullPointerException.class)
     public void testAddDumpable_null() {
-        assertThrows(NullPointerException.class, () -> mImpl.addDumpable(null));
+        mImpl.addDumpable(null);
     }
 
-    @Test
+    @Test(expected = NullPointerException.class)
     public void testAddDumpable_dumpableWithoutName() {
         Dumpable namelessDumpable = new Dumpable() {
 
@@ -55,7 +57,7 @@
             }
 
         };
-        assertThrows(NullPointerException.class, () -> mImpl.addDumpable(namelessDumpable));
+        mImpl.addDumpable(namelessDumpable);
     }
 
     @Test
@@ -179,9 +181,9 @@
                         + "......6 Args: 4,8,15,16,23,42,\n");
     }
 
-    @Test
+    @Test(expected = NullPointerException.class)
     public void testRemoveDumpable_null() {
-        assertThrows(NullPointerException.class, () -> mImpl.removeDumpable(null));
+        mImpl.removeDumpable(null);
     }
 
     @Test
diff --git a/core/tests/coretests/src/com/android/internal/util/FakeLatencyTrackerTest.java b/core/tests/coretests/src/com/android/internal/util/FakeLatencyTrackerTest.java
index 3946cdf..6bd67ea 100644
--- a/core/tests/coretests/src/com/android/internal/util/FakeLatencyTrackerTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/FakeLatencyTrackerTest.java
@@ -24,12 +24,15 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.provider.DeviceConfig;
 
-import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -42,7 +45,10 @@
  * {@link LatencyTrackerTest}
  */
 @RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = DeviceConfig.class)
 public class FakeLatencyTrackerTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
 
     private FakeLatencyTracker mFakeLatencyTracker;
     private int mInitialSyncDisabledMode;
diff --git a/core/tests/coretests/src/com/android/internal/util/FastDataTest.java b/core/tests/coretests/src/com/android/internal/util/FastDataTest.java
index de325ab..316b95ac 100644
--- a/core/tests/coretests/src/com/android/internal/util/FastDataTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/FastDataTest.java
@@ -21,6 +21,7 @@
 import static org.junit.Assert.fail;
 
 import android.annotation.NonNull;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.util.ExceptionUtils;
 
 import com.android.modules.utils.FastDataInput;
@@ -29,6 +30,7 @@
 import libcore.util.HexEncoding;
 
 import org.junit.Assume;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -51,6 +53,9 @@
 
 @RunWith(Parameterized.class)
 public class FastDataTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     private final boolean use4ByteSequence;
 
     private static final String TEST_SHORT_STRING = "a";
@@ -59,7 +64,12 @@
 
     @Parameters(name = "use4ByteSequence={0}")
     public static Collection<Object[]> data() {
-        return Arrays.asList(new Object[][] { {true}, {false} });
+        if (RavenwoodRule.isUnderRavenwood()) {
+            // TODO: 4-byte sequences are only supported on ART
+            return Arrays.asList(new Object[][]{{false}});
+        } else {
+            return Arrays.asList(new Object[][]{{true}, {false}});
+        }
     }
 
     public FastDataTest(boolean use4ByteSequence) {
diff --git a/core/tests/coretests/src/com/android/internal/util/FastMathTest.java b/core/tests/coretests/src/com/android/internal/util/FastMathTest.java
new file mode 100644
index 0000000..dd26334
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/util/FastMathTest.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+import static org.junit.Assert.assertEquals;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class FastMathTest {
+    @Test
+    public void testRound() {
+        assertEquals(-1, FastMath.round(-1.0f));
+        assertEquals(0, FastMath.round(0.0f));
+        assertEquals(1, FastMath.round(1.0f));
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/util/GrowingArrayUtilsTest.java b/core/tests/coretests/src/com/android/internal/util/GrowingArrayUtilsTest.java
new file mode 100644
index 0000000..8456161
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/util/GrowingArrayUtilsTest.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+import static com.android.internal.util.GrowingArrayUtils.append;
+import static com.android.internal.util.GrowingArrayUtils.insert;
+
+import static org.junit.Assert.assertArrayEquals;
+
+import android.util.EmptyArray;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+
+@RunWith(AndroidJUnit4.class)
+public class GrowingArrayUtilsTest {
+    private final Object TEST_OBJECT = new Object();
+
+    @Test
+    public void testAppend_Object() {
+        assertArrayEqualsPrefix(new Object[]{TEST_OBJECT},
+                append(EmptyArray.OBJECT, 0, TEST_OBJECT));
+        assertArrayEqualsPrefix(new Object[]{TEST_OBJECT, TEST_OBJECT},
+                append(new Object[]{TEST_OBJECT}, 1, TEST_OBJECT));
+        assertArrayEqualsPrefix(new Object[]{TEST_OBJECT},
+                append(new Object[]{null, null}, 0, TEST_OBJECT));
+    }
+
+    @Test
+    public void testInsert_Object() {
+        assertArrayEqualsPrefix(new Object[]{TEST_OBJECT},
+                insert(EmptyArray.OBJECT, 0, 0, TEST_OBJECT));
+        assertArrayEqualsPrefix(new Object[]{null, TEST_OBJECT},
+                insert(new Object[]{TEST_OBJECT}, 1, 0, null));
+        assertArrayEqualsPrefix(new Object[]{TEST_OBJECT, null},
+                insert(new Object[]{TEST_OBJECT}, 1, 1, null));
+        assertArrayEqualsPrefix(new Object[]{TEST_OBJECT, null, TEST_OBJECT},
+                insert(new Object[]{TEST_OBJECT, TEST_OBJECT}, 2, 1, null));
+    }
+
+    @Test
+    public void testAppend_Int() {
+        assertArrayEqualsPrefix(new int[]{42},
+                append(EmptyArray.INT, 0, 42));
+        assertArrayEqualsPrefix(new int[]{42, 42},
+                append(new int[]{42}, 1, 42));
+        assertArrayEqualsPrefix(new int[]{42},
+                append(new int[]{0, 0}, 0, 42));
+    }
+
+    @Test
+    public void testInsert_Int() {
+        assertArrayEqualsPrefix(new int[]{42},
+                insert(EmptyArray.INT, 0, 0, 42));
+        assertArrayEqualsPrefix(new int[]{21, 42},
+                insert(new int[]{42}, 1, 0, 21));
+        assertArrayEqualsPrefix(new int[]{42, 21},
+                insert(new int[]{42}, 1, 1, 21));
+        assertArrayEqualsPrefix(new int[]{42, 21, 43},
+                insert(new int[]{42, 43}, 2, 1, 21));
+    }
+
+    @Test
+    public void testAppend_Long() {
+        assertArrayEqualsPrefix(new long[]{42},
+                append(EmptyArray.LONG, 0, 42));
+        assertArrayEqualsPrefix(new long[]{42, 42},
+                append(new long[]{42}, 1, 42));
+        assertArrayEqualsPrefix(new long[]{42},
+                append(new long[]{0, 0}, 0, 42));
+    }
+
+    @Test
+    public void testInsert_Long() {
+        assertArrayEqualsPrefix(new long[]{42},
+                insert(EmptyArray.LONG, 0, 0, 42));
+        assertArrayEqualsPrefix(new long[]{21, 42},
+                insert(new long[]{42}, 1, 0, 21));
+        assertArrayEqualsPrefix(new long[]{42, 21},
+                insert(new long[]{42}, 1, 1, 21));
+        assertArrayEqualsPrefix(new long[]{42, 21, 43},
+                insert(new long[]{42, 43}, 2, 1, 21));
+    }
+
+    @Test
+    public void testAppend_Boolean() {
+        assertArrayEqualsPrefix(new boolean[]{true},
+                append(EmptyArray.BOOLEAN, 0, true));
+        assertArrayEqualsPrefix(new boolean[]{true, true},
+                append(new boolean[]{true}, 1, true));
+        assertArrayEqualsPrefix(new boolean[]{true},
+                append(new boolean[]{false, false}, 0, true));
+    }
+
+    @Test
+    public void testInsert_Boolean() {
+        assertArrayEqualsPrefix(new boolean[]{true},
+                insert(EmptyArray.BOOLEAN, 0, 0, true));
+        assertArrayEqualsPrefix(new boolean[]{false, true},
+                insert(new boolean[]{true}, 1, 0, false));
+        assertArrayEqualsPrefix(new boolean[]{true, false},
+                insert(new boolean[]{true}, 1, 1, false));
+        assertArrayEqualsPrefix(new boolean[]{true, false, true},
+                insert(new boolean[]{true, true}, 2, 1, false));
+    }
+
+    private <T> void assertArrayEqualsPrefix(T[] expected, T[] actual) {
+        assertArrayEquals(expected, Arrays.copyOf(actual, expected.length));
+    }
+
+    private void assertArrayEqualsPrefix(int[] expected, int[] actual) {
+        assertArrayEquals(expected, Arrays.copyOf(actual, expected.length));
+    }
+
+    private void assertArrayEqualsPrefix(long[] expected, long[] actual) {
+        assertArrayEquals(expected, Arrays.copyOf(actual, expected.length));
+    }
+
+    private void assertArrayEqualsPrefix(boolean[] expected, boolean[] actual) {
+        assertArrayEquals(expected, Arrays.copyOf(actual, expected.length));
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/util/HexDumpTest.java b/core/tests/coretests/src/com/android/internal/util/HexDumpTest.java
index f1cd89b..dcffa1c 100644
--- a/core/tests/coretests/src/com/android/internal/util/HexDumpTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/HexDumpTest.java
@@ -19,14 +19,22 @@
 import static com.android.internal.util.HexDump.hexStringToByteArray;
 import static com.android.internal.util.HexDump.toHexString;
 
-import junit.framework.TestCase;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.Arrays;
 import java.util.Random;
 
-public final class HexDumpTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+public final class HexDumpTest {
+    @Test
     public void testBytesToHexString() {
         assertEquals("abcdef", HexDump.toHexString(
                 new byte[] { (byte) 0xab, (byte) 0xcd, (byte) 0xef }, false));
@@ -34,12 +42,14 @@
                 new byte[] { (byte) 0xab, (byte) 0xcd, (byte) 0xef }, true));
     }
 
+    @Test
     public void testNullByteArray() {
         assertThrows(
                 NullPointerException.class,
                 () -> HexDump.toHexString(null));
     }
 
+    @Test
     public void testBytesToHexString_allByteValues() {
         byte[] bytes = new byte[256];
         for (int i = 0; i < bytes.length; i++) {
@@ -57,6 +67,7 @@
         assertEquals(expected, HexDump.toHexString(bytes));
     }
 
+    @Test
     public void testRoundTrip_fromBytes() {
         Random deterministicRandom = new Random(31337); // arbitrary but deterministic
         for (int length = 0; length < 100; length++) {
@@ -68,6 +79,7 @@
         }
     }
 
+    @Test
     public void testRoundTrip_fromString() {
         String hexString = "0123456789ABCDEF72f9a3438934c378d34f32a8b932";
         for (int length = 0; length < hexString.length(); length += 2) {
@@ -77,6 +89,7 @@
         }
     }
 
+    @Test
     public void testToHexString_offsetLength() {
         byte[] bytes = new byte[32];
         for (int i = 0; i < 16; i++) {
@@ -97,6 +110,7 @@
         }
     }
 
+    @Test
     public void testToHexString_case() {
         byte[] bytes = new byte[32];
         for (int i = 0; i < 16; i++) {
@@ -113,16 +127,19 @@
         assertEquals(expected.toUpperCase(), toHexString(bytes));
     }
 
+    @Test
     public void testHexStringToByteArray_empty() {
         assertBytesEqual(new byte[0], HexDump.hexStringToByteArray(""));
     }
 
+    @Test
     public void testHexStringToByteArray_null() {
         assertThrows(
                 NullPointerException.class,
                 () -> HexDump.hexStringToByteArray((String) null));
     }
 
+    @Test
     public void testHexStringToByteArray_invalidCharacters() {
         // IllegalArgumentException would probably have been better than RuntimeException, but it
         // might be too late to change now.
@@ -137,6 +154,7 @@
                 () -> HexDump.hexStringToByteArray("abcdefgh"));
     }
 
+    @Test
     public void testHexStringToByteArray_oddLength() {
         // IllegalArgumentException would probably have been better than
         // StringIndexOutOfBoundsException, but it might be too late to change now.
diff --git a/core/tests/coretests/src/com/android/internal/util/LatencyTrackerTest.java b/core/tests/coretests/src/com/android/internal/util/LatencyTrackerTest.java
index f24894e..010f724 100644
--- a/core/tests/coretests/src/com/android/internal/util/LatencyTrackerTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/LatencyTrackerTest.java
@@ -25,9 +25,11 @@
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.provider.DeviceConfig;
 
-import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.util.LatencyTracker.ActionProperties;
 
@@ -49,7 +51,11 @@
 import java.util.stream.Collectors;
 
 @RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = DeviceConfig.class)
 public class LatencyTrackerTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     private static final String ENUM_NAME_PREFIX = "UIACTION_LATENCY_REPORTED__ACTION__";
 
     @Rule
diff --git a/core/tests/coretests/src/com/android/internal/util/LineBreakBufferedWriterTest.java b/core/tests/coretests/src/com/android/internal/util/LineBreakBufferedWriterTest.java
index b2a2265..e6418fa 100644
--- a/core/tests/coretests/src/com/android/internal/util/LineBreakBufferedWriterTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/LineBreakBufferedWriterTest.java
@@ -16,7 +16,13 @@
 
 package com.android.internal.util;
 
-import junit.framework.TestCase;
+import static org.junit.Assert.assertEquals;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.io.ByteArrayOutputStream;
 import java.io.Writer;
@@ -26,18 +32,18 @@
 /**
  * Tests for {@link IndentingPrintWriter}.
  */
-public class LineBreakBufferedWriterTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+public class LineBreakBufferedWriterTest {
 
     private ByteArrayOutputStream mStream;
     private RecordingWriter mWriter;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
+    @Before
+    public void setUp() throws Exception {
         mWriter = new RecordingWriter();
     }
 
+    @Test
     public void testLessThanBufferSize() {
         final LineBreakBufferedWriter lw = new LineBreakBufferedWriter(mWriter, 1000);
 
@@ -49,6 +55,7 @@
         assertOutput("Hello\nWorld\nTest\n");
     }
 
+    @Test
     public void testMoreThanBufferSizeNoLineBreaks() {
         final LineBreakBufferedWriter lw = new LineBreakBufferedWriter(mWriter, 20);
 
@@ -71,6 +78,7 @@
         }
     }
 
+    @Test
     public void testMoreThanBufferSizeNoLineBreaksSingleString() {
         final LineBreakBufferedWriter lw = new LineBreakBufferedWriter(mWriter, 20);
 
@@ -92,6 +100,7 @@
         }
     }
 
+    @Test
     public void testMoreThanBufferSizeLineBreakBefore() {
         final LineBreakBufferedWriter lw = new LineBreakBufferedWriter(mWriter, 20);
 
@@ -104,6 +113,7 @@
         assertOutput("aaaaaaaaaa", "bbbbcccccccccc");
     }
 
+    @Test
     public void testMoreThanBufferSizeLineBreakBeforeSingleString() {
         final LineBreakBufferedWriter lw = new LineBreakBufferedWriter(mWriter, 20);
 
@@ -115,6 +125,7 @@
         assertOutput("aaaaaaaaaa", "bbbbcccccccccc");
     }
 
+    @Test
     public void testMoreThanBufferSizeLineBreakNew() {
         final LineBreakBufferedWriter lw = new LineBreakBufferedWriter(mWriter, 20);
 
@@ -127,6 +138,7 @@
         assertOutput("aaaaaaaaaabbbbbc\nd", "ddddddddd");
     }
 
+    @Test
     public void testMoreThanBufferSizeLineBreakBeforeAndNew() {
         final LineBreakBufferedWriter lw = new LineBreakBufferedWriter(mWriter, 20);
 
@@ -139,6 +151,7 @@
         assertOutput("aaaaaaaaaa\nbbbbbc\nd", "ddddddddd");
     }
 
+    @Test
     public void testMoreThanBufferSizeInt() {
         final LineBreakBufferedWriter lw = new LineBreakBufferedWriter(mWriter, 15);
 
@@ -151,6 +164,7 @@
         assertOutput("123456789098765", "4321");
     }
 
+    @Test
     public void testMoreThanBufferSizeChar() {
         final LineBreakBufferedWriter lw = new LineBreakBufferedWriter(mWriter, 15);
 
@@ -165,6 +179,7 @@
         assertOutput("$$$$$$$$$$%%%%%", "%%%%%");
     }
 
+    @Test
     public void testMoreThanBufferSizeLineBreakNewChars() {
         final LineBreakBufferedWriter lw = new LineBreakBufferedWriter(mWriter, 20);
 
@@ -177,6 +192,7 @@
         assertOutput("aaaaaaaaaabbbbbc\nd", "ddddddddd");
     }
 
+    @Test
     public void testMoreThenInitialCapacitySimpleWrites() {
         // This check is different from testMoreThanBufferSizeChar. The initial capacity is lower
         // than the maximum buffer size here.
diff --git a/core/tests/coretests/src/com/android/internal/util/ParseUtilsTest.java b/core/tests/coretests/src/com/android/internal/util/ParseUtilsTest.java
index 867152e..d24cbfe 100644
--- a/core/tests/coretests/src/com/android/internal/util/ParseUtilsTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/ParseUtilsTest.java
@@ -16,13 +16,23 @@
 
 package com.android.internal.util;
 
-import junit.framework.TestCase;
+import static org.junit.Assert.assertEquals;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 /**
  * Run with:
  atest /android/pi-dev/frameworks/base/core/tests/coretests/src/com/android/internal/util/ParseUtilsTest.java
  */
-public class ParseUtilsTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+public class ParseUtilsTest {
+    private static final float DELTA_FLOAT = 0.0f;
+    private static final double DELTA_DOUBLE = 0.0d;
+
+    @Test
     public void testParseInt() {
         assertEquals(1, ParseUtils.parseInt(null, 1));
         assertEquals(1, ParseUtils.parseInt("", 1));
@@ -33,6 +43,7 @@
         assertEquals(-2, ParseUtils.parseInt("-2", 1));
     }
 
+    @Test
     public void testParseIntWithBase() {
         assertEquals(1, ParseUtils.parseIntWithBase(null, 10, 1));
         assertEquals(1, ParseUtils.parseIntWithBase("", 10, 1));
@@ -45,6 +56,7 @@
         assertEquals(-3, ParseUtils.parseIntWithBase("-10", 3, 1));
     }
 
+    @Test
     public void testParseLong() {
         assertEquals(1L, ParseUtils.parseLong(null, 1));
         assertEquals(1L, ParseUtils.parseLong("", 1));
@@ -52,6 +64,7 @@
         assertEquals(2L, ParseUtils.parseLong("2", 1));
     }
 
+    @Test
     public void testParseLongWithBase() {
         assertEquals(1L, ParseUtils.parseLongWithBase(null, 10, 1));
         assertEquals(1L, ParseUtils.parseLongWithBase("", 10, 1));
@@ -69,20 +82,23 @@
         assertEquals(10_000_000_000L, ParseUtils.parseLongWithBase(null, 10, 10_000_000_000L));
     }
 
+    @Test
     public void testParseFloat() {
-        assertEquals(0.5f, ParseUtils.parseFloat(null, 0.5f));
-        assertEquals(0.5f, ParseUtils.parseFloat("", 0.5f));
-        assertEquals(0.5f, ParseUtils.parseFloat("1x", 0.5f));
-        assertEquals(1.5f, ParseUtils.parseFloat("1.5", 0.5f));
+        assertEquals(0.5f, ParseUtils.parseFloat(null, 0.5f), DELTA_FLOAT);
+        assertEquals(0.5f, ParseUtils.parseFloat("", 0.5f), DELTA_FLOAT);
+        assertEquals(0.5f, ParseUtils.parseFloat("1x", 0.5f), DELTA_FLOAT);
+        assertEquals(1.5f, ParseUtils.parseFloat("1.5", 0.5f), DELTA_FLOAT);
     }
 
+    @Test
     public void testParseDouble() {
-        assertEquals(0.5, ParseUtils.parseDouble(null, 0.5));
-        assertEquals(0.5, ParseUtils.parseDouble("", 0.5));
-        assertEquals(0.5, ParseUtils.parseDouble("1x", 0.5));
-        assertEquals(1.5, ParseUtils.parseDouble("1.5", 0.5));
+        assertEquals(0.5, ParseUtils.parseDouble(null, 0.5), DELTA_DOUBLE);
+        assertEquals(0.5, ParseUtils.parseDouble("", 0.5), DELTA_DOUBLE);
+        assertEquals(0.5, ParseUtils.parseDouble("1x", 0.5), DELTA_DOUBLE);
+        assertEquals(1.5, ParseUtils.parseDouble("1.5", 0.5), DELTA_DOUBLE);
     }
 
+    @Test
     public void testParseBoolean() {
         assertEquals(false, ParseUtils.parseBoolean(null, false));
         assertEquals(true, ParseUtils.parseBoolean(null, true));
diff --git a/core/tests/coretests/src/com/android/internal/util/ProgressReporterTest.java b/core/tests/coretests/src/com/android/internal/util/ProgressReporterTest.java
index 87f2a8a..0d21335 100644
--- a/core/tests/coretests/src/com/android/internal/util/ProgressReporterTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/ProgressReporterTest.java
@@ -16,14 +16,28 @@
 
 package com.android.internal.util;
 
-import junit.framework.TestCase;
+import static org.junit.Assert.assertEquals;
 
-public class ProgressReporterTest extends TestCase {
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = ProgressReporter.class)
+public class ProgressReporterTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     private ProgressReporter r;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @Before
+    public void setUp() throws Exception {
         r = new ProgressReporter(0);
     }
 
@@ -37,6 +51,7 @@
         assertEquals("len", len, range[1]);
     }
 
+    @Test
     public void testBasic() throws Exception {
         assertProgress(0);
 
@@ -50,6 +65,7 @@
         assertProgress(100);
     }
 
+    @Test
     public void testSegment() throws Exception {
         r.setProgress(20);
         assertProgress(20);
@@ -68,6 +84,7 @@
         assertProgress(80);
     }
 
+    @Test
     public void testSegmentOvershoot() throws Exception {
         r.setProgress(20);
         assertProgress(20);
@@ -87,6 +104,7 @@
         assertProgress(60);
     }
 
+    @Test
     public void testSegmentNested() throws Exception {
         r.setProgress(20);
         assertProgress(20);
diff --git a/core/tests/coretests/src/com/android/internal/util/RingBufferTest.java b/core/tests/coretests/src/com/android/internal/util/RingBufferTest.java
index 4497770..d7a100a 100644
--- a/core/tests/coretests/src/com/android/internal/util/RingBufferTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/RingBufferTest.java
@@ -20,8 +20,8 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.fail;
 
-import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/com/android/internal/util/TokenBucketTest.java b/core/tests/coretests/src/com/android/internal/util/TokenBucketTest.java
index 8b30828..ef579fe 100644
--- a/core/tests/coretests/src/com/android/internal/util/TokenBucketTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/TokenBucketTest.java
@@ -16,22 +16,29 @@
 
 package com.android.internal.util;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
 
 import android.os.SystemClock;
 import android.text.format.DateUtils;
 
-import junit.framework.TestCase;
+import androidx.test.runner.AndroidJUnit4;
 
-public class TokenBucketTest extends TestCase {
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class TokenBucketTest {
 
     static final int FILL_DELTA_VERY_SHORT  = 1;
     static final int FILL_DELTA_VERY_LONG   = Integer.MAX_VALUE;
 
+    @Test
     public void testArgumentValidation() {
         assertThrow(() -> new TokenBucket(0, 1, 1));
         assertThrow(() -> new TokenBucket(1, 0, 1));
-        assertThrow(() -> new TokenBucket(1, 1, 0));
         assertThrow(() -> new TokenBucket(0, 1));
         assertThrow(() -> new TokenBucket(1, 0));
         assertThrow(() -> new TokenBucket(-1, 1, 1));
@@ -46,6 +53,7 @@
         new TokenBucket(5000, 1);
     }
 
+    @Test
     public void testInitialCapacity() {
         drain(new TokenBucket(FILL_DELTA_VERY_LONG, 1), 1);
         drain(new TokenBucket(FILL_DELTA_VERY_LONG, 10), 10);
@@ -62,6 +70,7 @@
         drain(new TokenBucket((int) DateUtils.DAY_IN_MILLIS, 200), 200);
     }
 
+    @Test
     public void testReset() {
         TokenBucket tb = new TokenBucket(FILL_DELTA_VERY_LONG, 100, 10);
         drain(tb, 10);
@@ -77,6 +86,7 @@
         drain(tb, 30);
     }
 
+    @Test
     public void testFill() throws Exception {
         int delta = 50;
         TokenBucket tb = new TokenBucket(delta, 10, 0);
@@ -88,6 +98,7 @@
         assertTrue(tb.has());
     }
 
+    @Test
     public void testRefill() throws Exception {
         TokenBucket tb = new TokenBucket(FILL_DELTA_VERY_SHORT, 10, 10);
 
@@ -107,6 +118,7 @@
         assertEquals(10, tb.get(100));
     }
 
+    @Test
     public void testAverage() throws Exception {
         final int delta = 3;
         final int want = 60;
@@ -124,6 +136,7 @@
         assertDuration(want * delta, SystemClock.elapsedRealtime() - start);
     }
 
+    @Test
     public void testBurst() throws Exception {
         final int delta = 2;
         final int capacity = 20;
diff --git a/core/tests/packagemonitortests/src/com/android/internal/content/PackageMonitorTest.java b/core/tests/packagemonitortests/src/com/android/internal/content/PackageMonitorTest.java
index 8e653f5..9cb9122 100644
--- a/core/tests/packagemonitortests/src/com/android/internal/content/PackageMonitorTest.java
+++ b/core/tests/packagemonitortests/src/com/android/internal/content/PackageMonitorTest.java
@@ -30,6 +30,7 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.SystemClock;
 import android.os.UserHandle;
 
 import androidx.test.runner.AndroidJUnit4;
@@ -38,6 +39,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
+import org.mockito.ArgumentMatchers;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -185,16 +187,44 @@
         Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED);
         intent.putExtra(Intent.EXTRA_USER_HANDLE, FAKE_USER_ID);
         intent.putExtra(Intent.EXTRA_UID, FAKE_PACKAGE_UID);
+        final long elapsedRealtimeMs = SystemClock.elapsedRealtime();
+        intent.putExtra(Intent.EXTRA_TIME, elapsedRealtimeMs);
         intent.setData(Uri.fromParts("package", FAKE_PACKAGE_NAME, null));
         spyPackageMonitor.doHandlePackageEvent(intent);
 
         verify(spyPackageMonitor, times(1)).onBeginPackageChanges();
         verify(spyPackageMonitor, times(1)).onHandleForceStop(eq(intent),
-                eq(new String[]{FAKE_PACKAGE_NAME}), eq(FAKE_PACKAGE_UID), eq(true));
+                eq(new String[]{FAKE_PACKAGE_NAME}), eq(FAKE_PACKAGE_UID), eq(true),
+                eqTimestamp(elapsedRealtimeMs));
         verify(spyPackageMonitor, times(1)).onFinishPackageChanges();
     }
 
     @Test
+    public void testPackageMonitorDoHandlePackageEventPackageUnstopped() throws Exception {
+        PackageMonitor spyPackageMonitor = spy(new TestPackageMonitor());
+
+        Intent intent = new Intent(Intent.ACTION_PACKAGE_UNSTOPPED);
+        intent.putExtra(Intent.EXTRA_USER_HANDLE, FAKE_USER_ID);
+        intent.putExtra(Intent.EXTRA_UID, FAKE_PACKAGE_UID);
+        final long elapsedRealtimeMs = SystemClock.elapsedRealtime();
+        intent.putExtra(Intent.EXTRA_TIME, elapsedRealtimeMs);
+        intent.setData(Uri.fromParts("package", FAKE_PACKAGE_NAME, null));
+        spyPackageMonitor.doHandlePackageEvent(intent);
+
+        verify(spyPackageMonitor, times(1)).onBeginPackageChanges();
+        verify(spyPackageMonitor, times(1)).onPackageUnstopped(
+                eq(FAKE_PACKAGE_NAME), eq(FAKE_PACKAGE_UID), eqTimestamp(elapsedRealtimeMs));
+        verify(spyPackageMonitor, times(1)).onFinishPackageChanges();
+    }
+
+    private static Bundle eqTimestamp(long expectedRealtimeMs) {
+        return ArgumentMatchers.argThat(actualExtras -> {
+            final long actualRealtimeMs = actualExtras.getLong(Intent.EXTRA_TIME);
+            return expectedRealtimeMs == actualRealtimeMs;
+        });
+    }
+
+    @Test
     public void testPackageMonitorDoHandlePackageEventPackageQueryRestarted() throws Exception {
         PackageMonitor spyPackageMonitor = spy(new TestPackageMonitor());
 
diff --git a/core/tests/utiltests/Android.bp b/core/tests/utiltests/Android.bp
index 967047e..2ccee71 100644
--- a/core/tests/utiltests/Android.bp
+++ b/core/tests/utiltests/Android.bp
@@ -54,21 +54,20 @@
 
 android_ravenwood_test {
     name: "FrameworksUtilTestsRavenwood",
+    libs: [
+        "android.test.mock",
+    ],
     static_libs: [
         "androidx.annotation_annotation",
         "androidx.test.rules",
         "mockito_ravenwood",
+        "frameworks-base-testutils",
+        "servicestests-utils",
     ],
     srcs: [
-        "src/android/util/AtomicFileTest.java",
-        "src/android/util/DataUnitTest.java",
-        "src/android/util/EventLogTest.java",
-        "src/android/util/IndentingPrintWriterTest.java",
-        "src/android/util/IntArrayTest.java",
-        "src/android/util/LocalLogTest.java",
-        "src/android/util/LongArrayTest.java",
-        "src/android/util/SlogTest.java",
-        "src/android/util/TimeUtilsTest.java",
+        "src/android/util/IRemoteMemoryIntArray.aidl",
+        "src/android/util/**/*.java",
+        "src/com/android/internal/util/**/*.java",
     ],
     auto_gen_config: true,
 }
diff --git a/core/tests/utiltests/src/android/util/MemoryIntArrayTest.java b/core/tests/utiltests/src/android/util/MemoryIntArrayTest.java
index 1966e122..51013e4 100644
--- a/core/tests/utiltests/src/android/util/MemoryIntArrayTest.java
+++ b/core/tests/utiltests/src/android/util/MemoryIntArrayTest.java
@@ -23,11 +23,14 @@
 import static org.junit.Assert.fail;
 
 import android.os.Parcel;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 
-import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.runner.AndroidJUnit4;
 
 import libcore.io.IoUtils;
 
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -35,13 +38,17 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
 @RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = MemoryIntArray.class)
 public class MemoryIntArrayTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     static {
-        System.loadLibrary("cutils");
-        System.loadLibrary("memoryintarraytest");
+        if (!RavenwoodRule.isUnderRavenwood()) {
+            System.loadLibrary("cutils");
+            System.loadLibrary("memoryintarraytest");
+        }
     }
 
     @Test
diff --git a/core/tests/utiltests/src/android/util/MetadataReaderTest.java b/core/tests/utiltests/src/android/util/MetadataReaderTest.java
index a828edb..14feed8 100644
--- a/core/tests/utiltests/src/android/util/MetadataReaderTest.java
+++ b/core/tests/utiltests/src/android/util/MetadataReaderTest.java
@@ -16,37 +16,47 @@
 
 package android.util;
 
+import static org.junit.Assert.assertEquals;
+
 import android.media.ExifInterface;
 import android.os.Bundle;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.provider.DocumentsContract;
 import android.provider.MetadataReader;
 
-import libcore.io.IoUtils;
+import androidx.test.runner.AndroidJUnit4;
 
-import junit.framework.TestCase;
+import libcore.io.IoUtils;
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 
-public class MetadataReaderTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = MetadataReader.class)
+public class MetadataReaderTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
 
     private InputStream mInputStream;
     private Bundle mData;
 
     @Before
-    protected void setUp() throws Exception {
+    public void setUp() throws Exception {
         mInputStream = getClass().getClassLoader().getResourceAsStream("res/drawable/image.jpg");
         mData = new Bundle();
     }
 
     @After
-    protected void tearDown() throws Exception {
+    public void tearDown() throws Exception {
         IoUtils.closeQuietly(mInputStream);
     }
 
diff --git a/core/tests/utiltests/src/android/util/SystemConfigFileCommitEventLoggerTest.java b/core/tests/utiltests/src/android/util/SystemConfigFileCommitEventLoggerTest.java
index 5f6c201..3bb79ec 100644
--- a/core/tests/utiltests/src/android/util/SystemConfigFileCommitEventLoggerTest.java
+++ b/core/tests/utiltests/src/android/util/SystemConfigFileCommitEventLoggerTest.java
@@ -21,12 +21,22 @@
 import static org.mockito.Mockito.times;
 
 import android.os.SystemClock;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.mockito.Mockito;
 
-
+@RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = SystemConfigFileCommitEventLogger.class)
 public class SystemConfigFileCommitEventLoggerTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     @Test
     public void testSimple() throws Exception {
         var logger = spy(new SystemConfigFileCommitEventLogger("name"));
diff --git a/core/tests/utiltests/src/android/util/TimeUtilsTest.java b/core/tests/utiltests/src/android/util/TimeUtilsTest.java
index e8246c8..ac659e1 100644
--- a/core/tests/utiltests/src/android/util/TimeUtilsTest.java
+++ b/core/tests/utiltests/src/android/util/TimeUtilsTest.java
@@ -18,8 +18,12 @@
 
 import static org.junit.Assert.assertEquals;
 
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
+
 import androidx.test.runner.AndroidJUnit4;
 
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -29,6 +33,9 @@
 
 @RunWith(AndroidJUnit4.class)
 public class TimeUtilsTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     public static final long SECOND_IN_MILLIS = 1000;
     public static final long MINUTE_IN_MILLIS = SECOND_IN_MILLIS * 60;
     public static final long HOUR_IN_MILLIS = MINUTE_IN_MILLIS * 60;
@@ -78,6 +85,7 @@
     }
 
     @Test
+    @IgnoreUnderRavenwood(reason = "Flaky test, b/315872700")
     public void testDumpTime() {
         assertEquals("2023-01-01 00:00:00.000", runWithPrintWriter((pw) -> {
             TimeUtils.dumpTime(pw, 1672556400000L);
@@ -91,6 +99,7 @@
     }
 
     @Test
+    @IgnoreUnderRavenwood(reason = "Flaky test, b/315872700")
     public void testFormatForLogging() {
         assertEquals("unknown", TimeUtils.formatForLogging(0));
         assertEquals("unknown", TimeUtils.formatForLogging(-1));
@@ -99,6 +108,7 @@
     }
 
     @Test
+    @IgnoreUnderRavenwood(reason = "Flaky test, b/315872700")
     public void testLogTimeOfDay() {
         assertEquals("01-01 00:00:00.000", TimeUtils.logTimeOfDay(1672556400000L));
     }
diff --git a/core/tests/utiltests/src/com/android/internal/util/ArrayUtilsTest.java b/core/tests/utiltests/src/com/android/internal/util/ArrayUtilsTest.java
index 72f3af6..fc233fb 100644
--- a/core/tests/utiltests/src/com/android/internal/util/ArrayUtilsTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/ArrayUtilsTest.java
@@ -17,19 +17,28 @@
 package com.android.internal.util;
 
 import static org.junit.Assert.assertArrayEquals;
+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.junit.Assert.fail;
 
 import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 
-import junit.framework.TestCase;
-
 /**
  * Tests for {@link ArrayUtils}
  */
-public class ArrayUtilsTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+public class ArrayUtilsTest {
+    @Test
     public void testContains() throws Exception {
         final Object A = new Object();
         final Object B = new Object();
@@ -46,6 +55,7 @@
         assertFalse(ArrayUtils.contains(new Object[] { null }, A));
     }
 
+    @Test
     public void testIndexOf() throws Exception {
         final Object A = new Object();
         final Object B = new Object();
@@ -66,6 +76,7 @@
         assertEquals(2, ArrayUtils.indexOf(new Object[] { A, null, B }, B));
     }
 
+    @Test
     public void testContainsAll() throws Exception {
         final Object A = new Object();
         final Object B = new Object();
@@ -86,6 +97,7 @@
         assertFalse(ArrayUtils.containsAll(new Object[] { A }, new Object[] { null }));
     }
 
+    @Test
     public void testContainsInt() throws Exception {
         assertTrue(ArrayUtils.contains(new int[] { 1, 2, 3 }, 1));
         assertTrue(ArrayUtils.contains(new int[] { 1, 2, 3 }, 2));
@@ -96,6 +108,7 @@
         assertFalse(ArrayUtils.contains(new int[] { }, 2));
     }
 
+    @Test
     public void testAppendInt() throws Exception {
         assertArrayEquals(new int[] { 1 },
                 ArrayUtils.appendInt(null, 1));
@@ -107,6 +120,7 @@
                 ArrayUtils.appendInt(new int[] { 1, 2 }, 1));
     }
 
+    @Test
     public void testRemoveInt() throws Exception {
         assertNull(ArrayUtils.removeInt(null, 1));
         assertArrayEquals(new int[] { },
@@ -123,6 +137,7 @@
                 ArrayUtils.removeInt(new int[] { 1, 2, 3, 1 }, 1));
     }
 
+    @Test
     public void testContainsLong() throws Exception {
         assertTrue(ArrayUtils.contains(new long[] { 1, 2, 3 }, 1));
         assertTrue(ArrayUtils.contains(new long[] { 1, 2, 3 }, 2));
@@ -133,6 +148,7 @@
         assertFalse(ArrayUtils.contains(new long[] { }, 2));
     }
 
+    @Test
     public void testAppendLong() throws Exception {
         assertArrayEquals(new long[] { 1 },
                 ArrayUtils.appendLong(null, 1));
@@ -144,6 +160,19 @@
                 ArrayUtils.appendLong(new long[] { 1, 2 }, 1));
     }
 
+    @Test
+    public void testAppendBoolean() throws Exception {
+        assertArrayEquals(new boolean[] { true },
+                ArrayUtils.appendBoolean(null, true));
+        assertArrayEquals(new boolean[] { true },
+                ArrayUtils.appendBoolean(new boolean[] { }, true));
+        assertArrayEquals(new boolean[] { true, false },
+                ArrayUtils.appendBoolean(new boolean[] { true }, false));
+        assertArrayEquals(new boolean[] { true, true },
+                ArrayUtils.appendBoolean(new boolean[] { true }, true));
+    }
+
+    @Test
     public void testRemoveLong() throws Exception {
         assertNull(ArrayUtils.removeLong(null, 1));
         assertArrayEquals(new long[] { },
@@ -160,6 +189,7 @@
                 ArrayUtils.removeLong(new long[] { 1, 2, 3, 1 }, 1));
     }
 
+    @Test
     public void testConcat_zeroObjectArrays() {
         // empty varargs array
         assertArrayEquals(new String[] {}, ArrayUtils.concat(String.class));
@@ -167,16 +197,19 @@
         assertArrayEquals(new String[] {}, ArrayUtils.concat(String.class, (String[][]) null));
     }
 
+    @Test
     public void testConcat_oneObjectArray() {
         assertArrayEquals(new String[] { "1", "2" },
                 ArrayUtils.concat(String.class, new String[] { "1", "2" }));
     }
 
+    @Test
     public void testConcat_oneEmptyObjectArray() {
         assertArrayEquals(new String[] {}, ArrayUtils.concat(String.class, (String[]) null));
         assertArrayEquals(new String[] {}, ArrayUtils.concat(String.class, new String[] {}));
     }
 
+    @Test
     public void testConcat_twoObjectArrays() {
         assertArrayEquals(new Long[] { 1L },
                 ArrayUtils.concat(Long.class, new Long[] { 1L }, new Long[] {}));
@@ -188,6 +221,7 @@
                 ArrayUtils.concat(Long.class, new Long[] { 1L, 2L }, new Long[] { 3L, 4L }));
     }
 
+    @Test
     public void testConcat_twoEmptyObjectArrays() {
         assertArrayEquals(new Long[] {}, ArrayUtils.concat(Long.class, null, null));
         assertArrayEquals(new Long[] {}, ArrayUtils.concat(Long.class, new Long[] {}, null));
@@ -196,6 +230,7 @@
                 ArrayUtils.concat(Long.class, new Long[] {}, new Long[] {}));
     }
 
+    @Test
     public void testConcat_threeObjectArrays() {
         String[] array1 = { "1", "2" };
         String[] array2 = { "3", "4" };
@@ -205,6 +240,7 @@
         assertArrayEquals(expectation, ArrayUtils.concat(String.class, array1, array2, array3));
     }
 
+    @Test
     public void testConcat_threeObjectArraysWithNull() {
         String[] array1 = { "1", "2" };
         String[] array2 = null;
@@ -214,6 +250,7 @@
         assertArrayEquals(expectation, ArrayUtils.concat(String.class, array1, array2, array3));
     }
 
+    @Test
     public void testConcat_zeroByteArrays() {
         // empty varargs array
         assertArrayEquals(new byte[] {}, ArrayUtils.concat());
@@ -221,15 +258,18 @@
         assertArrayEquals(new byte[] {}, ArrayUtils.concat((byte[][]) null));
     }
 
+    @Test
     public void testConcat_oneByteArray() {
         assertArrayEquals(new byte[] { 1, 2 }, ArrayUtils.concat(new byte[] { 1, 2 }));
     }
 
+    @Test
     public void testConcat_oneEmptyByteArray() {
         assertArrayEquals(new byte[] {}, ArrayUtils.concat((byte[]) null));
         assertArrayEquals(new byte[] {}, ArrayUtils.concat(new byte[] {}));
     }
 
+    @Test
     public void testConcat_twoByteArrays() {
         assertArrayEquals(new byte[] { 1 }, ArrayUtils.concat(new byte[] { 1 }, new byte[] {}));
         assertArrayEquals(new byte[] { 1 }, ArrayUtils.concat(new byte[] {}, new byte[] { 1 }));
@@ -239,6 +279,7 @@
                 ArrayUtils.concat(new byte[] { 1, 2 }, new byte[] { 3, 4 }));
     }
 
+    @Test
     public void testConcat_twoEmptyByteArrays() {
         assertArrayEquals(new byte[] {}, ArrayUtils.concat((byte[]) null, null));
         assertArrayEquals(new byte[] {}, ArrayUtils.concat(new byte[] {}, null));
@@ -246,6 +287,7 @@
         assertArrayEquals(new byte[] {}, ArrayUtils.concat(new byte[] {}, new byte[] {}));
     }
 
+    @Test
     public void testConcat_threeByteArrays() {
         byte[] array1 = { 1, 2 };
         byte[] array2 = { 3, 4 };
@@ -255,6 +297,7 @@
         assertArrayEquals(expectation, ArrayUtils.concat(array1, array2, array3));
     }
 
+    @Test
     public void testConcat_threeByteArraysWithNull() {
         byte[] array1 = { 1, 2 };
         byte[] array2 = null;
@@ -264,6 +307,7 @@
         assertArrayEquals(expectation, ArrayUtils.concat(array1, array2, array3));
     }
 
+    @Test
     @SmallTest
     public void testUnstableRemoveIf() throws Exception {
         java.util.function.Predicate<Object> isNull = new java.util.function.Predicate<Object>() {
@@ -357,31 +401,37 @@
         assertEquals(0, collection.size());
     }
 
+    @Test
     @SmallTest
     public void testThrowsIfOutOfBounds_passesWhenRangeInsideArray() {
         ArrayUtils.throwsIfOutOfBounds(10, 2, 6);
     }
 
+    @Test
     @SmallTest
     public void testThrowsIfOutOfBounds_passesWhenRangeIsWholeArray() {
         ArrayUtils.throwsIfOutOfBounds(10, 0, 10);
     }
 
+    @Test
     @SmallTest
     public void testThrowsIfOutOfBounds_passesWhenEmptyRangeAtStart() {
         ArrayUtils.throwsIfOutOfBounds(10, 0, 0);
     }
 
+    @Test
     @SmallTest
     public void testThrowsIfOutOfBounds_passesWhenEmptyRangeAtEnd() {
         ArrayUtils.throwsIfOutOfBounds(10, 10, 0);
     }
 
+    @Test
     @SmallTest
     public void testThrowsIfOutOfBounds_passesWhenEmptyArray() {
         ArrayUtils.throwsIfOutOfBounds(0, 0, 0);
     }
 
+    @Test
     @SmallTest
     public void testThrowsIfOutOfBounds_failsWhenRangeStartNegative() {
         try {
@@ -392,6 +442,7 @@
         }
     }
 
+    @Test
     @SmallTest
     public void testThrowsIfOutOfBounds_failsWhenCountNegative() {
         try {
@@ -402,6 +453,7 @@
         }
     }
 
+    @Test
     @SmallTest
     public void testThrowsIfOutOfBounds_failsWhenRangeStartTooHigh() {
         try {
@@ -412,6 +464,7 @@
         }
     }
 
+    @Test
     @SmallTest
     public void testThrowsIfOutOfBounds_failsWhenRangeEndTooHigh() {
         try {
@@ -422,6 +475,7 @@
         }
     }
 
+    @Test
     @SmallTest
     public void testThrowsIfOutOfBounds_failsWhenLengthNegative() {
         try {
@@ -432,6 +486,7 @@
         }
     }
 
+    @Test
     @SmallTest
     public void testThrowsIfOutOfBounds_failsWhenOverflowRangeEndTooHigh() {
         try {
diff --git a/core/tests/utiltests/src/com/android/internal/util/BitwiseStreamsTest.java b/core/tests/utiltests/src/com/android/internal/util/BitwiseStreamsTest.java
index 306f58f..092d699 100644
--- a/core/tests/utiltests/src/com/android/internal/util/BitwiseStreamsTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/BitwiseStreamsTest.java
@@ -16,20 +16,23 @@
 
 package com.android.internal.util;
 
-import com.android.internal.util.BitwiseInputStream;
-import com.android.internal.util.BitwiseOutputStream;
-import com.android.internal.util.HexDump;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+import static org.junit.Assert.assertEquals;
 
 import android.util.Log;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import java.util.Random;
 
-public class BitwiseStreamsTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class BitwiseStreamsTest {
     private final static String LOG_TAG = "BitwiseStreamsTest";
 
+    @Test
     @SmallTest
     public void testOne() throws Exception {
         int offset = 3;
@@ -45,6 +48,7 @@
         assertEquals(HexDump.toHexString(inBuf), HexDump.toHexString(inBufDup));
     }
 
+    @Test
     @SmallTest
     public void testTwo() throws Exception {
         int offset = 3;
@@ -59,6 +63,7 @@
         assertEquals(HexDump.toHexString(inBuf), HexDump.toHexString(inBufDup));
     }
 
+    @Test
     @SmallTest
     public void testThree() throws Exception {
         int offset = 4;
@@ -73,6 +78,7 @@
         assertEquals(HexDump.toHexString(inBuf), HexDump.toHexString(inBufDup));
     }
 
+    @Test
     @SmallTest
     public void testFour() throws Exception {
         int offset = 7;
@@ -90,6 +96,7 @@
         assertEquals(HexDump.toHexString(inBuf), HexDump.toHexString(inBufDup));
     }
 
+    @Test
     @SmallTest
     public void testFive() throws Exception {
         Random random = new Random();
@@ -111,6 +118,7 @@
         }
     }
 
+    @Test
     @SmallTest
     public void testSix() throws Exception {
         int num_runs = 10;
@@ -134,6 +142,7 @@
         Log.d(LOG_TAG, "repeated encode-decode took " + (end - start) + " ms");
     }
 
+    @Test
     @SmallTest
     public void testExpandArray() throws Exception {
         Random random = new Random();
diff --git a/core/tests/utiltests/src/com/android/internal/util/CallbackRegistryTest.java b/core/tests/utiltests/src/com/android/internal/util/CallbackRegistryTest.java
index 1581abb..9a1402e 100644
--- a/core/tests/utiltests/src/com/android/internal/util/CallbackRegistryTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/CallbackRegistryTest.java
@@ -15,19 +15,21 @@
  */
 package com.android.internal.util;
 
-import junit.framework.TestCase;
-
-import org.junit.Test;
-
-import java.util.ArrayList;
-import java.util.Objects;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
-public class CallbackRegistryTest extends TestCase {
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.Objects;
+
+@RunWith(AndroidJUnit4.class)
+public class CallbackRegistryTest {
 
     final Integer callback1 = 1;
     final Integer callback2 = 2;
@@ -50,6 +52,7 @@
         deepNotifyCount[callback]++;
     }
 
+    @Test
     public void testAddListener() {
         CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer> notifier =
                 new CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer>() {
@@ -89,6 +92,7 @@
         assertEquals(otherListener, callbacks.get(0));
     }
 
+    @Test
     public void testSimpleNotify() {
         CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer> notifier =
                 new CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer>() {
@@ -108,6 +112,7 @@
         assertEquals(1, notify2);
     }
 
+    @Test
     public void testRemoveWhileNotifying() {
         CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer> notifier =
                 new CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer>() {
@@ -135,6 +140,7 @@
         assertEquals(callback3, callbacks.get(0));
     }
 
+    @Test
     public void testDeepRemoveWhileNotifying() {
         CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer> notifier =
                 new CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer>() {
@@ -159,6 +165,7 @@
         assertEquals(0, callbacks.size());
     }
 
+    @Test
     public void testAddRemovedListener() {
 
         CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer> notifier =
@@ -191,6 +198,7 @@
         assertEquals(1, notify3);
     }
 
+    @Test
     public void testVeryDeepRemoveWhileNotifying() {
         final Integer[] callbacks = new Integer[deepNotifyCount.length];
         for (int i = 0; i < callbacks.length; i++) {
@@ -221,6 +229,7 @@
         assertEquals(0, callbackList.size());
     }
 
+    @Test
     public void testClear() {
         CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer> notifier =
                 new CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer>() {
@@ -245,6 +254,7 @@
         }
     }
 
+    @Test
     public void testNestedClear() {
         CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer> notifier =
                 new CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer>() {
@@ -268,6 +278,7 @@
         assertEquals(0, callbackList.size());
     }
 
+    @Test
     public void testIsEmpty() throws Exception {
         CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer> notifier =
                 new CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer>() {
@@ -284,6 +295,7 @@
         assertFalse(registry.isEmpty());
     }
 
+    @Test
     public void testClone() throws Exception {
         CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer> notifier =
                 new CallbackRegistry.NotifierCallback<Integer, CallbackRegistryTest, Integer>() {
diff --git a/core/tests/utiltests/src/com/android/internal/util/CharSequencesTest.java b/core/tests/utiltests/src/com/android/internal/util/CharSequencesTest.java
index 469a4cc..9888540 100644
--- a/core/tests/utiltests/src/com/android/internal/util/CharSequencesTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/CharSequencesTest.java
@@ -18,12 +18,26 @@
 
 import static com.android.internal.util.CharSequences.forAsciiBytes;
 
-import android.test.suitebuilder.annotation.SmallTest;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
-import junit.framework.TestCase;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 
-public class CharSequencesTest extends TestCase {
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = CharSequences.class)
+public class CharSequencesTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
+    @Test
     @SmallTest
     public void testCharSequences() {
         String s = "Hello Bob";
diff --git a/core/tests/utiltests/src/com/android/internal/util/FastXmlSerializerTest.java b/core/tests/utiltests/src/com/android/internal/util/FastXmlSerializerTest.java
index 3cef336..7723d58 100644
--- a/core/tests/utiltests/src/com/android/internal/util/FastXmlSerializerTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/FastXmlSerializerTest.java
@@ -16,13 +16,23 @@
 
 package com.android.internal.util;
 
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.SmallTest;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
+import android.provider.DeviceConfig;
 import android.util.Log;
 import android.util.Xml;
 
-import junit.framework.TestCase;
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlSerializer;
 
@@ -34,7 +44,9 @@
  * Tests for {@link FastXmlSerializer}
  */
 @SmallTest
-public class FastXmlSerializerTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = Xml.class)
+public class FastXmlSerializerTest {
     private static final String TAG = "FastXmlSerializerTest";
 
     private static final boolean ENABLE_DUMP = false; // DO NOT SUBMIT WITH TRUE.
@@ -42,6 +54,10 @@
     private static final String ROOT_TAG = "root";
     private static final String ATTR = "attr";
 
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
+    @Test
     public void testEmptyText() throws Exception {
         final ByteArrayOutputStream stream = new ByteArrayOutputStream();
 
@@ -128,6 +144,7 @@
         return ok;
     }
 
+    @Test
     @LargeTest
     public void testAllCharacters() throws Exception {
         boolean ok = true;
diff --git a/core/tests/utiltests/src/com/android/internal/util/FileRotatorTest.java b/core/tests/utiltests/src/com/android/internal/util/FileRotatorTest.java
index 73e47e16..47c1795 100644
--- a/core/tests/utiltests/src/com/android/internal/util/FileRotatorTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/FileRotatorTest.java
@@ -23,16 +23,23 @@
 import static android.text.format.DateUtils.WEEK_IN_MILLIS;
 import static android.text.format.DateUtils.YEAR_IN_MILLIS;
 
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.Suppress;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
 import android.util.Log;
 
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.util.FileRotator.Reader;
 import com.android.internal.util.FileRotator.Writer;
-import com.android.internal.util.test.FsUtil;
 
 import com.google.android.collect.Lists;
 
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.File;
@@ -40,6 +47,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.nio.file.Files;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Random;
@@ -47,7 +55,8 @@
 /**
  * Tests for {@link FileRotator}.
  */
-public class FileRotatorTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class FileRotatorTest {
     private static final String TAG = "FileRotatorTest";
 
     private File mBasePath;
@@ -59,14 +68,12 @@
 
     // TODO: test throwing rolls back correctly
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        mBasePath = getContext().getFilesDir();
-        FsUtil.deleteContents(mBasePath);
+    @Before
+    public void setUp() throws Exception {
+        mBasePath = Files.createTempDirectory(TAG).toFile();
     }
 
+    @Test
     public void testEmpty() throws Exception {
         final FileRotator rotate1 = new FileRotator(
                 mBasePath, PREFIX, DAY_IN_MILLIS, WEEK_IN_MILLIS);
@@ -85,6 +92,7 @@
         assertReadAll(rotate2);
     }
 
+    @Test
     public void testCombine() throws Exception {
         final FileRotator rotate = new FileRotator(
                 mBasePath, PREFIX, DAY_IN_MILLIS, WEEK_IN_MILLIS);
@@ -106,6 +114,7 @@
         assertReadAll(rotate, "bar");
     }
 
+    @Test
     public void testRotate() throws Exception {
         final FileRotator rotate = new FileRotator(
                 mBasePath, PREFIX, DAY_IN_MILLIS, WEEK_IN_MILLIS);
@@ -138,6 +147,7 @@
         assertReadAll(rotate, "bar", "baz");
     }
 
+    @Test
     public void testDelete() throws Exception {
         final FileRotator rotate = new FileRotator(
                 mBasePath, PREFIX, MINUTE_IN_MILLIS, DAY_IN_MILLIS);
@@ -168,6 +178,7 @@
         assertReadAll(rotate);
     }
 
+    @Test
     public void testThrowRestoresBackup() throws Exception {
         final FileRotator rotate = new FileRotator(
                 mBasePath, PREFIX, MINUTE_IN_MILLIS, DAY_IN_MILLIS);
@@ -201,6 +212,7 @@
         assertReadAll(rotate, "foo");
     }
 
+    @Test
     public void testOtherFilesAndMalformed() throws Exception {
         final FileRotator rotate = new FileRotator(
                 mBasePath, PREFIX, SECOND_IN_MILLIS, SECOND_IN_MILLIS);
@@ -229,6 +241,7 @@
     private static final String BLUE = "blue";
     private static final String YELLOW = "yellow";
 
+    @Test
     public void testQueryMatch() throws Exception {
         final FileRotator rotate = new FileRotator(
                 mBasePath, PREFIX, HOUR_IN_MILLIS, YEAR_IN_MILLIS);
@@ -277,6 +290,7 @@
         assertReadMatching(rotate, Long.MIN_VALUE, TEST_TIME - DAY_IN_MILLIS);
     }
 
+    @Test
     public void testClockRollingBackwards() throws Exception {
         final FileRotator rotate = new FileRotator(
                 mBasePath, PREFIX, DAY_IN_MILLIS, YEAR_IN_MILLIS);
@@ -325,7 +339,8 @@
         assertReadAll(rotate, "meow", "yay");
     }
 
-    @Suppress
+    @Test
+    @Ignore
     public void testFuzz() throws Exception {
         final FileRotator rotate = new FileRotator(
                 mBasePath, PREFIX, HOUR_IN_MILLIS, DAY_IN_MILLIS);
@@ -352,6 +367,7 @@
         Log.d(TAG, Arrays.toString(mBasePath.list()));
     }
 
+    @Test
     public void testRecoverAtomic() throws Exception {
         write("rotator.1024-2048", "foo");
         write("rotator.1024-2048.backup", "bar");
@@ -366,6 +382,7 @@
         assertReadAll(rotate, "bar");
     }
 
+    @Test
     public void testReadSorted() throws Exception {
         write("rotator.1024-2048", "2");
         write("rotator.2048-4096", "3");
@@ -376,11 +393,11 @@
         assertReadAll(rotate, "1", "2", "3");
     }
 
+    @Test
     public void testFileSystemInaccessible() throws Exception {
-        File inaccessibleDir = null;
-        String dirPath = getContext().getFilesDir() + File.separator + "inaccessible";
-        inaccessibleDir = new File(dirPath);
-        final FileRotator rotate = new FileRotator(inaccessibleDir, PREFIX, SECOND_IN_MILLIS, SECOND_IN_MILLIS);
+        File inaccessibleDir = mBasePath.toPath().resolve("does_not_exist").toFile();
+        final FileRotator rotate = new FileRotator(inaccessibleDir, PREFIX,
+                SECOND_IN_MILLIS, SECOND_IN_MILLIS);
 
         // rotate should not throw on dir not mkdir-ed (or otherwise inaccessible)
         rotate.maybeRotate(TEST_TIME);
diff --git a/core/tests/utiltests/src/com/android/internal/util/HeavyHitterSketchTest.java b/core/tests/utiltests/src/com/android/internal/util/HeavyHitterSketchTest.java
index f2285a1..74184ca 100644
--- a/core/tests/utiltests/src/com/android/internal/util/HeavyHitterSketchTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/HeavyHitterSketchTest.java
@@ -16,10 +16,17 @@
 
 package com.android.internal.util;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
 import android.util.ArraySet;
 import android.util.Pair;
 
-import junit.framework.TestCase;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.util.ArrayList;
 import java.util.Comparator;
@@ -32,7 +39,8 @@
 /**
  * Tests for {@link HeavyHitterSketch}.
  */
-public final class HeavyHitterSketchTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+public final class HeavyHitterSketchTest {
 
     private static final float EPSILON = 0.00001f;
 
@@ -163,6 +171,7 @@
         return input;
     }
 
+    @Test
     public void testPositive() throws Exception {
         // Simple case
         verify(new int[]{2, 9, 9, 9, 7, 6, 4, 9, 9, 9, 3, 9}, 2, new int[]{9},
@@ -179,6 +188,7 @@
                 new float[]{0.32f, 0.24f, 0.16f, 0.08f});
     }
 
+    @Test
     public void testNegative() throws Exception {
         // Simple case
         verifyNotExpected(new int[]{2, 9, 9, 9, 7, 6, 4, 9, 9, 9, 3, 9}, 2, new int[]{0, 1, 2});
@@ -193,6 +203,7 @@
         verifyNotExpected(input, 12, new int[]{0, 1, 2, 1000, 1005});
     }
 
+    @Test
     public void testFalsePositive() throws Exception {
         // Simple case
         verifyNotExpected(new int[]{2, 9, 2, 2, 7, 6, 4, 9, 9, 9, 3, 9}, 2, new int[]{9});
diff --git a/core/tests/utiltests/src/com/android/internal/util/InlinePresentationStyleUtilsTest.java b/core/tests/utiltests/src/com/android/internal/util/InlinePresentationStyleUtilsTest.java
index 35c5681..7203b8c 100644
--- a/core/tests/utiltests/src/com/android/internal/util/InlinePresentationStyleUtilsTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/InlinePresentationStyleUtilsTest.java
@@ -22,20 +22,28 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+import android.graphics.Color;
 import android.os.Binder;
 import android.os.Bundle;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.widget.InlinePresentationStyleUtils;
 
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
+@IgnoreUnderRavenwood(blockedBy = InlinePresentationStyleUtils.class)
 public class InlinePresentationStyleUtilsTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     @Test
     public void testBundleEquals_empty() {
         Bundle bundle1 = new Bundle();
diff --git a/core/tests/utiltests/src/com/android/internal/util/LockPatternUtilsTest.java b/core/tests/utiltests/src/com/android/internal/util/LockPatternUtilsTest.java
index 0b70199..0df5b0a 100644
--- a/core/tests/utiltests/src/com/android/internal/util/LockPatternUtilsTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/LockPatternUtilsTest.java
@@ -43,6 +43,8 @@
 import android.os.Looper;
 import android.os.RemoteException;
 import android.os.UserManager;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.provider.Settings;
 import android.test.mock.MockContentResolver;
 
@@ -58,6 +60,7 @@
 
 import com.google.android.collect.Lists;
 
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
@@ -68,7 +71,10 @@
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
+@IgnoreUnderRavenwood(blockedBy = LockPatternUtils.class)
 public class LockPatternUtilsTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
 
     private static final int DEMO_USER_ID = 5;
 
diff --git a/core/tests/utiltests/src/com/android/internal/util/MessageUtilsTest.java b/core/tests/utiltests/src/com/android/internal/util/MessageUtilsTest.java
index 32b969a..36f238e 100644
--- a/core/tests/utiltests/src/com/android/internal/util/MessageUtilsTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/MessageUtilsTest.java
@@ -19,10 +19,13 @@
 import static org.junit.Assert.*;
 
 import com.android.internal.util.MessageUtils;
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import android.util.SparseArray;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 
 class A {
@@ -48,6 +51,7 @@
  * Unit tests for {@link com.android.util.MessageUtils}.
  */
 @SmallTest
+@RunWith(AndroidJUnit4.class)
 public class MessageUtilsTest {
 
     private static final Class[] CLASSES = { A.class, B.class };
diff --git a/core/tests/utiltests/src/com/android/internal/util/MimeIconUtilsTest.java b/core/tests/utiltests/src/com/android/internal/util/MimeIconUtilsTest.java
index 4412c2c..6c34797 100644
--- a/core/tests/utiltests/src/com/android/internal/util/MimeIconUtilsTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/MimeIconUtilsTest.java
@@ -16,12 +16,27 @@
 
 package com.android.internal.util;
 
-import junit.framework.TestCase;
+import static org.junit.Assert.assertEquals;
+
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 /**
  * Tests for {@link MimeIconUtils}.
  */
-public class MimeIconUtilsTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = MimeIconUtils.class)
+public class MimeIconUtilsTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
+    @Test
     public void testSimple() throws Exception {
         assertEquals("PNG image",
                 MimeIconUtils.getTypeInfo("image/png").getLabel());
diff --git a/core/tests/utiltests/src/com/android/internal/util/ObjectUtilsTest.java b/core/tests/utiltests/src/com/android/internal/util/ObjectUtilsTest.java
index 443183e..4eaacff 100644
--- a/core/tests/utiltests/src/com/android/internal/util/ObjectUtilsTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/ObjectUtilsTest.java
@@ -15,11 +15,18 @@
  */
 package com.android.internal.util;
 
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+import static org.junit.Assert.assertEquals;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 @SmallTest
-public class ObjectUtilsTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class ObjectUtilsTest {
+    @Test
     public void testCompare() {
         assertEquals(0, ObjectUtils.compare(null, null));
         assertEquals(1, ObjectUtils.compare("a", null));
diff --git a/core/tests/utiltests/src/com/android/internal/util/ObservableServiceConnectionTest.java b/core/tests/utiltests/src/com/android/internal/util/ObservableServiceConnectionTest.java
index d124ad9..c852e9f 100644
--- a/core/tests/utiltests/src/com/android/internal/util/ObservableServiceConnectionTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/ObservableServiceConnectionTest.java
@@ -29,14 +29,19 @@
 import android.content.Context;
 import android.content.Intent;
 import android.os.IBinder;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
 
 import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.util.ObservableServiceConnection.ServiceTransformer;
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -46,7 +51,12 @@
 import java.util.concurrent.Executor;
 
 @SmallTest
+@RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = ObservableServiceConnection.class)
 public class ObservableServiceConnectionTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     private static final ComponentName COMPONENT_NAME =
             new ComponentName("test.package", "component");
 
diff --git a/core/tests/utiltests/src/com/android/internal/util/PersistentServiceConnectionTest.java b/core/tests/utiltests/src/com/android/internal/util/PersistentServiceConnectionTest.java
index fee4654..096f303 100644
--- a/core/tests/utiltests/src/com/android/internal/util/PersistentServiceConnectionTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/PersistentServiceConnectionTest.java
@@ -30,6 +30,10 @@
 import android.content.Context;
 import android.content.Intent;
 import android.os.IBinder;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
+
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.util.ObservableServiceConnection.ServiceTransformer;
 import com.android.server.testutils.OffsettableClock;
@@ -37,7 +41,9 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -45,7 +51,12 @@
 import java.util.Queue;
 import java.util.concurrent.Executor;
 
+@RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = PersistentServiceConnection.class)
 public class PersistentServiceConnectionTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     private static final ComponentName COMPONENT_NAME =
             new ComponentName("test.package", "component");
     private static final int MAX_RETRIES = 2;
diff --git a/core/tests/utiltests/src/com/android/internal/util/ProcFileReaderTest.java b/core/tests/utiltests/src/com/android/internal/util/ProcFileReaderTest.java
index b932760..4c00c16 100644
--- a/core/tests/utiltests/src/com/android/internal/util/ProcFileReaderTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/ProcFileReaderTest.java
@@ -16,7 +16,15 @@
 
 package com.android.internal.util;
 
-import android.test.AndroidTestCase;
+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 androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.io.ByteArrayInputStream;
 import java.io.File;
@@ -28,8 +36,10 @@
 /**
  * Tests for {@link ProcFileReader}.
  */
-public class ProcFileReaderTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class ProcFileReaderTest {
 
+    @Test
     public void testEmpty() throws Exception {
         final ProcFileReader reader = buildReader("");
 
@@ -43,6 +53,7 @@
         assertFalse(reader.hasMoreData());
     }
 
+    @Test
     public void testSingleString() throws Exception {
         final ProcFileReader reader = buildReader("a\nb\nc\n");
 
@@ -59,6 +70,7 @@
         assertFalse(reader.hasMoreData());
     }
 
+    @Test
     public void testMixedNumbersSkip() throws Exception {
         final ProcFileReader reader = buildReader("1 2 3\n4 abc_def 5 6 7 8 9\n10\n");
 
@@ -79,6 +91,7 @@
         assertFalse(reader.hasMoreData());
     }
 
+    @Test
     public void testBufferSize() throws Exception {
         // read numbers using very small buffer size, exercising fillBuf()
         final ProcFileReader reader = buildReader("1 21 3 41 5 61 7 81 9 10\n", 3);
@@ -97,6 +110,7 @@
         assertFalse(reader.hasMoreData());
     }
 
+    @Test
     public void testBlankLines() throws Exception {
         final ProcFileReader reader = buildReader("1\n\n2\n\n3\n");
 
@@ -117,6 +131,7 @@
         assertFalse(reader.hasMoreData());
     }
 
+    @Test
     public void testMinMax() throws Exception {
         final ProcFileReader reader = buildReader(
                 "1 -1024 9223372036854775807 -9223372036854775808\n");
@@ -129,6 +144,7 @@
         assertFalse(reader.hasMoreData());
     }
 
+    @Test
     public void testDelimiterNeverFound() throws Exception {
         final ProcFileReader reader = buildReader("teststringwithoutdelimiters");
 
@@ -141,6 +157,7 @@
         }
     }
 
+    @Test
     public void testLargerThanBuffer() throws Exception {
         // try finishing line larger than buffer
         final ProcFileReader reader = buildReader("1 teststringlongerthanbuffer\n", 4);
@@ -155,6 +172,7 @@
         }
     }
 
+    @Test
     public void testOptionalLongs() throws Exception {
         final ProcFileReader reader = buildReader("123 456\n789\n");
 
@@ -169,6 +187,7 @@
         assertEquals(-1L, reader.nextOptionalLong(-1L));
     }
 
+    @Test
     public void testInvalidLongs() throws Exception {
         final ProcFileReader reader = buildReader("12: 34\n56 78@#\n");
 
@@ -183,6 +202,7 @@
         assertFalse(reader.hasMoreData());
     }
 
+    @Test
     public void testConsecutiveDelimiters() throws Exception {
         final ProcFileReader reader = buildReader("1 2  3   4     5\n");
 
@@ -195,6 +215,7 @@
         assertFalse(reader.hasMoreData());
     }
 
+    @Test
     public void testIgnore() throws Exception {
         final ProcFileReader reader = buildReader("a b c\n");
 
@@ -209,6 +230,7 @@
         assertFalse(reader.hasMoreData());
     }
 
+    @Test
     public void testRewind() throws Exception {
         final ProcFileReader reader = buildReader("abc\n");
 
@@ -224,7 +246,7 @@
         assertFalse(reader.hasMoreData());
     }
 
-
+    @Test
     public void testRewindFileInputStream() throws Exception {
         File tempFile = File.createTempFile("procfile", null, null);
         Files.write(tempFile.toPath(), "abc\n".getBytes(StandardCharsets.US_ASCII));
diff --git a/core/tests/utiltests/src/com/android/internal/util/QuickSelectTest.java b/core/tests/utiltests/src/com/android/internal/util/QuickSelectTest.java
index 1b9d2ef..1eb5e3ab 100644
--- a/core/tests/utiltests/src/com/android/internal/util/QuickSelectTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/QuickSelectTest.java
@@ -16,7 +16,12 @@
 
 package com.android.internal.util;
 
-import junit.framework.TestCase;
+import static org.junit.Assert.assertEquals;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.util.Arrays;
 import java.util.List;
@@ -24,8 +29,10 @@
 /**
  * Tests for {@link QuickSelect}.
  */
-public final class QuickSelectTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+public class QuickSelectTest {
 
+    @Test
     public void testQuickSelect() throws Exception {
         test((List<Integer>) null, 0, null);
         test(Arrays.asList(), -1, null);
diff --git a/core/tests/utiltests/src/com/android/internal/util/StringPoolTest.java b/core/tests/utiltests/src/com/android/internal/util/StringPoolTest.java
index f67fd51..6523ed7 100644
--- a/core/tests/utiltests/src/com/android/internal/util/StringPoolTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/StringPoolTest.java
@@ -16,12 +16,21 @@
 
 package com.android.internal.util;
 
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertSame;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 @SmallTest
-public final class StringPoolTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public final class StringPoolTest {
 
+    @Test
     public void testStringPool() {
         StringPool stringPool = new StringPool();
         String bcd = stringPool.get(new char[] { 'a', 'b', 'c', 'd', 'e' }, 1, 3);
@@ -29,6 +38,7 @@
         assertSame(bcd, stringPool.get(new char[] { 'a', 'b', 'c', 'd', 'e' }, 1, 3));
     }
 
+    @Test
     public void testHashCollision() {
         StringPool stringPool = new StringPool();
         char[] a = { (char) 1, (char) 0 };
diff --git a/core/tests/utiltests/src/com/android/internal/util/WakeupMessageTest.java b/core/tests/utiltests/src/com/android/internal/util/WakeupMessageTest.java
index 734ebef..b0db8a1 100644
--- a/core/tests/utiltests/src/com/android/internal/util/WakeupMessageTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/WakeupMessageTest.java
@@ -24,11 +24,17 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
@@ -40,6 +46,8 @@
  * Unit tests for {@link com.android.internal.util.WakeupMessage}.
  */
 @SmallTest
+@RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = WakeupMessage.class)
 public class WakeupMessageTest {
     private static final String TEST_CMD_NAME = "TEST cmd Name";
     private static final int TEST_CMD = 18;
@@ -47,11 +55,16 @@
     private static final int TEST_ARG2 = 182;
     private static final Object TEST_OBJ = "hello";
 
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder()
+            .setProvideMainThread(true)
+            .build();
+
     @Mock Context mContext;
     @Mock AlarmManager mAlarmManager;
     WakeupMessage mMessage;
     // Make a spy so that we can verify calls to it
-    @Spy MessageCapturingHandler mHandler = new MessageCapturingHandler();
+    @Spy MessageCapturingHandler mHandler;
 
     ArgumentCaptor<AlarmManager.OnAlarmListener> mListenerCaptor =
             ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class);
@@ -85,6 +98,8 @@
      */
     @Before
     public void setUp() {
+        mHandler = new MessageCapturingHandler();
+
         MockitoAnnotations.initMocks(this);
 
         when(mContext.getSystemService(Context.ALARM_SERVICE)).thenReturn(mAlarmManager);
diff --git a/core/tests/utiltests/src/com/android/internal/util/XmlUtilsTest.java b/core/tests/utiltests/src/com/android/internal/util/XmlUtilsTest.java
index 0484068..24eb213 100644
--- a/core/tests/utiltests/src/com/android/internal/util/XmlUtilsTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/XmlUtilsTest.java
@@ -17,13 +17,17 @@
 package com.android.internal.util;
 
 import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
 
 import android.util.Xml;
 
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.modules.utils.TypedXmlPullParser;
 import com.android.modules.utils.TypedXmlSerializer;
 
-import junit.framework.TestCase;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
@@ -32,9 +36,11 @@
 import java.util.HashMap;
 import java.util.Map;
 
-public class XmlUtilsTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+public class XmlUtilsTest {
 
     // https://code.google.com/p/android/issues/detail?id=63717
+    @Test
     public void testMapWithNullKeys() throws Exception {
         ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
         Map<String, Object> map = new HashMap<String, Object>();
@@ -48,6 +54,7 @@
         assertEquals("fooValue", deserialized.get("foo"));
     }
 
+    @Test
     public void testreadWriteXmlByteArrayValue() throws Exception {
         byte[] testByteArray = {0x1 , 0xa, 0xb, 0x9, 0x34, (byte) 0xaa, (byte) 0xba, (byte) 0x99};
 
diff --git a/core/tests/utiltests/src/com/android/internal/util/test/FakeSettingsProviderTest.java b/core/tests/utiltests/src/com/android/internal/util/test/FakeSettingsProviderTest.java
index f2be109..502d6b6 100644
--- a/core/tests/utiltests/src/com/android/internal/util/test/FakeSettingsProviderTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/test/FakeSettingsProviderTest.java
@@ -16,33 +16,41 @@
 
 package com.android.internal.util.test;
 
-import android.content.ContentResolver;
-import android.database.ContentObserver;
-import android.net.Uri;
-import android.provider.Settings;
-import android.test.AndroidTestCase;
-import android.test.mock.MockContentResolver;
-import android.test.mock.MockContext;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.test.suitebuilder.annotation.Suppress;
-import android.util.Log;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
 
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
+import android.content.ContentProvider;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
+import android.provider.Settings;
+import android.test.mock.MockContentResolver;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 /**
  * Unit tests for FakeSettingsProvider.
  */
-public class FakeSettingsProviderTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = ContentProvider.class)
+public class FakeSettingsProviderTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
 
     private MockContentResolver mCr;
 
-    @Override
+    @Before
     public void setUp() throws Exception {
         mCr = new MockContentResolver();
         mCr.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
     }
 
+    @Test
     @SmallTest
     public void testBasicOperation() throws Exception {
         String settingName = Settings.System.SCREEN_BRIGHTNESS;
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 2237ba1..aaddf0e 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -169,6 +169,12 @@
       "group": "WM_DEBUG_WINDOW_ORGANIZER",
       "at": "com\/android\/server\/wm\/TaskOrganizerController.java"
     },
+    "-1961637874": {
+      "message": "DeferredDisplayUpdater: applying DisplayInfo immediately",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_WINDOW_TRANSITIONS",
+      "at": "com\/android\/server\/wm\/DeferredDisplayUpdater.java"
+    },
     "-1949279037": {
       "message": "Attempted to add input method window with bad token %s.  Aborting.",
       "level": "WARN",
@@ -313,6 +319,12 @@
       "group": "WM_DEBUG_RESIZE",
       "at": "com\/android\/server\/wm\/WindowState.java"
     },
+    "-1818910559": {
+      "message": "DeferredDisplayUpdater: applied DisplayInfo after deferring",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_WINDOW_TRANSITIONS",
+      "at": "com\/android\/server\/wm\/DeferredDisplayUpdater.java"
+    },
     "-1814361639": {
       "message": "Set IME snapshot position: (%d, %d)",
       "level": "INFO",
@@ -595,6 +607,12 @@
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
+    "-1518132958": {
+      "message": "fractionRendered boundsOverSource=%f",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_TPL",
+      "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java"
+    },
     "-1517908912": {
       "message": "requestScrollCapture: caught exception dispatching to window.token=%s",
       "level": "WARN",
@@ -961,6 +979,12 @@
       "group": "WM_DEBUG_CONTENT_RECORDING",
       "at": "com\/android\/server\/wm\/ContentRecorder.java"
     },
+    "-1209762265": {
+      "message": "Registering listener=%s with id=%d for window=%s with %s",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_TPL",
+      "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java"
+    },
     "-1209252064": {
       "message": "Clear animatingExit: reason=clearAnimatingFlags win=%s",
       "level": "DEBUG",
@@ -1333,6 +1357,12 @@
       "group": "WM_DEBUG_WINDOW_TRANSITIONS",
       "at": "com\/android\/server\/wm\/Transition.java"
     },
+    "-888703350": {
+      "message": "Skipping %s",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_TPL",
+      "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java"
+    },
     "-883738232": {
       "message": "Adding more than one toast window for UID at a time.",
       "level": "WARN",
@@ -1909,6 +1939,12 @@
       "group": "WM_DEBUG_FOCUS_LIGHT",
       "at": "com\/android\/server\/wm\/DisplayContent.java"
     },
+    "-415346336": {
+      "message": "DeferredDisplayUpdater: partially applying DisplayInfo immediately",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_WINDOW_TRANSITIONS",
+      "at": "com\/android\/server\/wm\/DeferredDisplayUpdater.java"
+    },
     "-401282500": {
       "message": "destroyIfPossible: r=%s destroy returned removed=%s",
       "level": "DEBUG",
@@ -1957,6 +1993,12 @@
       "group": "WM_DEBUG_APP_TRANSITIONS",
       "at": "com\/android\/server\/wm\/AppTransitionController.java"
     },
+    "-376950429": {
+      "message": "DeferredDisplayUpdater: deferring DisplayInfo update",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_WINDOW_TRANSITIONS",
+      "at": "com\/android\/server\/wm\/DeferredDisplayUpdater.java"
+    },
     "-374767836": {
       "message": "setAppVisibility(%s, visible=%b): %s visible=%b mVisibleRequested=%b Callers=%s",
       "level": "VERBOSE",
@@ -2803,6 +2845,12 @@
       "group": "WM_DEBUG_ORIENTATION",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
+    "360319850": {
+      "message": "fractionRendered scale=%f",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_TPL",
+      "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java"
+    },
     "364992694": {
       "message": "freezeDisplayRotation: current rotation=%d, new rotation=%d, caller=%s",
       "level": "VERBOSE",
@@ -2983,6 +3031,12 @@
       "group": "WM_DEBUG_BACK_PREVIEW",
       "at": "com\/android\/server\/wm\/BackNavigationController.java"
     },
+    "532771960": {
+      "message": "Adding untrusted state listener=%s with id=%d",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_TPL",
+      "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java"
+    },
     "535103992": {
       "message": "Wallpaper may change!  Adjusting",
       "level": "VERBOSE",
@@ -3061,6 +3115,12 @@
       "group": "WM_DEBUG_DREAM",
       "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java"
     },
+    "605179032": {
+      "message": "checkIfInThreshold fractionRendered=%f alpha=%f currTimeMs=%d",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_TPL",
+      "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java"
+    },
     "608694300": {
       "message": "  NEW SURFACE SESSION %s",
       "level": "INFO",
@@ -3289,6 +3349,12 @@
       "group": "WM_SHOW_TRANSACTIONS",
       "at": "com\/android\/server\/wm\/WindowState.java"
     },
+    "824532141": {
+      "message": "lastState=%s newState=%s alpha=%f minAlpha=%f fractionRendered=%f minFractionRendered=%f",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_TPL",
+      "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java"
+    },
     "829434921": {
       "message": "Draw state now committed in %s",
       "level": "VERBOSE",
@@ -3583,6 +3649,12 @@
       "group": "WM_SHOW_SURFACE_ALLOC",
       "at": "com\/android\/server\/wm\/ScreenRotationAnimation.java"
     },
+    "1090378847": {
+      "message": "Checking %d windows",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_TPL",
+      "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java"
+    },
     "1100065297": {
       "message": "Attempted to get IME policy of a display that does not exist: %d",
       "level": "WARN",
@@ -3715,6 +3787,12 @@
       "group": "WM_DEBUG_FOCUS",
       "at": "com\/android\/server\/wm\/ActivityRecord.java"
     },
+    "1251721200": {
+      "message": "unregister failed, couldn't find deathRecipient for %s with id=%d",
+      "level": "ERROR",
+      "group": "WM_DEBUG_TPL",
+      "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java"
+    },
     "1252594551": {
       "message": "Window types in WindowContext and LayoutParams.type should match! Type from LayoutParams is %d, but type from WindowContext is %d",
       "level": "WARN",
@@ -3853,6 +3931,12 @@
       "group": "WM_DEBUG_ORIENTATION",
       "at": "com\/android\/server\/wm\/TaskDisplayArea.java"
     },
+    "1382634842": {
+      "message": "Unregistering listener=%s with id=%d",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_TPL",
+      "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java"
+    },
     "1393721079": {
       "message": "Starting remote display change: from [rot = %d], to [%dx%d, rot = %d]",
       "level": "VERBOSE",
@@ -3901,6 +3985,12 @@
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
+    "1445704347": {
+      "message": "coveredRegionsAbove updated with %s frame:%s region:%s",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_TPL",
+      "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java"
+    },
     "1448683958": {
       "message": "Override pending remote transitionSet=%b adapter=%s",
       "level": "INFO",
@@ -4201,6 +4291,12 @@
       "group": "WM_DEBUG_RECENTS_ANIMATIONS",
       "at": "com\/android\/server\/wm\/RecentsAnimation.java"
     },
+    "1786463281": {
+      "message": "Adding trusted state listener=%s with id=%d",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_TPL",
+      "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java"
+    },
     "1789321832": {
       "message": "Then token:%s is invalid. It might be removed",
       "level": "WARN",
@@ -4375,6 +4471,12 @@
       "group": "WM_DEBUG_TASKS",
       "at": "com\/android\/server\/wm\/RootWindowContainer.java"
     },
+    "1955470028": {
+      "message": "computeFractionRendered: visibleRegion=%s screenBounds=%s contentSize=%s scale=%f,%f",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_TPL",
+      "at": "com\/android\/server\/wm\/TrustedPresentationListenerController.java"
+    },
     "1964565370": {
       "message": "Starting remote animation",
       "level": "INFO",
@@ -4659,6 +4761,9 @@
     "WM_DEBUG_TASKS": {
       "tag": "WindowManager"
     },
+    "WM_DEBUG_TPL": {
+      "tag": "WindowManager"
+    },
     "WM_DEBUG_WALLPAPER": {
       "tag": "WindowManager"
     },
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 92c4de6..f10cdb8 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -1739,10 +1739,6 @@
     /**
      * Get the elegant metrics flag.
      *
-     * From API {@link Build.VERSION_CODES#VANILLA_ICE_CREAM}, the default value will be true by
-     * default if the app has a target SDK of API {@link Build.VERSION_CODES#VANILLA_ICE_CREAM} or
-     * later.
-     *
      * @return true if elegant metrics are enabled for text drawing.
      */
     public boolean isElegantTextHeight() {
diff --git a/graphics/java/android/graphics/text/LineBreakConfig.java b/graphics/java/android/graphics/text/LineBreakConfig.java
index c5e451a..ddae673 100644
--- a/graphics/java/android/graphics/text/LineBreakConfig.java
+++ b/graphics/java/android/graphics/text/LineBreakConfig.java
@@ -354,13 +354,13 @@
             return this;
         }
 
+        // TODO(316208691): Revive following removed API docs.
+        // Note: different from {@link #merge(LineBreakConfig)} if this function is called with
+        // {@link #LINE_BREAK_STYLE_UNSPECIFIED}, the line break style is reset to
+        // {@link #LINE_BREAK_STYLE_UNSPECIFIED}.
         /**
          * Sets the line-break style.
          *
-         * Note: different from {@link #merge(LineBreakConfig)} if this function is called with
-         * {@link #LINE_BREAK_STYLE_UNSPECIFIED}, the line break style is reset to
-         * {@link #LINE_BREAK_STYLE_UNSPECIFIED}.
-         *
          * @see <a href="https://unicode.org/reports/tr35/#UnicodeLineBreakStyleIdentifier">
          *     Unicode Line Break Style Identifier</a>
          * @see <a href="https://drafts.csswg.org/css-text/#line-break-property">
@@ -374,13 +374,13 @@
             return this;
         }
 
+        // TODO(316208691): Revive following removed API docs.
+        // Note: different from {@link #merge(LineBreakConfig)} method, if this function is called
+        // with {@link #LINE_BREAK_WORD_STYLE_UNSPECIFIED}, the line break style is reset to
+        // {@link #LINE_BREAK_WORD_STYLE_UNSPECIFIED}.
         /**
          * Sets the line-break word style.
          *
-         * Note: different from {@link #merge(LineBreakConfig)} method, if this function is called
-         * with {@link #LINE_BREAK_WORD_STYLE_UNSPECIFIED}, the line break style is reset to
-         * {@link #LINE_BREAK_WORD_STYLE_UNSPECIFIED}.
-         *
          * @see <a href="https://unicode.org/reports/tr35/#UnicodeLineBreakWordIdentifier">
          *     Unicode Line Break Word Identifier</a>
          * @see <a href="https://drafts.csswg.org/css-text/#word-break-property">
diff --git a/keystore/java/android/security/Authorization.java b/keystore/java/android/security/Authorization.java
index b4b3e92..4ec5e1b 100644
--- a/keystore/java/android/security/Authorization.java
+++ b/keystore/java/android/security/Authorization.java
@@ -26,7 +26,6 @@
 import android.os.ServiceSpecificException;
 import android.os.StrictMode;
 import android.security.authorization.IKeystoreAuthorization;
-import android.security.authorization.LockScreenEvent;
 import android.system.keystore2.ResponseCode;
 import android.util.Log;
 
@@ -76,26 +75,37 @@
     }
 
     /**
-     * Informs keystore2 about lock screen event.
+     * Tells Keystore that the device is now unlocked for a user.
      *
-     * @param locked            - whether it is a lock (true) or unlock (false) event
-     * @param syntheticPassword - if it is an unlock event with the password, pass the synthetic
-     *                            password provided by the LockSettingService
-     * @param unlockingSids     - KeyMint secure user IDs that should be permitted to unlock
-     *                            UNLOCKED_DEVICE_REQUIRED keys.
-     *
+     * @param userId - the user's Android user ID
+     * @param password - a secret derived from the user's synthetic password, if the unlock method
+     *                   is LSKF (or equivalent) and thus has made the synthetic password available
      * @return 0 if successful or a {@code ResponseCode}.
      */
-    public static int onLockScreenEvent(@NonNull boolean locked, @NonNull int userId,
-            @Nullable byte[] syntheticPassword, @Nullable long[] unlockingSids) {
+    public static int onDeviceUnlocked(int userId, @Nullable byte[] password) {
         StrictMode.noteDiskWrite();
         try {
-            if (locked) {
-                getService().onLockScreenEvent(LockScreenEvent.LOCK, userId, null, unlockingSids);
-            } else {
-                getService().onLockScreenEvent(
-                        LockScreenEvent.UNLOCK, userId, syntheticPassword, unlockingSids);
-            }
+            getService().onDeviceUnlocked(userId, password);
+            return 0;
+        } catch (RemoteException | NullPointerException e) {
+            Log.w(TAG, "Can not connect to keystore", e);
+            return SYSTEM_ERROR;
+        } catch (ServiceSpecificException e) {
+            return e.errorCode;
+        }
+    }
+
+    /**
+     * Tells Keystore that the device is now locked for a user.
+     *
+     * @param userId - the user's Android user ID
+     * @param unlockingSids - list of biometric SIDs with which the device may be unlocked again
+     * @return 0 if successful or a {@code ResponseCode}.
+     */
+    public static int onDeviceLocked(int userId, @NonNull long[] unlockingSids) {
+        StrictMode.noteDiskWrite();
+        try {
+            getService().onDeviceLocked(userId, unlockingSids);
             return 0;
         } catch (RemoteException | NullPointerException e) {
             Log.w(TAG, "Can not connect to keystore", e);
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index 231fa48..4982f37 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -618,7 +618,7 @@
      * @see #isMgf1DigestsSpecified()
      */
     @NonNull
-    @FlaggedApi("MGF1_DIGEST_SETTER")
+    @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER)
     public @KeyProperties.DigestEnum Set<String> getMgf1Digests() {
         if (mMgf1Digests.isEmpty()) {
             throw new IllegalStateException("Mask generation function (MGF) not specified");
@@ -633,7 +633,7 @@
      * @see #getMgf1Digests()
      */
     @NonNull
-    @FlaggedApi("MGF1_DIGEST_SETTER")
+    @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER)
     public boolean isMgf1DigestsSpecified() {
         return !mMgf1Digests.isEmpty();
     }
@@ -1292,7 +1292,7 @@
          * <p>See {@link KeyProperties}.{@code DIGEST} constants.
          */
         @NonNull
-        @FlaggedApi("MGF1_DIGEST_SETTER")
+        @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER)
         public Builder setMgf1Digests(@NonNull @KeyProperties.DigestEnum String... mgf1Digests) {
             mMgf1Digests = Set.of(mgf1Digests);
             return this;
diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java
index c1e3bab..7b6b2d1 100644
--- a/keystore/java/android/security/keystore/KeyProtection.java
+++ b/keystore/java/android/security/keystore/KeyProtection.java
@@ -401,7 +401,7 @@
      * @see #isMgf1DigestsSpecified()
      */
     @NonNull
-    @FlaggedApi("MGF1_DIGEST_SETTER")
+    @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER)
     public @KeyProperties.DigestEnum Set<String> getMgf1Digests() {
         if (mMgf1Digests.isEmpty()) {
             throw new IllegalStateException("Mask generation function (MGF) not specified");
@@ -416,7 +416,7 @@
      * @see #getMgf1Digests()
      */
     @NonNull
-    @FlaggedApi("MGF1_DIGEST_SETTER")
+    @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER)
     public boolean isMgf1DigestsSpecified() {
         return !mMgf1Digests.isEmpty();
     }
@@ -799,7 +799,7 @@
          * <p>See {@link KeyProperties}.{@code DIGEST} constants.
          */
         @NonNull
-        @FlaggedApi("MGF1_DIGEST_SETTER")
+        @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER)
         public Builder setMgf1Digests(@Nullable @KeyProperties.DigestEnum String... mgf1Digests) {
             mMgf1Digests = Set.of(mgf1Digests);
             return this;
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
index ed4b485..9c05a3a 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -28,6 +28,7 @@
 import android.hardware.security.keymint.Tag;
 import android.os.Build;
 import android.os.StrictMode;
+import android.security.Flags;
 import android.security.KeyPairGeneratorSpec;
 import android.security.KeyStore2;
 import android.security.KeyStoreException;
@@ -853,6 +854,22 @@
                             KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST, mgf1Digest
                     ));
                 });
+
+                /* If the MGF1 Digest setter is not set, fall back to the previous behaviour:
+                 * Add, as MGF1 Digest function, all the primary digests.
+                 * Avoid adding the default MGF1 digest as it will have been included in the
+                 * mKeymasterMgf1Digests field.
+                 */
+                if (!getMgf1DigestSetterFlag()) {
+                    final int defaultMgf1Digest = KeyProperties.Digest.toKeymaster(
+                            DEFAULT_MGF1_DIGEST);
+                    ArrayUtils.forEach(mKeymasterDigests, (digest) -> {
+                        if (digest != defaultMgf1Digest) {
+                            params.add(KeyStore2ParameterUtils.makeEnum(
+                                    KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST, digest));
+                        }
+                    });
+                }
             }
         });
         ArrayUtils.forEach(mKeymasterSignaturePaddings, (padding) -> {
@@ -928,6 +945,16 @@
         return params;
     }
 
+    private static boolean getMgf1DigestSetterFlag() {
+        try {
+            return Flags.mgf1DigestSetter();
+        } catch (SecurityException e) {
+            Log.w(TAG, "Cannot read MGF1 Digest setter flag value", e);
+            return false;
+        }
+    }
+
+
     private void addAlgorithmSpecificParameters(List<KeyParameter> params) {
         switch (mKeymasterAlgorithm) {
             case KeymasterDefs.KM_ALGORITHM_RSA:
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
index ddbd93e..2d8c5a3 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
@@ -25,6 +25,7 @@
 import android.hardware.security.keymint.KeyParameter;
 import android.hardware.security.keymint.SecurityLevel;
 import android.os.StrictMode;
+import android.security.Flags;
 import android.security.GateKeeper;
 import android.security.KeyStore2;
 import android.security.KeyStoreParameter;
@@ -256,6 +257,15 @@
         }
     }
 
+    private static boolean getMgf1DigestSetterFlag() {
+        try {
+            return Flags.mgf1DigestSetter();
+        } catch (SecurityException e) {
+            Log.w(NAME, "Cannot read MGF1 Digest setter flag value", e);
+            return false;
+        }
+    }
+
     @Override
     public Date engineGetCreationDate(String alias) {
         KeyEntryResponse response = getKeyMetadata(alias);
@@ -537,11 +547,31 @@
                         /* Because of default MGF1 digest is SHA-1. It has to be added in Key
                          * characteristics. Otherwise, crypto operations will fail with Incompatible
                          * MGF1 digest.
+                         * If the MGF1 Digest setter flag isn't set, then the condition in the
+                         * if clause above must be false (cannot have MGF1 digests specified if the
+                         * flag was off). In that case, in addition to adding the default MGF1
+                         * digest, we have to add all the other digests as MGF1 Digests.
+                         *
                          */
                         importArgs.add(KeyStore2ParameterUtils.makeEnum(
                                 KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST,
                                 KeyProperties.Digest.toKeymaster(DEFAULT_MGF1_DIGEST)
                         ));
+                        if (!getMgf1DigestSetterFlag()) {
+                            final int defaultMgf1Digest = KeyProperties.Digest.toKeymaster(
+                                    DEFAULT_MGF1_DIGEST);
+                            for (String digest : spec.getDigests()) {
+                                int digestToAddAsMgf1Digest = KeyProperties.Digest.toKeymaster(
+                                        digest);
+                                // Do not add the default MGF1 digest as it has been added above.
+                                if (digestToAddAsMgf1Digest != defaultMgf1Digest) {
+                                    importArgs.add(KeyStore2ParameterUtils.makeEnum(
+                                            KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST,
+                                            digestToAddAsMgf1Digest
+                                    ));
+                                }
+                            }
+                        }
                     }
                 }
             }
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
index 15d14e8..b315f94 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
@@ -241,7 +241,7 @@
         for (int i = 0; i < displays.length; i++) {
             DisplayAddress.Physical address =
                     (DisplayAddress.Physical) displays[i].getAddress();
-            if (mRearDisplayAddress == address.getPhysicalDisplayId()) {
+            if (address != null && mRearDisplayAddress == address.getPhysicalDisplayId()) {
                 rearDisplayMetrics = new DisplayMetrics();
                 final Display rearDisplay = displays[i];
 
diff --git a/libs/WindowManager/Shell/OWNERS b/libs/WindowManager/Shell/OWNERS
index f0ed6ee..e346b51 100644
--- a/libs/WindowManager/Shell/OWNERS
+++ b/libs/WindowManager/Shell/OWNERS
@@ -1,4 +1,4 @@
 xutan@google.com
 
 # Give submodule owners in shell resource approval
-per-file res*/*/*.xml = atsjenk@google.com, hwwang@google.com, jorgegil@google.com, lbill@google.com, madym@google.com
+per-file res*/*/*.xml = atsjenk@google.com, hwwang@google.com, jorgegil@google.com, lbill@google.com, madym@google.com, nmusgrave@google.com, pbdr@google.com, tkachenkoi@google.com
diff --git a/libs/WindowManager/Shell/res/drawable/desktop_mode_decor_title.xml b/libs/WindowManager/Shell/res/drawable/desktop_mode_decor_title.xml
deleted file mode 100644
index ef30060..0000000
--- a/libs/WindowManager/Shell/res/drawable/desktop_mode_decor_title.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2022 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<shape android:shape="rectangle"
-       android:tintMode="multiply"
-       android:tint="@color/decor_title_color"
-       xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@android:color/white" />
-</shape>
diff --git a/libs/WindowManager/Shell/res/layout/desktop_mode_app_controls_window_decor.xml b/libs/WindowManager/Shell/res/layout/desktop_mode_app_controls_window_decor.xml
index c525a29..85bf2c1 100644
--- a/libs/WindowManager/Shell/res/layout/desktop_mode_app_controls_window_decor.xml
+++ b/libs/WindowManager/Shell/res/layout/desktop_mode_app_controls_window_decor.xml
@@ -21,8 +21,7 @@
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:gravity="center_horizontal"
-    android:orientation="horizontal"
-    android:background="@drawable/desktop_mode_decor_title">
+    android:orientation="horizontal">
 
     <LinearLayout
         android:id="@+id/open_menu_button"
@@ -45,7 +44,6 @@
             android:layout_width="0dp"
             android:layout_height="20dp"
             android:minWidth="80dp"
-            android:textColor="@color/desktop_mode_caption_app_name_dark"
             android:textAppearance="@android:style/TextAppearance.Material.Title"
             android:textSize="14sp"
             android:textFontWeight="500"
@@ -62,7 +60,6 @@
             android:layout_height="16dp"
             android:contentDescription="@string/expand_menu_text"
             android:src="@drawable/ic_baseline_expand_more_24"
-            android:tint="@color/desktop_mode_caption_expand_button_dark"
             android:background="@null"
             android:scaleType="fitCenter"
             android:clickable="false"
@@ -87,8 +84,7 @@
         android:src="@drawable/decor_desktop_mode_maximize_button_dark"
         android:scaleType="fitCenter"
         android:gravity="end"
-        android:background="@null"
-        android:tint="@color/desktop_mode_caption_maximize_button_dark"/>
+        android:background="@null"/>
 
     <ImageButton
         android:id="@+id/close_window"
@@ -100,6 +96,5 @@
         android:src="@drawable/decor_close_button_dark"
         android:scaleType="fitCenter"
         android:gravity="end"
-        android:background="@null"
-        android:tint="@color/desktop_mode_caption_close_button_dark"/>
+        android:background="@null"/>
 </com.android.wm.shell.windowdecor.WindowDecorLinearLayout>
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/layout/desktop_mode_focused_window_decor.xml b/libs/WindowManager/Shell/res/layout/desktop_mode_focused_window_decor.xml
index 7638132..cec7ee2 100644
--- a/libs/WindowManager/Shell/res/layout/desktop_mode_focused_window_decor.xml
+++ b/libs/WindowManager/Shell/res/layout/desktop_mode_focused_window_decor.xml
@@ -20,8 +20,7 @@
     android:id="@+id/desktop_mode_caption"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:gravity="center_horizontal"
-    android:background="@drawable/desktop_mode_decor_title">
+    android:gravity="center_horizontal">
 
     <ImageButton
         android:id="@+id/caption_handle"
@@ -33,5 +32,4 @@
         tools:tint="@color/desktop_mode_caption_handle_bar_dark"
         android:scaleType="fitXY"
         android:background="?android:selectableItemBackground"/>
-
 </com.android.wm.shell.windowdecor.WindowDecorLinearLayout>
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/values/colors.xml b/libs/WindowManager/Shell/res/values/colors.xml
index 9bfd1b4..fae71ef 100644
--- a/libs/WindowManager/Shell/res/values/colors.xml
+++ b/libs/WindowManager/Shell/res/values/colors.xml
@@ -60,14 +60,6 @@
     <!-- Desktop Mode -->
     <color name="desktop_mode_caption_handle_bar_light">#EFF1F2</color>
     <color name="desktop_mode_caption_handle_bar_dark">#1C1C17</color>
-    <color name="desktop_mode_caption_expand_button_light">#EFF1F2</color>
-    <color name="desktop_mode_caption_expand_button_dark">#48473A</color>
-    <color name="desktop_mode_caption_close_button_light">#EFF1F2</color>
-    <color name="desktop_mode_caption_close_button_dark">#1C1C17</color>
-    <color name="desktop_mode_caption_maximize_button_light">#EFF1F2</color>
-    <color name="desktop_mode_caption_maximize_button_dark">#1C1C17</color>
-    <color name="desktop_mode_caption_app_name_light">#EFF1F2</color>
-    <color name="desktop_mode_caption_app_name_dark">#1C1C17</color>
     <color name="desktop_mode_resize_veil_light">#EFF1F2</color>
     <color name="desktop_mode_resize_veil_dark">#1C1C17</color>
     <color name="desktop_mode_maximize_menu_button">#DDDACD</color>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index b1b196d..fe65fdd 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -16,6 +16,7 @@
 
 package com.android.wm.shell;
 
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
@@ -168,6 +169,13 @@
     private final Object mLock = new Object();
     private StartingWindowController mStartingWindow;
 
+    /** Overlay surface for home root task */
+    private final SurfaceControl mHomeTaskOverlayContainer = new SurfaceControl.Builder()
+            .setName("home_task_overlay_container")
+            .setContainerLayer()
+            .setHidden(false)
+            .build();
+
     /**
      * In charge of showing compat UI. Can be {@code null} if the device doesn't support size
      * compat or if this isn't the main {@link ShellTaskOrganizer}.
@@ -428,6 +436,14 @@
         }
     }
 
+    /**
+     * Returns a surface which can be used to attach overlays to the home root task
+     */
+    @NonNull
+    public SurfaceControl getHomeTaskOverlayContainer() {
+        return mHomeTaskOverlayContainer;
+    }
+
     @Override
     public void addStartingWindow(StartingWindowInfo info) {
         if (mStartingWindow != null) {
@@ -485,6 +501,15 @@
         if (mUnfoldAnimationController != null) {
             mUnfoldAnimationController.onTaskAppeared(info.getTaskInfo(), info.getLeash());
         }
+
+        if (info.getTaskInfo().getActivityType() == ACTIVITY_TYPE_HOME) {
+            ProtoLog.v(WM_SHELL_TASK_ORG, "Adding overlay to home task");
+            final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+            t.setLayer(mHomeTaskOverlayContainer, Integer.MAX_VALUE);
+            t.reparent(mHomeTaskOverlayContainer, info.getLeash());
+            t.apply();
+        }
+
         notifyLocusVisibilityIfNeeded(info.getTaskInfo());
         notifyCompatUI(info.getTaskInfo(), listener);
         mRecentTasks.ifPresent(recentTasks -> recentTasks.onTaskAdded(info.getTaskInfo()));
@@ -579,6 +604,12 @@
             notifyCompatUI(taskInfo, null /* taskListener */);
             // Notify the recent tasks that a task has been removed
             mRecentTasks.ifPresent(recentTasks -> recentTasks.onTaskRemoved(taskInfo));
+            if (taskInfo.getActivityType() == ACTIVITY_TYPE_HOME) {
+                SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+                t.reparent(mHomeTaskOverlayContainer, null);
+                t.apply();
+                ProtoLog.v(WM_SHELL_TASK_ORG, "Removing overlay surface");
+            }
 
             if (!ENABLE_SHELL_TRANSITIONS && (appearedInfo.getLeash() != null)) {
                 // Preemptively clean up the leash only if shell transitions are not enabled
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java
index c980906..8d8dc10 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java
@@ -49,6 +49,11 @@
             @BackEvent.SwipeEdge int swipeEdge);
 
     /**
+     * Called when the input pointers are pilfered.
+     */
+    void onPilferPointers();
+
+    /**
      * Sets whether the back gesture is past the trigger threshold or not.
      */
     void setTriggerBack(boolean triggerBack);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
index 5843635..d8c691b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
@@ -17,6 +17,7 @@
 package com.android.wm.shell.back;
 
 import static com.android.internal.jank.InteractionJankMonitor.CUJ_PREDICTIVE_BACK_HOME;
+import static com.android.window.flags.Flags.predictiveBackSystemAnimations;
 import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
 import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_BACK_PREVIEW;
 import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_BACK_ANIMATION;
@@ -110,6 +111,7 @@
 
     /** Tracks if we should start the back gesture on the next motion move event */
     private boolean mShouldStartOnNextMoveEvent = false;
+    private boolean mOnBackStartDispatched = false;
 
     private final FlingAnimationUtils mFlingAnimationUtils;
 
@@ -221,6 +223,7 @@
 
     private void onInit() {
         setupAnimationDeveloperSettingsObserver(mContentResolver, mBgHandler);
+        updateEnableAnimationFromFlags();
         createAdapter();
         mShellController.addExternalInterface(KEY_EXTRA_SHELL_BACK_ANIMATION,
                 this::createExternalInterface, this);
@@ -229,28 +232,39 @@
     private void setupAnimationDeveloperSettingsObserver(
             @NonNull ContentResolver contentResolver,
             @NonNull @ShellBackgroundThread final Handler backgroundHandler) {
+        if (predictiveBackSystemAnimations()) {
+            ProtoLog.d(WM_SHELL_BACK_PREVIEW, "Back animation aconfig flag is enabled, therefore "
+                    + "developer settings flag is ignored and no content observer registered");
+            return;
+        }
         ContentObserver settingsObserver = new ContentObserver(backgroundHandler) {
             @Override
             public void onChange(boolean selfChange, Uri uri) {
-                updateEnableAnimationFromSetting();
+                updateEnableAnimationFromFlags();
             }
         };
         contentResolver.registerContentObserver(
                 Global.getUriFor(Global.ENABLE_BACK_ANIMATION),
                 false, settingsObserver, UserHandle.USER_SYSTEM
         );
-        updateEnableAnimationFromSetting();
     }
 
+    /**
+     * Updates {@link BackAnimationController#mEnableAnimations} based on the current values of the
+     * aconfig flag and the developer settings flag
+     */
     @ShellBackgroundThread
-    private void updateEnableAnimationFromSetting() {
-        int settingValue = Global.getInt(mContext.getContentResolver(),
-                Global.ENABLE_BACK_ANIMATION, SETTING_VALUE_OFF);
-        boolean isEnabled = settingValue == SETTING_VALUE_ON;
+    private void updateEnableAnimationFromFlags() {
+        boolean isEnabled = predictiveBackSystemAnimations() || isDeveloperSettingEnabled();
         mEnableAnimations.set(isEnabled);
         ProtoLog.d(WM_SHELL_BACK_PREVIEW, "Back animation enabled=%s", isEnabled);
     }
 
+    private boolean isDeveloperSettingEnabled() {
+        return Global.getInt(mContext.getContentResolver(),
+                Global.ENABLE_BACK_ANIMATION, SETTING_VALUE_OFF) == SETTING_VALUE_ON;
+    }
+
     public BackAnimation getBackAnimationImpl() {
         return mBackAnimation;
     }
@@ -291,6 +305,11 @@
         }
 
         @Override
+        public void onPilferPointers() {
+            BackAnimationController.this.onPilferPointers();
+        }
+
+        @Override
         public void setTriggerBack(boolean triggerBack) {
             mShellExecutor.execute(() -> BackAnimationController.this.setTriggerBack(triggerBack));
         }
@@ -371,6 +390,16 @@
         return null;
     }
 
+    @VisibleForTesting
+    void onPilferPointers() {
+        mCurrentTracker.updateStartLocation();
+        // Dispatch onBackStarted, only to app callbacks.
+        // System callbacks will receive onBackStarted when the remote animation starts.
+        if (!shouldDispatchToAnimator()) {
+            tryDispatchOnBackStarted(mActiveCallback, mCurrentTracker.createStartEvent(null));
+        }
+    }
+
     /**
      * Called when a new motion event needs to be transferred to this
      * {@link BackAnimationController}
@@ -470,12 +499,15 @@
             mActiveCallback = mBackNavigationInfo.getOnBackInvokedCallback();
             // App is handling back animation. Cancel system animation latency tracking.
             cancelLatencyTracking();
-            dispatchOnBackStarted(mActiveCallback, touchTracker.createStartEvent(null));
+            tryDispatchOnBackStarted(mActiveCallback, touchTracker.createStartEvent(null));
         }
     }
 
     private void onMove() {
-        if (!mBackGestureStarted || mBackNavigationInfo == null || mActiveCallback == null) {
+        if (!mBackGestureStarted
+                || mBackNavigationInfo == null
+                || mActiveCallback == null
+                || !mOnBackStartDispatched) {
             return;
         }
         // Skip dispatching if the move corresponds to the queued instead of the current gesture
@@ -511,13 +543,14 @@
                 && mBackNavigationInfo.isPrepareRemoteAnimation();
     }
 
-    private void dispatchOnBackStarted(IOnBackInvokedCallback callback,
+    private void tryDispatchOnBackStarted(IOnBackInvokedCallback callback,
             BackMotionEvent backEvent) {
-        if (callback == null) {
+        if (callback == null || mOnBackStartDispatched) {
             return;
         }
         try {
             callback.onBackStarted(backEvent);
+            mOnBackStartDispatched = true;
         } catch (RemoteException e) {
             Log.e(TAG, "dispatchOnBackStarted error: ", e);
         }
@@ -815,6 +848,8 @@
     void finishBackNavigation(boolean triggerBack) {
         ProtoLog.d(WM_SHELL_BACK_PREVIEW, "BackAnimationController: finishBackNavigation()");
         mActiveCallback = null;
+        mShouldStartOnNextMoveEvent = false;
+        mOnBackStartDispatched = false;
         mShellBackAnimationRegistry.resetDefaultCrossActivity();
         cancelLatencyTracking();
         if (mBackNavigationInfo != null) {
@@ -896,7 +931,8 @@
                                                                     ::onBackAnimationFinished));
 
                                     if (apps.length >= 1) {
-                                        dispatchOnBackStarted(
+                                        mCurrentTracker.updateStartLocation();
+                                        tryDispatchOnBackStarted(
                                                 mActiveCallback,
                                                 mCurrentTracker.createStartEvent(apps[0]));
                                     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java
index dc413b0..a32b435 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java
@@ -28,7 +28,7 @@
 import android.window.IBackAnimationRunner;
 import android.window.IOnBackInvokedCallback;
 
-import com.android.internal.jank.InteractionJankMonitor;
+import com.android.internal.jank.Cuj.CujType;
 import com.android.wm.shell.common.InteractionJankMonitorUtils;
 
 /**
@@ -42,7 +42,7 @@
 
     private final IOnBackInvokedCallback mCallback;
     private final IRemoteAnimationRunner mRunner;
-    private final @InteractionJankMonitor.CujType int mCujType;
+    private final @CujType int mCujType;
     private final Context mContext;
 
     // Whether we are waiting to receive onAnimationStart
@@ -55,7 +55,7 @@
             @NonNull IOnBackInvokedCallback callback,
             @NonNull IRemoteAnimationRunner runner,
             @NonNull Context context,
-            @InteractionJankMonitor.CujType int cujType) {
+            @CujType int cujType) {
         mCallback = callback;
         mRunner = runner;
         mCujType = cujType;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/TouchTracker.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/TouchTracker.java
index 19eb928..4bd56d4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/TouchTracker.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/TouchTracker.java
@@ -104,6 +104,15 @@
         mStartThresholdX = mInitTouchX;
     }
 
+    /** Update the start location used to compute the progress
+     * to the latest touch location.
+     */
+    void updateStartLocation() {
+        mInitTouchX = mLatestTouchX;
+        mInitTouchY = mLatestTouchY;
+        mStartThresholdX = mInitTouchX;
+    }
+
     void reset() {
         mInitTouchX = 0;
         mInitTouchY = 0;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
index 85ea809..7a3210e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
@@ -637,7 +637,7 @@
      * @return the last time this bubble was updated or accessed, whichever is most recent.
      */
     long getLastActivity() {
-        return isAppBubble() ? Long.MAX_VALUE : Math.max(mLastUpdated, mLastAccessed);
+        return Math.max(mLastUpdated, mLastAccessed);
     }
 
     /**
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 249f52b..896bcaf 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
@@ -1481,6 +1481,36 @@
         }
     }
 
+    // TODO(b/316358859): remove this method after task views are shared across modes
+    /**
+     * Removes the bubble with the given key after task removal, unless the task was removed as
+     * a result of mode switching, in which case, the bubble isn't removed because it will be
+     * re-inflated for the new mode.
+     */
+    @MainThread
+    public void removeFloatingBubbleAfterTaskRemoval(String key, int reason) {
+        // if we're floating remove the bubble. otherwise, we're here because the task was removed
+        // after switching modes. See b/316358859
+        if (!isShowingAsBubbleBar()) {
+            removeBubble(key, reason);
+        }
+    }
+
+    // TODO(b/316358859): remove this method after task views are shared across modes
+    /**
+     * Removes the bubble with the given key after task removal, unless the task was removed as
+     * a result of mode switching, in which case, the bubble isn't removed because it will be
+     * re-inflated for the new mode.
+     */
+    @MainThread
+    public void removeBarBubbleAfterTaskRemoval(String key, int reason) {
+        // if we're showing as bubble bar remove the bubble. otherwise, we're here because the task
+        // was removed after switching modes. See b/316358859
+        if (isShowingAsBubbleBar()) {
+            removeBubble(key, reason);
+        }
+    }
+
     /**
      * Removes all the bubbles.
      * <p>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
index 595a4af..bbb4b74 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
@@ -784,8 +784,7 @@
         if (bubble.getPendingIntentCanceled()
                 || !(reason == Bubbles.DISMISS_AGED
                 || reason == Bubbles.DISMISS_USER_GESTURE
-                || reason == Bubbles.DISMISS_RELOAD_FROM_DISK)
-                || bubble.isAppBubble()) {
+                || reason == Bubbles.DISMISS_RELOAD_FROM_DISK)) {
             return;
         }
         if (DEBUG_BUBBLE_DATA) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
index a3eb429..f3fe895 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
@@ -313,7 +313,8 @@
                         + " bubble=" + getBubbleKey());
             }
             if (mBubble != null) {
-                mController.removeBubble(mBubble.getKey(), Bubbles.DISMISS_TASK_FINISHED);
+                mController.removeFloatingBubbleAfterTaskRemoval(
+                        mBubble.getKey(), Bubbles.DISMISS_TASK_FINISHED);
             }
             if (mTaskView != null) {
                 // Release the surface
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewHelper.java
index da4a989..f6c382f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewHelper.java
@@ -188,7 +188,8 @@
                         + " bubble=" + getBubbleKey());
             }
             if (mBubble != null) {
-                mController.removeBubble(mBubble.getKey(), Bubbles.DISMISS_TASK_FINISHED);
+                mController.removeBarBubbleAfterTaskRemoval(
+                        mBubble.getKey(), Bubbles.DISMISS_TASK_FINISHED);
             }
         }
 
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 689323b..7f34ee0 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
@@ -78,34 +78,37 @@
         mExpandedViewAlphaAnimator.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationStart(Animator animation) {
-                if (mExpandedBubble != null && mExpandedBubble.getBubbleBarExpandedView() != null) {
+                BubbleBarExpandedView bbev = getExpandedView();
+                if (bbev != null) {
                     // We need to be Z ordered on top in order for alpha animations to work.
-                    mExpandedBubble.getBubbleBarExpandedView().setSurfaceZOrderedOnTop(true);
-                    mExpandedBubble.getBubbleBarExpandedView().setAnimating(true);
+                    bbev.setSurfaceZOrderedOnTop(true);
+                    bbev.setAnimating(true);
                 }
             }
 
             @Override
             public void onAnimationEnd(Animator animation) {
-                if (mExpandedBubble != null && mExpandedBubble.getBubbleBarExpandedView() != null) {
+                BubbleBarExpandedView bbev = getExpandedView();
+                if (bbev != null) {
                     // The surface needs to be Z ordered on top for alpha values to work on the
                     // TaskView, and if we're temporarily hidden, we are still on the screen
                     // with alpha = 0f until we animate back. Stay Z ordered on top so the alpha
                     // = 0f remains in effect.
                     if (mIsExpanded) {
-                        mExpandedBubble.getBubbleBarExpandedView().setSurfaceZOrderedOnTop(false);
+                        bbev.setSurfaceZOrderedOnTop(false);
                     }
 
-                    mExpandedBubble.getBubbleBarExpandedView().setContentVisibility(mIsExpanded);
-                    mExpandedBubble.getBubbleBarExpandedView().setAnimating(false);
+                    bbev.setContentVisibility(mIsExpanded);
+                    bbev.setAnimating(false);
                 }
             }
         });
         mExpandedViewAlphaAnimator.addUpdateListener(valueAnimator -> {
-            if (mExpandedBubble != null && mExpandedBubble.getBubbleBarExpandedView() != null) {
+            BubbleBarExpandedView bbev = getExpandedView();
+            if (bbev != null) {
                 float alpha = (float) valueAnimator.getAnimatedValue();
-                mExpandedBubble.getBubbleBarExpandedView().setTaskViewAlpha(alpha);
-                mExpandedBubble.getBubbleBarExpandedView().setAlpha(alpha);
+                bbev.setTaskViewAlpha(alpha);
+                bbev.setAlpha(alpha);
             }
         });
     }
@@ -116,11 +119,8 @@
     public void animateExpansion(BubbleViewProvider expandedBubble,
             @Nullable Runnable afterAnimation) {
         mExpandedBubble = expandedBubble;
-        if (mExpandedBubble == null) {
-            return;
-        }
-        BubbleBarExpandedView bev = mExpandedBubble.getBubbleBarExpandedView();
-        if (bev == null) {
+        final BubbleBarExpandedView bbev = getExpandedView();
+        if (bbev == null) {
             return;
         }
         mIsExpanded = true;
@@ -129,11 +129,11 @@
         mExpandedViewContainerMatrix.setScaleY(0f);
 
         updateExpandedView();
-        bev.setAnimating(true);
-        bev.setContentVisibility(false);
-        bev.setAlpha(0f);
-        bev.setTaskViewAlpha(0f);
-        bev.setVisibility(VISIBLE);
+        bbev.setAnimating(true);
+        bbev.setContentVisibility(false);
+        bbev.setAlpha(0f);
+        bbev.setTaskViewAlpha(0f);
+        bbev.setVisibility(VISIBLE);
 
         // Set the pivot point for the scale, so the view animates out from the bubble bar.
         Point bubbleBarPosition = mPositioner.getBubbleBarPosition();
@@ -143,7 +143,7 @@
                 bubbleBarPosition.x,
                 bubbleBarPosition.y);
 
-        bev.setAnimationMatrix(mExpandedViewContainerMatrix);
+        bbev.setAnimationMatrix(mExpandedViewContainerMatrix);
 
         mExpandedViewAlphaAnimator.start();
 
@@ -156,13 +156,12 @@
                         AnimatableScaleMatrix.getAnimatableValueForScaleFactor(1f),
                         mScaleInSpringConfig)
                 .addUpdateListener((target, values) -> {
-                    mExpandedBubble.getBubbleBarExpandedView().setAnimationMatrix(
-                            mExpandedViewContainerMatrix);
+                    bbev.setAnimationMatrix(mExpandedViewContainerMatrix);
                 })
                 .withEndActions(() -> {
-                    bev.setAnimationMatrix(null);
+                    bbev.setAnimationMatrix(null);
                     updateExpandedView();
-                    bev.setSurfaceZOrderedOnTop(false);
+                    bbev.setSurfaceZOrderedOnTop(false);
                     if (afterAnimation != null) {
                         afterAnimation.run();
                     }
@@ -177,7 +176,8 @@
      */
     public void animateCollapse(Runnable endRunnable) {
         mIsExpanded = false;
-        if (mExpandedBubble == null || mExpandedBubble.getBubbleBarExpandedView() == null) {
+        final BubbleBarExpandedView bbev = getExpandedView();
+        if (bbev == null) {
             Log.w(TAG, "Trying to animate collapse without a bubble");
             return;
         }
@@ -196,17 +196,10 @@
                                 EXPANDED_VIEW_ANIMATE_OUT_SCALE_AMOUNT),
                         mScaleOutSpringConfig)
                 .addUpdateListener((target, values) -> {
-                    if (mExpandedBubble != null
-                            && mExpandedBubble.getBubbleBarExpandedView() != null) {
-                        mExpandedBubble.getBubbleBarExpandedView().setAnimationMatrix(
-                                mExpandedViewContainerMatrix);
-                    }
+                    bbev.setAnimationMatrix(mExpandedViewContainerMatrix);
                 })
                 .withEndActions(() -> {
-                    if (mExpandedBubble != null
-                            && mExpandedBubble.getBubbleBarExpandedView() != null) {
-                        mExpandedBubble.getBubbleBarExpandedView().setAnimationMatrix(null);
-                    }
+                    bbev.setAnimationMatrix(null);
                     if (endRunnable != null) {
                         endRunnable.run();
                     }
@@ -223,12 +216,20 @@
         mExpandedViewAlphaAnimator.cancel();
     }
 
+    private @Nullable BubbleBarExpandedView getExpandedView() {
+        BubbleViewProvider bubble = mExpandedBubble;
+        if (bubble != null) {
+            return bubble.getBubbleBarExpandedView();
+        }
+        return null;
+    }
+
     private void updateExpandedView() {
-        if (mExpandedBubble == null || mExpandedBubble.getBubbleBarExpandedView() == null) {
+        BubbleBarExpandedView bbev = getExpandedView();
+        if (bbev == null) {
             Log.w(TAG, "Trying to update the expanded view without a bubble");
             return;
         }
-        BubbleBarExpandedView bbev = mExpandedBubble.getBubbleBarExpandedView();
 
         boolean isOverflowExpanded = mExpandedBubble.getKey().equals(BubbleOverflow.KEY);
         final int padding = mPositioner.getBubbleBarExpandedViewPadding();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/InteractionJankMonitorUtils.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/InteractionJankMonitorUtils.java
index ec344d3..86f00b8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/InteractionJankMonitorUtils.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/InteractionJankMonitorUtils.java
@@ -23,6 +23,7 @@
 import android.view.SurfaceControl;
 import android.view.View;
 
+import com.android.internal.jank.Cuj.CujType;
 import com.android.internal.jank.InteractionJankMonitor;
 
 /** Utils class for simplfy InteractionJank trancing call */
@@ -31,11 +32,11 @@
     /**
      * Begin a trace session.
      *
-     * @param cujType the specific {@link InteractionJankMonitor.CujType}.
+     * @param cujType the specific {@link CujType}.
      * @param view the view to trace
      * @param tag the tag to distinguish different flow of same type CUJ.
      */
-    public static void beginTracing(@InteractionJankMonitor.CujType int cujType,
+    public static void beginTracing(@CujType int cujType,
             @NonNull View view, @Nullable String tag) {
         final InteractionJankMonitor.Configuration.Builder builder =
                 InteractionJankMonitor.Configuration.Builder.withView(cujType, view);
@@ -48,12 +49,12 @@
     /**
      * Begin a trace session.
      *
-     * @param cujType the specific {@link InteractionJankMonitor.CujType}.
+     * @param cujType the specific {@link CujType}.
      * @param context the context
      * @param surface the surface to trace
      * @param tag the tag to distinguish different flow of same type CUJ.
      */
-    public static void beginTracing(@InteractionJankMonitor.CujType int cujType,
+    public static void beginTracing(@CujType int cujType,
             @NonNull Context context, @NonNull SurfaceControl surface, @Nullable String tag) {
         final InteractionJankMonitor.Configuration.Builder builder =
                 InteractionJankMonitor.Configuration.Builder.withSurface(cujType, context, surface);
@@ -66,18 +67,18 @@
     /**
      * End a trace session.
      *
-     * @param cujType the specific {@link InteractionJankMonitor.CujType}.
+     * @param cujType the specific {@link CujType}.
      */
-    public static void endTracing(@InteractionJankMonitor.CujType int cujType) {
+    public static void endTracing(@CujType int cujType) {
         InteractionJankMonitor.getInstance().end(cujType);
     }
 
     /**
      * Cancel the trace session.
      *
-     * @param cujType the specific {@link InteractionJankMonitor.CujType}.
+     * @param cujType the specific {@link CujType}.
      */
-    public static void cancelTracing(@InteractionJankMonitor.CujType int cujType) {
+    public static void cancelTracing(@CujType int cujType) {
         InteractionJankMonitor.getInstance().cancel(cujType);
     }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
index 0f0fbd9c..f801b0d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
@@ -83,6 +83,7 @@
     private int mStartPos;
     private GestureDetector mDoubleTapDetector;
     private boolean mInteractive;
+    private boolean mHideHandle;
     private boolean mSetTouchRegion = true;
     private int mLastDraggingPosition;
     private int mHandleRegionWidth;
@@ -211,11 +212,8 @@
     }
 
     /** Sets up essential dependencies of the divider bar. */
-    public void setup(
-            SplitLayout layout,
-            SplitWindowManager splitWindowManager,
-            SurfaceControlViewHost viewHost,
-            InsetsState insetsState) {
+    public void setup(SplitLayout layout, SplitWindowManager splitWindowManager,
+            SurfaceControlViewHost viewHost, InsetsState insetsState) {
         mSplitLayout = layout;
         mSplitWindowManager = splitWindowManager;
         mViewHost = viewHost;
@@ -277,6 +275,7 @@
                 R.dimen.docked_stack_divider_lift_elevation);
         mDoubleTapDetector = new GestureDetector(getContext(), new DoubleTapListener());
         mInteractive = true;
+        mHideHandle = false;
         setOnTouchListener(this);
         mHandle.setAccessibilityDelegate(mHandleDelegate);
         setWillNotDraw(false);
@@ -469,10 +468,11 @@
     void setInteractive(boolean interactive, boolean hideHandle, String from) {
         if (interactive == mInteractive) return;
         ProtoLog.d(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN,
-                "Set divider bar %s from %s", interactive ? "interactive" : "non-interactive",
-                from);
+                "Set divider bar %s hide handle=%b from %s",
+                interactive ? "interactive" : "non-interactive", hideHandle, from);
         mInteractive = interactive;
-        if (!mInteractive && hideHandle && mMoving) {
+        mHideHandle = hideHandle;
+        if (!mInteractive && mHideHandle && mMoving) {
             final int position = mSplitLayout.getDividePosition();
             mSplitLayout.flingDividePosition(
                     mLastDraggingPosition,
@@ -482,7 +482,15 @@
             mMoving = false;
         }
         releaseTouching();
-        mHandle.setVisibility(!mInteractive && hideHandle ? View.INVISIBLE : View.VISIBLE);
+        mHandle.setVisibility(!mInteractive && mHideHandle ? View.INVISIBLE : View.VISIBLE);
+    }
+
+    boolean isInteractive() {
+        return mInteractive;
+    }
+
+    boolean isHandleHidden() {
+        return mHideHandle;
     }
 
     private class DoubleTapListener extends GestureDetector.SimpleOnGestureListener {
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 b699533..53caddb 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
@@ -59,6 +59,7 @@
 import androidx.annotation.Nullable;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.protolog.common.ProtoLog;
 import com.android.wm.shell.R;
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.animation.Interpolators;
@@ -70,6 +71,7 @@
 import com.android.wm.shell.common.split.SplitScreenConstants.PersistentSnapPosition;
 import com.android.wm.shell.common.split.SplitScreenConstants.SnapPosition;
 import com.android.wm.shell.common.split.SplitScreenConstants.SplitPosition;
+import com.android.wm.shell.protolog.ShellProtoLogGroup;
 
 import java.io.PrintWriter;
 import java.util.function.Consumer;
@@ -420,7 +422,7 @@
     public void init() {
         if (mInitialized) return;
         mInitialized = true;
-        mSplitWindowManager.init(this, mInsetsState);
+        mSplitWindowManager.init(this, mInsetsState, false /* isRestoring */);
         mDisplayImeController.addPositionProcessor(mImePositionProcessor);
     }
 
@@ -442,14 +444,19 @@
     }
 
     /** Releases and re-inflates {@link DividerView} on the root surface. */
-    public void update(SurfaceControl.Transaction t) {
+    public void update(SurfaceControl.Transaction t, boolean resetImePosition) {
         if (!mInitialized) {
             init();
             return;
         }
         mSplitWindowManager.release(t);
-        mImePositionProcessor.reset();
-        mSplitWindowManager.init(this, mInsetsState);
+        if (resetImePosition) {
+            mImePositionProcessor.reset();
+        }
+        mSplitWindowManager.init(this, mInsetsState, true /* isRestoring */);
+        // Update the surface positions again after recreating the divider in case nothing else
+        // triggers it
+        mSplitLayoutHandler.onLayoutPositionChanging(SplitLayout.this);
     }
 
     @Override
@@ -868,6 +875,9 @@
         pw.println(prefix + TAG + ":");
         pw.println(innerPrefix + "mAllowLeftRightSplitInPortrait=" + mAllowLeftRightSplitInPortrait);
         pw.println(innerPrefix + "mIsLeftRightSplit=" + mIsLeftRightSplit);
+        pw.println(innerPrefix + "mFreezeDividerWindow=" + mFreezeDividerWindow);
+        pw.println(innerPrefix + "mDimNonImeSide=" + mDimNonImeSide);
+        pw.println(innerPrefix + "mDividerPosition=" + mDividerPosition);
         pw.println(innerPrefix + "bounds1=" + mBounds1.toShortString());
         pw.println(innerPrefix + "dividerBounds=" + mDividerBounds.toShortString());
         pw.println(innerPrefix + "bounds2=" + mBounds2.toShortString());
@@ -1151,14 +1161,16 @@
             mTargetYOffset = needOffset ? getTargetYOffset() : 0;
 
             if (mTargetYOffset != mLastYOffset) {
+                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN,
+                        "Split IME animation starting, fromY=%d toY=%d",
+                        mLastYOffset, mTargetYOffset);
                 // Freeze the configuration size with offset to prevent app get a configuration
                 // changed or relaunch. This is required to make sure client apps will calculate
                 // insets properly after layout shifted.
                 if (mTargetYOffset == 0) {
                     mSplitLayoutHandler.setLayoutOffsetTarget(0, 0, SplitLayout.this);
                 } else {
-                    mSplitLayoutHandler.setLayoutOffsetTarget(0, mTargetYOffset - mLastYOffset,
-                            SplitLayout.this);
+                    mSplitLayoutHandler.setLayoutOffsetTarget(0, mTargetYOffset, SplitLayout.this);
                 }
             }
 
@@ -1183,6 +1195,8 @@
         public void onImeEndPositioning(int displayId, boolean cancel,
                 SurfaceControl.Transaction t) {
             if (displayId != mDisplayId || !mHasImeFocus || cancel) return;
+            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN,
+                    "Split IME animation ending, canceled=%b", cancel);
             onProgress(1.0f);
             mSplitLayoutHandler.onLayoutPositionChanging(SplitLayout.this);
         }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
index 00361d9..8fb9bda 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
@@ -62,6 +62,10 @@
     // Used to "pass" a transaction to WWM.remove so that view removal can be synchronized.
     private SurfaceControl.Transaction mSyncTransaction = null;
 
+    // For saving/restoring state
+    private boolean mLastDividerInteractive = true;
+    private boolean mLastDividerHandleHidden;
+
     public interface ParentContainerCallbacks {
         void attachToParentSurface(SurfaceControl.Builder b);
         void onLeashReady(SurfaceControl leash);
@@ -107,7 +111,7 @@
     }
 
     /** Inflates {@link DividerView} on to the root surface. */
-    void init(SplitLayout splitLayout, InsetsState insetsState) {
+    void init(SplitLayout splitLayout, InsetsState insetsState, boolean isRestoring) {
         if (mDividerView != null || mViewHost != null) {
             throw new UnsupportedOperationException(
                     "Try to inflate divider view again without release first");
@@ -130,6 +134,10 @@
         lp.accessibilityTitle = mContext.getResources().getString(R.string.accessibility_divider);
         mViewHost.setView(mDividerView, lp);
         mDividerView.setup(splitLayout, this, mViewHost, insetsState);
+        if (isRestoring) {
+            mDividerView.setInteractive(mLastDividerInteractive, mLastDividerHandleHidden,
+                    "restore_setup");
+        }
     }
 
     /**
@@ -138,6 +146,8 @@
      */
     void release(@Nullable SurfaceControl.Transaction t) {
         if (mDividerView != null) {
+            mLastDividerInteractive = mDividerView.isInteractive();
+            mLastDividerHandleHidden = mDividerView.isHandleHidden();
             mDividerView = null;
         }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManager.java
index ef763ec..afd3b14 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManager.java
@@ -22,6 +22,7 @@
 import android.annotation.Nullable;
 import android.app.TaskInfo;
 import android.content.Context;
+import android.content.Intent;
 import android.graphics.Rect;
 import android.os.SystemClock;
 import android.view.LayoutInflater;
@@ -227,9 +228,12 @@
     }
 
     private boolean getHasUserAspectRatioSettingsButton(@NonNull TaskInfo taskInfo) {
+        final Intent intent = taskInfo.baseIntent;
         return taskInfo.appCompatTaskInfo.topActivityEligibleForUserAspectRatioButton
                 && (taskInfo.appCompatTaskInfo.topActivityBoundsLetterboxed
                     || taskInfo.appCompatTaskInfo.isUserFullscreenOverrideEnabled)
+                && Intent.ACTION_MAIN.equals(intent.getAction())
+                && intent.hasCategory(Intent.CATEGORY_LAUNCHER)
                 && (!mUserAspectRatioButtonShownChecker.get() || isShowingButton());
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/OWNERS
index deb7c6d..1385f42 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/OWNERS
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/OWNERS
@@ -1,3 +1,7 @@
 # WM shell sub-module desktop owners
 atsjenk@google.com
+jorgegil@google.com
 madym@google.com
+nmusgrave@google.com
+pbdr@google.com
+tkachenkoi@google.com
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/OWNERS
index a3803ed..8a0eea0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/OWNERS
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/OWNERS
@@ -2,3 +2,6 @@
 atsjenk@google.com
 jorgegil@google.com
 madym@google.com
+nmusgrave@google.com
+pbdr@google.com
+tkachenkoi@google.com
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
index 38ce164..d157ca8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
@@ -16,8 +16,8 @@
 
 package com.android.wm.shell.onehanded;
 
-import static com.android.internal.jank.InteractionJankMonitor.CUJ_ONE_HANDED_ENTER_TRANSITION;
-import static com.android.internal.jank.InteractionJankMonitor.CUJ_ONE_HANDED_EXIT_TRANSITION;
+import static com.android.internal.jank.Cuj.CUJ_ONE_HANDED_ENTER_TRANSITION;
+import static com.android.internal.jank.Cuj.CUJ_ONE_HANDED_EXIT_TRANSITION;
 import static com.android.wm.shell.onehanded.OneHandedAnimationController.TRANSITION_DIRECTION_EXIT;
 import static com.android.wm.shell.onehanded.OneHandedAnimationController.TRANSITION_DIRECTION_TRIGGER;
 
@@ -37,6 +37,7 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
+import com.android.internal.jank.Cuj.CujType;
 import com.android.internal.jank.InteractionJankMonitor;
 import com.android.wm.shell.R;
 import com.android.wm.shell.common.DisplayLayout;
@@ -327,7 +328,7 @@
         mTransitionCallbacks.add(callback);
     }
 
-    void beginCUJTracing(@InteractionJankMonitor.CujType int cujType, @Nullable String tag) {
+    void beginCUJTracing(@CujType int cujType, @Nullable String tag) {
         final Map.Entry<WindowContainerToken, SurfaceControl> firstEntry =
                 getDisplayAreaTokenMap().entrySet().iterator().next();
         final InteractionJankMonitor.Configuration.Builder builder =
@@ -339,11 +340,11 @@
         mJankMonitor.begin(builder);
     }
 
-    void endCUJTracing(@InteractionJankMonitor.CujType int cujType) {
+    void endCUJTracing(@CujType int cujType) {
         mJankMonitor.end(cujType);
     }
 
-    void cancelCUJTracing(@InteractionJankMonitor.CujType int cujType) {
+    void cancelCUJTracing(@CujType int cujType) {
         mJankMonitor.cancel(cujType);
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
index 8eb4a5a..4c47737 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
@@ -769,7 +769,7 @@
                         getSurfaceTransactionHelper().crop(tx, leash, destBounds);
                     }
                     if (mContentOverlay != null) {
-                        mContentOverlay.onAnimationEnd(tx, destBounds);
+                        clearContentOverlay();
                     }
                 }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipContentOverlay.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipContentOverlay.java
index 850b06a0..e11e859 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipContentOverlay.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipContentOverlay.java
@@ -67,15 +67,6 @@
     public abstract void onAnimationUpdate(SurfaceControl.Transaction atomicTx,
             Rect currentBounds, float fraction);
 
-    /**
-     * Callback when reaches the end of animation on the internal {@link #mLeash}.
-     * @param atomicTx {@link SurfaceControl.Transaction} to operate, you should not explicitly
-     *                 call apply on this transaction, it should be applied on the caller side.
-     * @param destinationBounds {@link Rect} of the final bounds.
-     */
-    public abstract void onAnimationEnd(SurfaceControl.Transaction atomicTx,
-            Rect destinationBounds);
-
     /** A {@link PipContentOverlay} uses solid color. */
     public static final class PipColorOverlay extends PipContentOverlay {
         private static final String TAG = PipColorOverlay.class.getSimpleName();
@@ -107,11 +98,6 @@
             atomicTx.setAlpha(mLeash, fraction < 0.5f ? 0 : (fraction - 0.5f) * 2);
         }
 
-        @Override
-        public void onAnimationEnd(SurfaceControl.Transaction atomicTx, Rect destinationBounds) {
-            // Do nothing. Color overlay should be fully opaque by now.
-        }
-
         private float[] getContentOverlayColor(Context context) {
             final TypedArray ta = context.obtainStyledAttributes(new int[] {
                     android.R.attr.colorBackground });
@@ -164,11 +150,6 @@
                 Rect currentBounds, float fraction) {
             // Do nothing. Keep the snapshot till animation ends.
         }
-
-        @Override
-        public void onAnimationEnd(SurfaceControl.Transaction atomicTx, Rect destinationBounds) {
-            atomicTx.remove(mLeash);
-        }
     }
 
     /** A {@link PipContentOverlay} shows app icon on solid color background. */
@@ -193,19 +174,12 @@
                     MAX_APP_ICON_SIZE_DP, context.getResources().getDisplayMetrics());
             mAppIconSizePx = Math.min(maxAppIconSizePx, appIconSizePx);
 
-            final int appWidth = appBounds.width();
-            final int appHeight = appBounds.height();
-
-            // In order to have the overlay always cover the pip window during the transition, the
-            // overlay will be drawn with the max size of the start and end bounds in different
-            // rotation.
-            final int overlaySize = Math.max(Math.max(appWidth, appHeight),
-                    Math.max(destinationBounds.width(), destinationBounds.height())) + 1;
+            final int overlaySize = getOverlaySize(appBounds, destinationBounds);
             mOverlayHalfSize = overlaySize >> 1;
 
             // When the activity is in the secondary split, make sure the scaling center is not
             // offset.
-            mAppBounds = new Rect(0, 0, appWidth, appHeight);
+            mAppBounds = new Rect(0, 0, appBounds.width(), appBounds.height());
 
             mBitmap = Bitmap.createBitmap(overlaySize, overlaySize, Bitmap.Config.ARGB_8888);
             prepareAppIconOverlay(appIcon);
@@ -215,6 +189,21 @@
                     .build();
         }
 
+        /**
+         * Returns the size of the app icon overlay.
+         *
+         * In order to have the overlay always cover the pip window during the transition,
+         * the overlay will be drawn with the max size of the start and end bounds in different
+         * rotation.
+         */
+        public static int getOverlaySize(Rect appBounds, Rect destinationBounds) {
+            final int appWidth = appBounds.width();
+            final int appHeight = appBounds.height();
+
+            return Math.max(Math.max(appWidth, appHeight),
+                    Math.max(destinationBounds.width(), destinationBounds.height())) + 1;
+        }
+
         @Override
         public void attach(SurfaceControl.Transaction tx, SurfaceControl parentLeash) {
             tx.show(mLeash);
@@ -247,11 +236,6 @@
         }
 
         @Override
-        public void onAnimationEnd(SurfaceControl.Transaction atomicTx, Rect destinationBounds) {
-            atomicTx.remove(mLeash);
-        }
-
-        @Override
         public void detach(SurfaceControl.Transaction tx) {
             super.detach(tx);
             if (mBitmap != null && !mBitmap.isRecycled()) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index c1164fc..3635165 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -156,74 +156,77 @@
     // These callbacks are called on the update thread
     private final PipAnimationController.PipAnimationCallback mPipAnimationCallback =
             new PipAnimationController.PipAnimationCallback() {
-        private boolean mIsCancelled;
-        @Override
-        public void onPipAnimationStart(TaskInfo taskInfo,
-                PipAnimationController.PipTransitionAnimator animator) {
-            final int direction = animator.getTransitionDirection();
-            mIsCancelled = false;
-            sendOnPipTransitionStarted(direction);
-        }
+                private boolean mIsCancelled;
 
-        @Override
-        public void onPipAnimationEnd(TaskInfo taskInfo, SurfaceControl.Transaction tx,
-                PipAnimationController.PipTransitionAnimator animator) {
-            final int direction = animator.getTransitionDirection();
-            if (mIsCancelled) {
-                sendOnPipTransitionFinished(direction);
-                maybePerformFinishResizeCallback();
-                return;
-            }
-            final int animationType = animator.getAnimationType();
-            final Rect destinationBounds = animator.getDestinationBounds();
-            if (isInPipDirection(direction) && animator.getContentOverlayLeash() != null) {
-                fadeOutAndRemoveOverlay(animator.getContentOverlayLeash(),
-                        animator::clearContentOverlay, true /* withStartDelay*/);
-            }
-            if (mWaitForFixedRotation && animationType == ANIM_TYPE_BOUNDS
-                    && direction == TRANSITION_DIRECTION_TO_PIP) {
-                // Notify the display to continue the deferred orientation change.
-                final WindowContainerTransaction wct = new WindowContainerTransaction();
-                wct.scheduleFinishEnterPip(mToken, destinationBounds);
-                mTaskOrganizer.applyTransaction(wct);
-                // The final task bounds will be applied by onFixedRotationFinished so that all
-                // coordinates are in new rotation.
-                mSurfaceTransactionHelper.round(tx, mLeash, isInPip());
-                mDeferredAnimEndTransaction = tx;
-                return;
-            }
-            final boolean isExitPipDirection = isOutPipDirection(direction)
-                    || isRemovePipDirection(direction);
-            if (mPipTransitionState.getTransitionState() != PipTransitionState.EXITING_PIP
-                    || isExitPipDirection) {
-                // execute the finish resize callback if needed after the transaction is committed
-                tx.addTransactionCommittedListener(mMainExecutor,
-                        PipTaskOrganizer.this::maybePerformFinishResizeCallback);
+                @Override
+                public void onPipAnimationStart(TaskInfo taskInfo,
+                        PipAnimationController.PipTransitionAnimator animator) {
+                    final int direction = animator.getTransitionDirection();
+                    mIsCancelled = false;
+                    sendOnPipTransitionStarted(direction);
+                }
 
-                // Finish resize as long as we're not exiting PIP, or, if we are, only if this is
-                // the end of an exit PIP animation.
-                // This is necessary in case there was a resize animation ongoing when exit PIP
-                // started, in which case the first resize will be skipped to let the exit
-                // operation handle the final resize out of PIP mode. See b/185306679.
-                finishResizeDelayedIfNeeded(() -> {
-                    finishResize(tx, destinationBounds, direction, animationType);
-                    sendOnPipTransitionFinished(direction);
-                });
-            }
-        }
+                @Override
+                public void onPipAnimationEnd(TaskInfo taskInfo, SurfaceControl.Transaction tx,
+                        PipAnimationController.PipTransitionAnimator animator) {
+                    final int direction = animator.getTransitionDirection();
+                    if (mIsCancelled) {
+                        sendOnPipTransitionFinished(direction);
+                        maybePerformFinishResizeCallback();
+                        return;
+                    }
+                    final int animationType = animator.getAnimationType();
+                    final Rect destinationBounds = animator.getDestinationBounds();
+                    if (isInPipDirection(direction) && mPipOverlay != null) {
+                        fadeOutAndRemoveOverlay(mPipOverlay,
+                                null /* callback */, true /* withStartDelay*/);
+                    }
+                    if (mWaitForFixedRotation && animationType == ANIM_TYPE_BOUNDS
+                            && direction == TRANSITION_DIRECTION_TO_PIP) {
+                        // Notify the display to continue the deferred orientation change.
+                        final WindowContainerTransaction wct = new WindowContainerTransaction();
+                        wct.scheduleFinishEnterPip(mToken, destinationBounds);
+                        mTaskOrganizer.applyTransaction(wct);
+                        // The final task bounds will be applied by onFixedRotationFinished so
+                        // that all coordinates are in new rotation.
+                        mSurfaceTransactionHelper.round(tx, mLeash, isInPip());
+                        mDeferredAnimEndTransaction = tx;
+                        return;
+                    }
+                    final boolean isExitPipDirection = isOutPipDirection(direction)
+                            || isRemovePipDirection(direction);
+                    if (mPipTransitionState.getTransitionState() != PipTransitionState.EXITING_PIP
+                            || isExitPipDirection) {
+                        // execute the finish resize callback if needed after the transaction is
+                        // committed
+                        tx.addTransactionCommittedListener(mMainExecutor,
+                                PipTaskOrganizer.this::maybePerformFinishResizeCallback);
 
-        @Override
-        public void onPipAnimationCancel(TaskInfo taskInfo,
-                PipAnimationController.PipTransitionAnimator animator) {
-            final int direction = animator.getTransitionDirection();
-            mIsCancelled = true;
-            if (isInPipDirection(direction) && animator.getContentOverlayLeash() != null) {
-                fadeOutAndRemoveOverlay(animator.getContentOverlayLeash(),
-                        animator::clearContentOverlay, true /* withStartDelay */);
-            }
-            sendOnPipTransitionCancelled(direction);
-        }
-    };
+                        // Finish resize as long as we're not exiting PIP, or, if we are, only if
+                        // this is the end of an exit PIP animation.
+                        // This is necessary in case there was a resize animation ongoing when
+                        // exit PIP started, in which case the first resize will be skipped to
+                        // let the exit operation handle the final resize out of PIP mode.
+                        // See b/185306679.
+                        finishResizeDelayedIfNeeded(() -> {
+                            finishResize(tx, destinationBounds, direction, animationType);
+                            sendOnPipTransitionFinished(direction);
+                        });
+                    }
+                }
+
+                @Override
+                public void onPipAnimationCancel(TaskInfo taskInfo,
+                        PipAnimationController.PipTransitionAnimator animator) {
+                    final int direction = animator.getTransitionDirection();
+                    mIsCancelled = true;
+                    if (isInPipDirection(direction) && mPipOverlay != null) {
+                        fadeOutAndRemoveOverlay(mPipOverlay,
+                                null /* callback */, true /* withStartDelay */);
+                    }
+                    sendOnPipTransitionCancelled(direction);
+                }
+            };
 
     /**
      * Finishes resizing the PiP, delaying the operation if it has to be synced with the PiP menu.
@@ -326,11 +329,10 @@
     private @Surface.Rotation int mCurrentRotation;
 
     /**
-     * An optional overlay used to mask content changing between an app in/out of PiP, only set if
-     * {@link PipTransitionState#getInSwipePipToHomeTransition()} is true.
+     * An optional overlay used to mask content changing between an app in/out of PiP.
      */
     @Nullable
-    SurfaceControl mSwipePipToHomeOverlay;
+    SurfaceControl mPipOverlay;
 
     public PipTaskOrganizer(Context context,
             @NonNull SyncTransactionQueue syncTransactionQueue,
@@ -470,7 +472,7 @@
             return;
         }
         mPipBoundsState.setBounds(destinationBounds);
-        mSwipePipToHomeOverlay = overlay;
+        mPipOverlay = overlay;
         if (ENABLE_SHELL_TRANSITIONS && overlay != null) {
             // With Shell transition, the overlay was attached to the remote transition leash, which
             // will be removed when the current transition is finished, so we need to reparent it
@@ -882,7 +884,7 @@
         }
 
         final Rect destinationBounds = mPipBoundsState.getBounds();
-        final SurfaceControl swipeToHomeOverlay = mSwipePipToHomeOverlay;
+        final SurfaceControl swipeToHomeOverlay = mPipOverlay;
         final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
         mSurfaceTransactionHelper
                 .resetScale(tx, mLeash, destinationBounds)
@@ -901,7 +903,7 @@
             }
         }, tx);
         mPipTransitionState.setInSwipePipToHomeTransition(false);
-        mSwipePipToHomeOverlay = null;
+        mPipOverlay = null;
     }
 
     private void applyEnterPipSyncTransaction(Rect destinationBounds, Runnable runnable,
@@ -1116,9 +1118,9 @@
         }
 
         clearWaitForFixedRotation();
-        if (mSwipePipToHomeOverlay != null) {
-            removeContentOverlay(mSwipePipToHomeOverlay, null /* callback */);
-            mSwipePipToHomeOverlay = null;
+        if (mPipOverlay != null) {
+            removeContentOverlay(mPipOverlay, null /* callback */);
+            mPipOverlay = null;
         }
         resetShadowRadius();
         mPipTransitionState.setInSwipePipToHomeTransition(false);
@@ -1766,6 +1768,7 @@
                     animator.setSnapshotContentOverlay(snapshot, sourceHintRect);
                 }
             }
+            mPipOverlay = animator.getContentOverlayLeash();
             // The destination bounds are used for the end rect of animation and the final bounds
             // after animation finishes. So after the animation is started, the destination bounds
             // can be updated to new rotation (computeRotatedBounds has changed the DisplayLayout
@@ -1879,6 +1882,14 @@
     }
 
     private void removeContentOverlay(SurfaceControl surface, Runnable callback) {
+        if (mPipOverlay != null) {
+            if (mPipOverlay != surface) {
+                ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                        "%s: trying to remove overlay (%s) which is not local reference (%s)",
+                        TAG, surface, mPipOverlay);
+            }
+            mPipOverlay = null;
+        }
         if (mPipTransitionState.getTransitionState() == PipTransitionState.UNDEFINED) {
             // Avoid double removal, which is fatal.
             return;
@@ -1907,11 +1918,11 @@
     private void cancelCurrentAnimator() {
         final PipAnimationController.PipTransitionAnimator<?> animator =
                 mPipAnimationController.getCurrentAnimator();
+        // remove any overlays if present
+        if (mPipOverlay != null) {
+            removeContentOverlay(mPipOverlay, null /* callback */);
+        }
         if (animator != null) {
-            if (animator.getContentOverlayLeash() != null) {
-                removeContentOverlay(animator.getContentOverlayLeash(),
-                        animator::clearContentOverlay);
-            }
             PipAnimationController.quietCancel(animator);
             mPipAnimationController.resetAnimatorState();
         }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
index fe4980a..f5f15d8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
@@ -43,6 +43,7 @@
 import static com.android.wm.shell.transition.Transitions.TRANSIT_REMOVE_PIP;
 
 import android.animation.Animator;
+import android.annotation.IntDef;
 import android.app.ActivityManager;
 import android.app.TaskInfo;
 import android.content.Context;
@@ -76,6 +77,8 @@
 import com.android.wm.shell.util.TransitionUtil;
 
 import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Optional;
 
 /**
@@ -86,6 +89,18 @@
 
     private static final String TAG = PipTransition.class.getSimpleName();
 
+    /** No fixed rotation, or fixed rotation state is undefined. */
+    private static final int FIXED_ROTATION_UNDEFINED = 0;
+    /**
+     * Fixed rotation detected via callbacks (see PipController#startSwipePipToHome());
+     * this is used in the swipe PiP to home case, since the transitions itself isn't supposed to
+     * see the fixed rotation.
+     */
+    private static final int FIXED_ROTATION_CALLBACK = 1;
+
+    /** Fixed rotation detected in the incoming transition. */
+    private static final int FIXED_ROTATION_TRANSITION = 2;
+
     private final Context mContext;
     private final PipTransitionState mPipTransitionState;
     private final PipDisplayLayoutState mPipDisplayLayoutState;
@@ -106,17 +121,28 @@
     /** The Task window that is currently in PIP windowing mode. */
     @Nullable
     private WindowContainerToken mCurrentPipTaskToken;
-    /** Whether display is in fixed rotation. */
-    private boolean mInFixedRotation;
+
+    @IntDef(prefix = { "FIXED_ROTATION_" }, value =  {
+            FIXED_ROTATION_UNDEFINED,
+            FIXED_ROTATION_CALLBACK,
+            FIXED_ROTATION_TRANSITION
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface FixedRotationState {}
+
+    /** Fixed rotation state of the display. */
+    private @FixedRotationState int mFixedRotationState = FIXED_ROTATION_UNDEFINED;
     /**
      * The rotation that the display will apply after expanding PiP to fullscreen. This is only
-     * meaningful if {@link #mInFixedRotation} is true.
+     * meaningful if {@link #mFixedRotationState} is {@link #FIXED_ROTATION_TRANSITION}.
      */
     @Surface.Rotation
     private int mEndFixedRotation;
     /** Whether the PIP window has fade out for fixed rotation. */
     private boolean mHasFadeOut;
 
+    private Rect mInitBounds = new Rect();
+
     /** Used for setting transform to a transaction from animator. */
     private final PipAnimationController.PipTransactionHandler mTransactionConsumer =
             new PipAnimationController.PipTransactionHandler() {
@@ -181,8 +207,16 @@
             @NonNull Transitions.TransitionFinishCallback finishCallback) {
         final TransitionInfo.Change currentPipTaskChange = findCurrentPipTaskChange(info);
         final TransitionInfo.Change fixedRotationChange = findFixedRotationChange(info);
-        mInFixedRotation = fixedRotationChange != null;
-        mEndFixedRotation = mInFixedRotation
+        if (mFixedRotationState == FIXED_ROTATION_TRANSITION) {
+            // If we are just about to process potential fixed rotation information,
+            // then fixed rotation state should either be UNDEFINED or CALLBACK.
+            ProtoLog.w(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
+                    "%s: startAnimation() should start with clear fixed rotation state", TAG);
+            mFixedRotationState = FIXED_ROTATION_UNDEFINED;
+        }
+        mFixedRotationState = fixedRotationChange != null
+                ? FIXED_ROTATION_TRANSITION : mFixedRotationState;
+        mEndFixedRotation = mFixedRotationState == FIXED_ROTATION_TRANSITION
                 ? fixedRotationChange.getEndFixedRotation()
                 : ROTATION_UNDEFINED;
 
@@ -347,6 +381,10 @@
     @Override
     public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted,
             @Nullable SurfaceControl.Transaction finishT) {
+        // Transition either finished pre-emptively, got merged, or aborted,
+        // so update fixed rotation state to default.
+        mFixedRotationState = FIXED_ROTATION_UNDEFINED;
+
         if (transition != mExitTransition) {
             return;
         }
@@ -408,7 +446,8 @@
                 // done at the start. But if it is running fixed rotation, there will be a seamless
                 // display transition later. So the last rotation transform needs to be kept to
                 // avoid flickering, and then the display transition will reset the transform.
-                if (!mInFixedRotation && mFinishTransaction != null) {
+                if (mFixedRotationState != FIXED_ROTATION_TRANSITION
+                        && mFinishTransaction != null) {
                     mFinishTransaction.merge(tx);
                 }
             } else {
@@ -426,12 +465,27 @@
                     mSurfaceTransactionHelper.crop(tx, leash, destinationBounds)
                             .resetScale(tx, leash, destinationBounds)
                             .round(tx, leash, true /* applyCornerRadius */);
+                    if (mPipOrganizer.mPipOverlay != null && !mInitBounds.isEmpty()) {
+                        // Resetting the scale for pinned task while re-adjusting its crop,
+                        // also scales the overlay. So we need to update the overlay leash too.
+                        Rect overlayBounds = new Rect(destinationBounds);
+                        final int overlaySize = PipContentOverlay.PipAppIconOverlay
+                                .getOverlaySize(mInitBounds, destinationBounds);
+
+                        overlayBounds.offsetTo(
+                                (destinationBounds.width() - overlaySize) / 2,
+                                (destinationBounds.height() - overlaySize) / 2);
+                        mSurfaceTransactionHelper.resetScale(tx,
+                                mPipOrganizer.mPipOverlay, overlayBounds);
+                    }
                 }
+                mInitBounds.setEmpty();
                 wct.setBoundsChangeTransaction(taskInfo.token, tx);
             }
             final int displayRotation = taskInfo.getConfiguration().windowConfiguration
                     .getDisplayRotation();
-            if (enteringPip && mInFixedRotation && mEndFixedRotation != displayRotation
+            if (enteringPip && mFixedRotationState == FIXED_ROTATION_TRANSITION
+                    && mEndFixedRotation != displayRotation
                     && hasValidLeash) {
                 // Launcher may update the Shelf height during the animation, which will update the
                 // destination bounds. Because this is in fixed rotation, We need to make sure the
@@ -451,6 +505,8 @@
             mFinishTransaction = null;
             callFinishCallback(wct);
         }
+        // This is the end of transition on the Shell side so update the fixed rotation state.
+        mFixedRotationState = FIXED_ROTATION_UNDEFINED;
         finishResizeForMenu(destinationBounds);
     }
 
@@ -467,6 +523,7 @@
         // mFinishCallback might be null with an outdated mCurrentPipTaskToken
         // for example, when app crashes while in PiP and exit transition has not started
         mCurrentPipTaskToken = null;
+        mFixedRotationState = FIXED_ROTATION_UNDEFINED;
         if (mFinishCallback == null) return;
         mFinishCallback.onTransitionFinished(null /* wct */);
         mFinishCallback = null;
@@ -475,6 +532,9 @@
 
     @Override
     public void onFixedRotationStarted() {
+        if (mFixedRotationState == FIXED_ROTATION_UNDEFINED) {
+            mFixedRotationState = FIXED_ROTATION_CALLBACK;
+        }
         fadeEnteredPipIfNeed(false /* show */);
     }
 
@@ -555,9 +615,9 @@
             }
         }
         // if overlay is present remove it immediately, as exit transition came before it faded out
-        if (mPipOrganizer.mSwipePipToHomeOverlay != null) {
-            startTransaction.remove(mPipOrganizer.mSwipePipToHomeOverlay);
-            clearSwipePipToHomeOverlay();
+        if (mPipOrganizer.mPipOverlay != null) {
+            startTransaction.remove(mPipOrganizer.mPipOverlay);
+            clearPipOverlay();
         }
         if (pipChange == null) {
             ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
@@ -656,7 +716,7 @@
 
         // Check if it is fixed rotation.
         final int rotationDelta;
-        if (mInFixedRotation) {
+        if (mFixedRotationState == FIXED_ROTATION_TRANSITION) {
             final int startRotation = pipChange.getStartRotation();
             final int endRotation = mEndFixedRotation;
             rotationDelta = deltaRotation(startRotation, endRotation);
@@ -873,11 +933,13 @@
         final int startRotation = pipChange.getStartRotation();
         // Check again in case some callers use startEnterAnimation directly so the flag was not
         // set in startAnimation, e.g. from DefaultMixedHandler.
-        if (!mInFixedRotation) {
+        if (mFixedRotationState != FIXED_ROTATION_TRANSITION) {
             mEndFixedRotation = pipChange.getEndFixedRotation();
-            mInFixedRotation = mEndFixedRotation != ROTATION_UNDEFINED;
+            mFixedRotationState = mEndFixedRotation != ROTATION_UNDEFINED
+                    ? FIXED_ROTATION_TRANSITION : mFixedRotationState;
         }
-        final int endRotation = mInFixedRotation ? mEndFixedRotation : pipChange.getEndRotation();
+        final int endRotation = mFixedRotationState == FIXED_ROTATION_TRANSITION
+                ? mEndFixedRotation : pipChange.getEndRotation();
 
         setBoundsStateForEntry(taskInfo.topActivity, taskInfo.pictureInPictureParams,
                 taskInfo.topActivityInfo);
@@ -888,10 +950,15 @@
 
         final Rect destinationBounds = mPipBoundsAlgorithm.getEntryDestinationBounds();
         final Rect currentBounds = pipChange.getStartAbsBounds();
+
+        // Cache the start bounds for overlay manipulations as a part of finishCallback.
+        mInitBounds.set(currentBounds);
+
         int rotationDelta = deltaRotation(startRotation, endRotation);
         Rect sourceHintRect = PipBoundsAlgorithm.getValidSourceHintRect(
                 taskInfo.pictureInPictureParams, currentBounds, destinationBounds);
-        if (rotationDelta != Surface.ROTATION_0 && mInFixedRotation) {
+        if (rotationDelta != Surface.ROTATION_0
+                && mFixedRotationState == FIXED_ROTATION_TRANSITION) {
             // Need to get the bounds of new rotation in old rotation for fixed rotation,
             computeEnterPipRotatedBounds(rotationDelta, startRotation, endRotation, taskInfo,
                     destinationBounds, sourceHintRect);
@@ -955,10 +1022,12 @@
         } else {
             throw new RuntimeException("Unrecognized animation type: " + enterAnimationType);
         }
+        mPipOrganizer.mPipOverlay = animator.getContentOverlayLeash();
         animator.setTransitionDirection(TRANSITION_DIRECTION_TO_PIP)
                 .setPipAnimationCallback(mPipAnimationCallback)
                 .setDuration(mEnterExitAnimationDuration);
-        if (rotationDelta != Surface.ROTATION_0 && mInFixedRotation) {
+        if (rotationDelta != Surface.ROTATION_0
+                && mFixedRotationState == FIXED_ROTATION_TRANSITION) {
             // For fixed rotation, the animation destination bounds is in old rotation coordinates.
             // Set the destination bounds to new coordinates after the animation is finished.
             // ComputeRotatedBounds has changed the DisplayLayout without affecting the animation.
@@ -997,14 +1066,18 @@
             @NonNull SurfaceControl leash, @Nullable Rect sourceHintRect,
             @NonNull Rect destinationBounds,
             @NonNull ActivityManager.RunningTaskInfo pipTaskInfo) {
-        if (mInFixedRotation) {
+        if (mFixedRotationState == FIXED_ROTATION_TRANSITION) {
             // If rotation changes when returning to home, the transition should contain both the
             // entering PiP and the display change (PipController#startSwipePipToHome has updated
             // the display layout to new rotation). So it is not expected to see fixed rotation.
             ProtoLog.w(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
                     "%s: SwipePipToHome should not use fixed rotation %d", TAG, mEndFixedRotation);
         }
-        final SurfaceControl swipePipToHomeOverlay = mPipOrganizer.mSwipePipToHomeOverlay;
+        Rect appBounds = pipTaskInfo.configuration.windowConfiguration.getAppBounds();
+        if (mFixedRotationState == FIXED_ROTATION_CALLBACK && appBounds != null) {
+            mInitBounds.set(appBounds);
+        }
+        final SurfaceControl swipePipToHomeOverlay = mPipOrganizer.mPipOverlay;
         if (swipePipToHomeOverlay != null) {
             // Launcher fade in the overlay on top of the fullscreen Task. It is possible we
             // reparent the PIP activity to a new PIP task (in case there are other activities
@@ -1033,7 +1106,7 @@
         sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP);
         if (swipePipToHomeOverlay != null) {
             mPipOrganizer.fadeOutAndRemoveOverlay(swipePipToHomeOverlay,
-                    this::clearSwipePipToHomeOverlay /* callback */, false /* withStartDelay */);
+                    this::clearPipOverlay /* callback */, false /* withStartDelay */);
         }
         mPipTransitionState.setInSwipePipToHomeTransition(false);
     }
@@ -1177,8 +1250,8 @@
         mPipMenuController.updateMenuBounds(destinationBounds);
     }
 
-    private void clearSwipePipToHomeOverlay() {
-        mPipOrganizer.mSwipePipToHomeOverlay = null;
+    private void clearPipOverlay() {
+        mPipOrganizer.mPipOverlay = null;
     }
 
     @Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
index 20c57fa..04911c0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
@@ -78,9 +78,9 @@
                     if (direction == TRANSITION_DIRECTION_REMOVE_STACK) {
                         return;
                     }
-                    if (isInPipDirection(direction) && animator.getContentOverlayLeash() != null) {
-                        mPipOrganizer.fadeOutAndRemoveOverlay(animator.getContentOverlayLeash(),
-                                animator::clearContentOverlay, true /* withStartDelay*/);
+                    if (isInPipDirection(direction) && mPipOrganizer.mPipOverlay != null) {
+                        mPipOrganizer.fadeOutAndRemoveOverlay(mPipOrganizer.mPipOverlay,
+                                null /* callback */, true /* withStartDelay*/);
                     }
                     onFinishResize(taskInfo, animator.getDestinationBounds(), direction, tx);
                     sendOnPipTransitionFinished(direction);
@@ -90,9 +90,9 @@
                 public void onPipAnimationCancel(TaskInfo taskInfo,
                         PipAnimationController.PipTransitionAnimator animator) {
                     final int direction = animator.getTransitionDirection();
-                    if (isInPipDirection(direction) && animator.getContentOverlayLeash() != null) {
-                        mPipOrganizer.fadeOutAndRemoveOverlay(animator.getContentOverlayLeash(),
-                                animator::clearContentOverlay, true /* withStartDelay */);
+                    if (isInPipDirection(direction) && mPipOrganizer.mPipOverlay != null) {
+                        mPipOrganizer.fadeOutAndRemoveOverlay(mPipOrganizer.mPipOverlay,
+                                null /* callback */, true /* withStartDelay */);
                     }
                     sendOnPipTransitionCancelled(animator.getTransitionDirection());
                 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
index 79c2076..d023cea 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
@@ -255,6 +255,7 @@
         private ArrayList<TaskState> mOpeningTasks = null;
 
         private WindowContainerToken mPipTask = null;
+        private int mPipTaskId = -1;
         private WindowContainerToken mRecentsTask = null;
         private int mRecentsTaskId = -1;
         private TransitionInfo mInfo = null;
@@ -822,8 +823,8 @@
             } else if (!didMergeThings) {
                 // Didn't recognize anything in incoming transition so don't merge it.
                 Slog.w(TAG, "Don't know how to merge this transition, foundRecentsClosing="
-                        + foundRecentsClosing);
-                if (foundRecentsClosing) {
+                        + foundRecentsClosing + " recentsTaskId=" + mRecentsTaskId);
+                if (foundRecentsClosing || mRecentsTaskId < 0) {
                     mWillFinishToHome = false;
                     cancel(false /* toHome */, false /* withScreenshots */, "didn't merge");
                 }
@@ -904,12 +905,14 @@
         @Override
         public void setFinishTaskTransaction(int taskId,
                 PictureInPictureSurfaceTransaction finishTransaction, SurfaceControl overlay) {
-            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
-                    "[%d] RecentsController.setFinishTaskTransaction: taskId=%d",
-                    mInstanceId, taskId);
             mExecutor.execute(() -> {
+                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+                        "[%d] RecentsController.setFinishTaskTransaction: taskId=%d,"
+                                + " [mFinishCB is non-null]=%b",
+                        mInstanceId, taskId, mFinishCB != null);
                 if (mFinishCB == null) return;
                 mPipTransaction = finishTransaction;
+                mPipTaskId = taskId;
             });
         }
 
@@ -992,21 +995,40 @@
                     t.show(mOpeningTasks.get(i).mTaskSurface);
                 }
                 for (int i = 0; i < mPausingTasks.size(); ++i) {
-                    if (!sendUserLeaveHint && mPausingTasks.get(i).isLeaf()) {
-                        // This means recents is not *actually* finishing, so of course we gotta
-                        // do special stuff in WMCore to accommodate.
-                        wct.setDoNotPip(mPausingTasks.get(i).mToken);
-                    }
-                    // Since we will reparent out of the leashes, pre-emptively hide the child
-                    // surface to match the leash. Otherwise, there will be a flicker before the
-                    // visibility gets committed in Core when using split-screen (in splitscreen,
-                    // the leaf-tasks are not "independent" so aren't hidden by normal setup).
-                    t.hide(mPausingTasks.get(i).mTaskSurface);
+                    cleanUpPausingOrClosingTask(mPausingTasks.get(i), wct, t, sendUserLeaveHint);
                 }
-                if (mPipTask != null && mPipTransaction != null && sendUserLeaveHint) {
-                    t.show(mInfo.getChange(mPipTask).getLeash());
-                    PictureInPictureSurfaceTransaction.apply(mPipTransaction,
-                            mInfo.getChange(mPipTask).getLeash(), t);
+                for (int i = 0; i < mClosingTasks.size(); ++i) {
+                    cleanUpPausingOrClosingTask(mClosingTasks.get(i), wct, t, sendUserLeaveHint);
+                }
+                if (mPipTransaction != null && sendUserLeaveHint) {
+                    SurfaceControl pipLeash = null;
+                    if (mPipTask != null) {
+                        pipLeash = mInfo.getChange(mPipTask).getLeash();
+                    } else if (mPipTaskId != -1) {
+                        // find a task with taskId from #setFinishTaskTransaction()
+                        for (TransitionInfo.Change change : mInfo.getChanges()) {
+                            if (change.getTaskInfo() != null
+                                    && change.getTaskInfo().taskId == mPipTaskId) {
+                                pipLeash = change.getLeash();
+                                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+                                        "RecentsController.finishInner:"
+                                                + " found a change with taskId=%d", mPipTaskId);
+                            }
+                        }
+                    }
+                    if (pipLeash == null) {
+                        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+                                "RecentsController.finishInner: no valid PiP leash;"
+                                        + "mPipTransaction=%s, mPipTask=%s, mPipTaskId=%d",
+                                mPipTransaction.toString(), mPipTask.toString(), mPipTaskId);
+                    } else {
+                        t.show(pipLeash);
+                        PictureInPictureSurfaceTransaction.apply(mPipTransaction, pipLeash, t);
+                        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+                                "RecentsController.finishInner: PiP transaction %s merged",
+                                mPipTransaction);
+                    }
+                    mPipTaskId = -1;
                     mPipTask = null;
                     mPipTransaction = null;
                 }
@@ -1025,6 +1047,20 @@
             }
         }
 
+        private void cleanUpPausingOrClosingTask(TaskState task, WindowContainerTransaction wct,
+                SurfaceControl.Transaction finishTransaction, boolean sendUserLeaveHint) {
+            if (!sendUserLeaveHint && task.isLeaf()) {
+                // This means recents is not *actually* finishing, so of course we gotta
+                // do special stuff in WMCore to accommodate.
+                wct.setDoNotPip(task.mToken);
+            }
+            // Since we will reparent out of the leashes, pre-emptively hide the child
+            // surface to match the leash. Otherwise, there will be a flicker before the
+            // visibility gets committed in Core when using split-screen (in splitscreen,
+            // the leaf-tasks are not "independent" so aren't hidden by normal setup).
+            finishTransaction.hide(task.mTaskSurface);
+        }
+
         @Override
         public void setDeferCancelUntilNextTransition(boolean defer, boolean screenshot) {
         }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index 56f1c78..7b57097 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -847,9 +847,12 @@
                 .map(recentTasks -> recentTasks.findTaskInBackground(component, userId1))
                 .orElse(null);
         if (taskInfo != null) {
-            startTask(taskInfo.taskId, position, options);
-            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN,
-                    "Start task in background");
+            if (ENABLE_SHELL_TRANSITIONS) {
+                mStageCoordinator.startTask(taskInfo.taskId, position, options);
+            } else {
+                startTask(taskInfo.taskId, position, options);
+            }
+            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "Start task in background");
             return;
         }
         if (samePackage(packageName1, packageName2, userId1, userId2)) {
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 be685b5..96e57e7 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
@@ -223,6 +223,7 @@
     private boolean mExitSplitScreenOnHide;
     private boolean mIsDividerRemoteAnimating;
     private boolean mIsDropEntering;
+    private boolean mSkipEvictingMainStageChildren;
     private boolean mIsExiting;
     private boolean mIsRootTranslucent;
     @VisibleForTesting
@@ -263,6 +264,10 @@
             mStartIntent2 = startIntent2;
             mActivatePosition = position;
         }
+        SplitRequest(int taskId1, int position) {
+            mActivateTaskId = taskId1;
+            mActivatePosition = position;
+        }
         SplitRequest(int taskId1, int taskId2, int position) {
             mActivateTaskId = taskId1;
             mActivateTaskId2 = taskId2;
@@ -464,6 +469,7 @@
         }
         // Due to drag already pip task entering split by this method so need to reset flag here.
         mIsDropEntering = false;
+        mSkipEvictingMainStageChildren = false;
         return true;
     }
 
@@ -556,6 +562,36 @@
         }
     }
 
+    /** Use this method to launch an existing Task via a taskId */
+    void startTask(int taskId, @SplitPosition int position, @Nullable Bundle options) {
+        mSplitRequest = new SplitRequest(taskId, position);
+        final WindowContainerTransaction wct = new WindowContainerTransaction();
+        options = resolveStartStage(STAGE_TYPE_UNDEFINED, position, options, null /* wct */);
+        wct.startTask(taskId, options);
+        // If this should be mixed, send the task to avoid split handle transition directly.
+        if (mMixedHandler != null && mMixedHandler.shouldSplitEnterMixed(taskId, mTaskOrganizer)) {
+            mTaskOrganizer.applyTransaction(wct);
+            return;
+        }
+
+        // Don't evict the main stage children as this can race and happen after the activity is
+        // started into that stage
+        if (!isSplitScreenVisible()) {
+            mSkipEvictingMainStageChildren = true;
+            // Starting the split task without evicting children will bring the single root task
+            // container forward, so ensure that we hide the divider before we start animate it
+            setDividerVisibility(false, null);
+        }
+
+        // If split screen is not activated, we're expecting to open a pair of apps to split.
+        final int extraTransitType = mMainStage.isActive()
+                ? TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE : TRANSIT_SPLIT_SCREEN_PAIR_OPEN;
+        prepareEnterSplitScreen(wct, null /* taskInfo */, position, !mIsDropEntering);
+
+        mSplitTransitions.startEnterTransition(TRANSIT_TO_FRONT, wct, null, this,
+                extraTransitType, !mIsDropEntering);
+    }
+
     /** Launches an activity into split. */
     void startIntent(PendingIntent intent, Intent fillInIntent, @SplitPosition int position,
             @Nullable Bundle options) {
@@ -575,6 +611,15 @@
             return;
         }
 
+        // Don't evict the main stage children as this can race and happen after the activity is
+        // started into that stage
+        if (!isSplitScreenVisible()) {
+            mSkipEvictingMainStageChildren = true;
+            // Starting the split task without evicting children will bring the single root task
+            // container forward, so ensure that we hide the divider before we start animate it
+            setDividerVisibility(false, null);
+        }
+
         // If split screen is not activated, we're expecting to open a pair of apps to split.
         final int extraTransitType = mMainStage.isActive()
                 ? TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE : TRANSIT_SPLIT_SCREEN_PAIR_OPEN;
@@ -1593,7 +1638,9 @@
             // Ensure to evict old splitting tasks because the new split pair might be composed by
             // one of the splitting tasks, evicting the task when finishing entering transition
             // won't guarantee to put the task to the indicated new position.
-            mMainStage.evictAllChildren(wct);
+            if (!mSkipEvictingMainStageChildren) {
+                mMainStage.evictAllChildren(wct);
+            }
             mMainStage.reparentTopTask(wct);
             prepareSplitLayout(wct, resizeAnim);
         }
@@ -1639,7 +1686,7 @@
     }
 
     void finishEnterSplitScreen(SurfaceControl.Transaction finishT) {
-        mSplitLayout.update(finishT);
+        mSplitLayout.update(finishT, true /* resetImePosition */);
         mMainStage.getSplitDecorManager().inflate(mContext, mMainStage.mRootLeash,
                 getMainStageBounds());
         mSideStage.getSplitDecorManager().inflate(mContext, mSideStage.mRootLeash,
@@ -1653,6 +1700,7 @@
         finishT.show(mRootTaskLeash);
         setSplitsVisible(true);
         mIsDropEntering = false;
+        mSkipEvictingMainStageChildren = false;
         mSplitRequest = null;
         updateRecentTasksSplitPair();
         if (!mLogger.hasStartedSession()) {
@@ -1833,9 +1881,10 @@
                 && mSplitLayout.updateConfiguration(mRootTaskInfo.configuration)
                 && mMainStage.isActive()) {
             // Clear the divider remote animating flag as the divider will be re-rendered to apply
-            // the new rotation config.
+            // the new rotation config.  Don't reset the IME state since those updates are not in
+            // sync with task info changes.
             mIsDividerRemoteAnimating = false;
-            mSplitLayout.update(null /* t */);
+            mSplitLayout.update(null /* t */, false /* resetImePosition */);
             onLayoutSizeChanged(mSplitLayout);
         }
     }
@@ -1901,6 +1950,7 @@
                 if (mIsDropEntering) {
                     updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */);
                     mIsDropEntering = false;
+                    mSkipEvictingMainStageChildren = false;
                 } else {
                     mShowDecorImmediately = true;
                     mSplitLayout.flingDividerToCenter();
@@ -2095,6 +2145,7 @@
                 if (mIsDropEntering) {
                     updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */);
                     mIsDropEntering = false;
+                    mSkipEvictingMainStageChildren = false;
                 } else {
                     mShowDecorImmediately = true;
                     mSplitLayout.flingDividerToCenter();
@@ -2298,7 +2349,7 @@
      */
     public void updateSurfaces(SurfaceControl.Transaction transaction) {
         updateSurfaceBounds(mSplitLayout, transaction, /* applyResizingOffset */ false);
-        mSplitLayout.update(transaction);
+        mSplitLayout.update(transaction, true /* resetImePosition */);
     }
 
     private void onDisplayChange(int displayId, int fromRotation, int toRotation,
@@ -2571,7 +2622,9 @@
                 final TransitionInfo.Change change = info.getChanges().get(iC);
                 if (change.getMode() == TRANSIT_CHANGE
                         && (change.getFlags() & FLAG_IS_DISPLAY) != 0) {
-                    mSplitLayout.update(startTransaction);
+                    // Don't reset the IME state since those updates are not in sync with the
+                    // display change transition
+                    mSplitLayout.update(startTransaction, false /* resetImePosition */);
                 }
 
                 if (mMixedHandler.isEnteringPip(change, transitType)) {
@@ -2672,7 +2725,7 @@
                     startTransaction, finishTransaction, finishCallback)) {
                 if (mSplitTransitions.isPendingResize(transition)) {
                     // Only need to update in resize because divider exist before transition.
-                    mSplitLayout.update(startTransaction);
+                    mSplitLayout.update(startTransaction, true /* resetImePosition */);
                     startTransaction.apply();
                 }
                 return true;
@@ -3215,6 +3268,7 @@
     public void onDroppedToSplit(@SplitPosition int position, InstanceId dragSessionId) {
         if (!isSplitScreenVisible()) {
             mIsDropEntering = true;
+            mSkipEvictingMainStageChildren = true;
         }
         if (!isSplitScreenVisible() && !ENABLE_SHELL_TRANSITIONS) {
             // If split running background, exit split first.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
index 43ae5f4..ae21c4b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
@@ -247,7 +247,7 @@
         }
         params.layoutInDisplayCutoutMode = a.getInt(
                 R.styleable.Window_windowLayoutInDisplayCutoutMode,
-                params.layoutInDisplayCutoutMode);
+                WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS);
         params.windowAnimations = a.getResourceId(R.styleable.Window_windowAnimationStyle, 0);
         a.recycle();
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java
index e03f825..34c015f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java
@@ -330,6 +330,11 @@
                     continue;
                 }
                 if (isHide) {
+                    if (pending.mType == TRANSIT_TO_BACK) {
+                        // TO_BACK is only used when setting the task view visibility immediately,
+                        // so in that case we can also hide the surface immediately
+                        startTransaction.hide(chg.getLeash());
+                    }
                     tv.prepareHideAnimation(finishTransaction);
                 } else {
                     tv.prepareCloseAnimation();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
index ce7fef2..9f20f49 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
@@ -48,9 +48,9 @@
 import android.window.WindowContainerTransaction;
 
 import com.android.internal.protolog.common.ProtoLog;
+import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.activityembedding.ActivityEmbeddingController;
 import com.android.wm.shell.common.split.SplitScreenUtils;
-import com.android.wm.shell.desktopmode.DesktopModeStatus;
 import com.android.wm.shell.desktopmode.DesktopTasksController;
 import com.android.wm.shell.keyguard.KeyguardTransitionHandler;
 import com.android.wm.shell.pip.PipTransitionController;
@@ -298,7 +298,7 @@
             mixed.mLeftoversHandler = handler.first;
             mActiveTransitions.add(mixed);
             return handler.second;
-        } else if (mUnfoldHandler != null && mUnfoldHandler.hasUnfold(request)) {
+        } else if (mUnfoldHandler != null && mUnfoldHandler.shouldPlayUnfoldAnimation(request)) {
             final WindowContainerTransaction wct =
                     mUnfoldHandler.handleRequest(transition, request);
             if (wct != null) {
@@ -902,6 +902,18 @@
         return false;
     }
 
+    /** Use to when split use taskId to enter, check if this enter transition should be mixed or
+     * not.*/
+    public boolean shouldSplitEnterMixed(int taskId, ShellTaskOrganizer shellTaskOrganizer) {
+        // Check if this intent package is same as pip one or not, if true we want let the pip
+        // task enter split.
+        if (mPipHandler != null) {
+            return mPipHandler.isInPipPackage(
+                    SplitScreenUtils.getPackageName(taskId, shellTaskOrganizer));
+        }
+        return false;
+    }
+
     /** @return whether the transition-request represents a pip-entry. */
     public boolean requestHasPipEnter(TransitionRequestInfo request) {
         return mPipHandler.requestHasPipEnter(request);
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 5c02dbc..473deba 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
@@ -57,7 +57,9 @@
             @NonNull SurfaceControl.Transaction finishTransaction) {
         for (TransitionInfo.Change change : info.getChanges()) {
             final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
-            if (taskInfo == null || taskInfo.taskId == -1) {
+            if (taskInfo == null
+                    || taskInfo.taskId == -1
+                    || !taskInfo.isRunning) {
                 continue;
             }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/IShellTransitions.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/IShellTransitions.aidl
index 644a6a5..7f4a8f1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/IShellTransitions.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/IShellTransitions.aidl
@@ -16,6 +16,7 @@
 
 package com.android.wm.shell.transition;
 
+import android.view.SurfaceControl;
 import android.window.RemoteTransition;
 import android.window.TransitionFilter;
 
@@ -42,6 +43,13 @@
      */
     IBinder getShellApplyToken() = 3;
 
-    /** Set listener that will receive callbacks about transitions involving home activity */
+    /**
+     * Set listener that will receive callbacks about transitions involving home activity.
+     */
     oneway void setHomeTransitionListener(in IHomeTransitionListener listener) = 4;
+
+    /**
+     * Returns a container surface for the home root task.
+     */
+    SurfaceControl getHomeTaskOverlayContainer() = 5;
 }
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 b98762d..af69b52 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
@@ -64,7 +64,6 @@
 import android.window.TransitionMetrics;
 import android.window.TransitionRequestInfo;
 import android.window.WindowContainerTransaction;
-import android.window.WindowOrganizer;
 
 import androidx.annotation.BinderThread;
 
@@ -72,6 +71,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
+import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.ExternalInterfaceBinder;
 import com.android.wm.shell.common.RemoteCallable;
@@ -172,7 +172,7 @@
     /** Transition to animate task to desktop. */
     public static final int TRANSIT_MOVE_TO_DESKTOP = WindowManager.TRANSIT_FIRST_CUSTOM + 15;
 
-    private final WindowOrganizer mOrganizer;
+    private final ShellTaskOrganizer mOrganizer;
     private final Context mContext;
     private final ShellExecutor mMainExecutor;
     private final ShellExecutor mAnimExecutor;
@@ -264,7 +264,7 @@
     public Transitions(@NonNull Context context,
             @NonNull ShellInit shellInit,
             @NonNull ShellController shellController,
-            @NonNull WindowOrganizer organizer,
+            @NonNull ShellTaskOrganizer organizer,
             @NonNull TransactionPool pool,
             @NonNull DisplayController displayController,
             @NonNull ShellExecutor mainExecutor,
@@ -280,7 +280,7 @@
             @NonNull ShellInit shellInit,
             @Nullable ShellCommandHandler shellCommandHandler,
             @NonNull ShellController shellController,
-            @NonNull WindowOrganizer organizer,
+            @NonNull ShellTaskOrganizer organizer,
             @NonNull TransactionPool pool,
             @NonNull DisplayController displayController,
             @NonNull ShellExecutor mainExecutor,
@@ -1240,6 +1240,10 @@
         }
     }
 
+    private SurfaceControl getHomeTaskOverlayContainer() {
+        return mOrganizer.getHomeTaskOverlayContainer();
+    }
+
     /**
      * Interface for a callback that must be called after a TransitionHandler finishes playing an
      * animation.
@@ -1470,6 +1474,17 @@
                                 listener);
                     });
         }
+
+        @Override
+        public SurfaceControl getHomeTaskOverlayContainer() {
+            SurfaceControl[] result = new SurfaceControl[1];
+            executeRemoteCallWithTaskPermission(mTransitions, "getHomeTaskOverlayContainer",
+                    (controller) -> {
+                        result[0] = controller.getHomeTaskOverlayContainer();
+                    }, true /* blocking */);
+            // Return a copy as writing to parcel releases the original surface
+            return new SurfaceControl(result[0], "Transitions.HomeOverlay");
+        }
     }
 
     private class SettingsObserver extends ContentObserver {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldTransitionHandler.java
index 07c5429..98d343b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldTransitionHandler.java
@@ -18,6 +18,7 @@
 
 import static android.view.WindowManager.KEYGUARD_VISIBILITY_TRANSIT_FLAGS;
 import static android.view.WindowManager.TRANSIT_CHANGE;
+import static android.view.WindowManager.TRANSIT_FLAG_PHYSICAL_DISPLAY_SWITCH;
 
 import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TRANSITIONS;
 
@@ -106,7 +107,7 @@
             @NonNull SurfaceControl.Transaction startTransaction,
             @NonNull SurfaceControl.Transaction finishTransaction,
             @NonNull TransitionFinishCallback finishCallback) {
-        if (hasUnfold(info) && transition != mTransition) {
+        if (shouldPlayUnfoldAnimation(info) && transition != mTransition) {
             // Take over transition that has unfold, we might receive it if no other handler
             // accepted request in handleRequest, e.g. for rotation + unfold or
             // TRANSIT_NONE + unfold transitions
@@ -213,33 +214,61 @@
     }
 
     /** Whether `request` contains an unfold action. */
-    public boolean hasUnfold(@NonNull TransitionRequestInfo request) {
-        return (request.getType() == TRANSIT_CHANGE
-                && request.getDisplayChange() != null
-                && request.getDisplayChange().isPhysicalDisplayChanged());
-    }
-
-    /** Whether `transitionInfo` contains an unfold action. */
-    public boolean hasUnfold(@NonNull TransitionInfo transitionInfo) {
+    public boolean shouldPlayUnfoldAnimation(@NonNull TransitionRequestInfo request) {
         // Unfold animation won't play when animations are disabled
         if (!ValueAnimator.areAnimatorsEnabled()) return false;
 
+        return (request.getType() == TRANSIT_CHANGE
+                && request.getDisplayChange() != null
+                && isUnfoldDisplayChange(request.getDisplayChange()));
+    }
+
+    private boolean isUnfoldDisplayChange(
+            @NonNull TransitionRequestInfo.DisplayChange displayChange) {
+        if (!displayChange.isPhysicalDisplayChanged()) {
+            return false;
+        }
+
+        if (displayChange.getStartAbsBounds() == null || displayChange.getEndAbsBounds() == null) {
+            return false;
+        }
+
+        // Handle only unfolding, currently we don't have an animation when folding
+        final int endArea =
+                displayChange.getEndAbsBounds().width() * displayChange.getEndAbsBounds().height();
+        final int startArea = displayChange.getStartAbsBounds().width()
+                * displayChange.getStartAbsBounds().height();
+
+        return endArea > startArea;
+    }
+
+    /** Whether `transitionInfo` contains an unfold action. */
+    public boolean shouldPlayUnfoldAnimation(@NonNull TransitionInfo transitionInfo) {
+        // Unfold animation won't play when animations are disabled
+        if (!ValueAnimator.areAnimatorsEnabled()) return false;
+        // Only handle transitions that are marked as physical display switch
+        // See PhysicalDisplaySwitchTransitionLauncher for the conditions
+        if ((transitionInfo.getFlags() & TRANSIT_FLAG_PHYSICAL_DISPLAY_SWITCH) == 0) return false;
+
         for (int i = 0; i < transitionInfo.getChanges().size(); i++) {
             final TransitionInfo.Change change = transitionInfo.getChanges().get(i);
-            if ((change.getFlags() & TransitionInfo.FLAG_IS_DISPLAY) != 0) {
-                if (change.getEndAbsBounds() == null || change.getStartAbsBounds() == null) {
-                    continue;
-                }
+            // We are interested only in display container changes
+            if ((change.getFlags() & TransitionInfo.FLAG_IS_DISPLAY) == 0) {
+                continue;
+            }
 
-                // Handle only unfolding, currently we don't have an animation when folding
-                final int afterArea =
-                        change.getEndAbsBounds().width() * change.getEndAbsBounds().height();
-                final int beforeArea = change.getStartAbsBounds().width()
-                        * change.getStartAbsBounds().height();
+            // Handle only unfolding, currently we don't have an animation when folding
+            if (change.getEndAbsBounds() == null || change.getStartAbsBounds() == null) {
+                continue;
+            }
 
-                if (afterArea > beforeArea) {
-                    return true;
-                }
+            final int afterArea =
+                    change.getEndAbsBounds().width() * change.getEndAbsBounds().height();
+            final int beforeArea = change.getStartAbsBounds().width()
+                    * change.getStartAbsBounds().height();
+
+            if (afterArea > beforeArea) {
+                return true;
             }
         }
 
@@ -250,7 +279,7 @@
     @Override
     public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
             @NonNull TransitionRequestInfo request) {
-        if (hasUnfold(request)) {
+        if (shouldPlayUnfoldAnimation(request)) {
             mTransition = transition;
             return new WindowContainerTransaction();
         }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeAppControlsWindowDecorationViewHolder.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeAppControlsWindowDecorationViewHolder.kt
index b739ad3..589a813 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeAppControlsWindowDecorationViewHolder.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeAppControlsWindowDecorationViewHolder.kt
@@ -1,14 +1,23 @@
 package com.android.wm.shell.windowdecor.viewholder
 
+import android.annotation.ColorInt
 import android.app.ActivityManager.RunningTaskInfo
 import android.content.res.ColorStateList
+import android.content.res.Configuration
 import android.graphics.Bitmap
-import android.graphics.drawable.GradientDrawable
+import android.graphics.Color
 import android.view.View
 import android.view.View.OnLongClickListener
 import android.widget.ImageButton
 import android.widget.ImageView
 import android.widget.TextView
+import androidx.core.content.withStyledAttributes
+import com.android.internal.R.attr.materialColorOnSecondaryContainer
+import com.android.internal.R.attr.materialColorOnSurface
+import com.android.internal.R.attr.materialColorSecondaryContainer
+import com.android.internal.R.attr.materialColorSurfaceContainerHigh
+import com.android.internal.R.attr.materialColorSurfaceContainerLow
+import com.android.internal.R.attr.materialColorSurfaceDim
 import com.android.wm.shell.R
 
 /**
@@ -49,57 +58,82 @@
     }
 
     override fun bindData(taskInfo: RunningTaskInfo) {
-        val captionDrawable = captionView.background as GradientDrawable
-        taskInfo.taskDescription?.statusBarColor?.let {
-            captionDrawable.setColor(it)
-        }
-
-        closeWindowButton.imageTintList = ColorStateList.valueOf(
-                getCaptionCloseButtonColor(taskInfo))
-        maximizeWindowButton.imageTintList = ColorStateList.valueOf(
-                getCaptionMaximizeButtonColor(taskInfo))
-        expandMenuButton.imageTintList = ColorStateList.valueOf(
-                getCaptionExpandButtonColor(taskInfo))
-        appNameTextView.setTextColor(getCaptionAppNameTextColor(taskInfo))
+        captionView.setBackgroundColor(getCaptionBackgroundColor(taskInfo))
+        val color = getAppNameAndButtonColor(taskInfo)
+        val alpha = Color.alpha(color)
+        closeWindowButton.imageTintList = ColorStateList.valueOf(color)
+        maximizeWindowButton.imageTintList = ColorStateList.valueOf(color)
+        expandMenuButton.imageTintList = ColorStateList.valueOf(color)
+        appNameTextView.setTextColor(color)
+        appIconImageView.imageAlpha = alpha
+        maximizeWindowButton.imageAlpha = alpha
+        closeWindowButton.imageAlpha = alpha
+        expandMenuButton.imageAlpha = alpha
     }
 
     override fun onHandleMenuOpened() {}
 
     override fun onHandleMenuClosed() {}
 
-    private fun getCaptionAppNameTextColor(taskInfo: RunningTaskInfo): Int {
-        return if (shouldUseLightCaptionColors(taskInfo)) {
-            context.getColor(R.color.desktop_mode_caption_app_name_light)
-        } else {
-            context.getColor(R.color.desktop_mode_caption_app_name_dark)
+    @ColorInt
+    private fun getCaptionBackgroundColor(taskInfo: RunningTaskInfo): Int {
+        val materialColorAttr: Int =
+            if (isDarkMode()) {
+                if (!taskInfo.isFocused) {
+                    materialColorSurfaceContainerHigh
+                } else {
+                    materialColorSurfaceDim
+                }
+            } else {
+                if (!taskInfo.isFocused) {
+                    materialColorSurfaceContainerLow
+                } else {
+                    materialColorSecondaryContainer
+                }
         }
+        context.withStyledAttributes(null, intArrayOf(materialColorAttr), 0, 0) {
+            return getColor(0, 0)
+        }
+        return 0
     }
 
-    private fun getCaptionCloseButtonColor(taskInfo: RunningTaskInfo): Int {
-        return if (shouldUseLightCaptionColors(taskInfo)) {
-            context.getColor(R.color.desktop_mode_caption_close_button_light)
-        } else {
-            context.getColor(R.color.desktop_mode_caption_close_button_dark)
+    @ColorInt
+    private fun getAppNameAndButtonColor(taskInfo: RunningTaskInfo): Int {
+        val materialColorAttr = when {
+            isDarkMode() -> materialColorOnSurface
+            else -> materialColorOnSecondaryContainer
         }
+        val appDetailsOpacity = when {
+            isDarkMode() && !taskInfo.isFocused -> DARK_THEME_UNFOCUSED_OPACITY
+            !isDarkMode() && !taskInfo.isFocused -> LIGHT_THEME_UNFOCUSED_OPACITY
+            else -> FOCUSED_OPACITY
+        }
+        context.withStyledAttributes(null, intArrayOf(materialColorAttr), 0, 0) {
+            val color = getColor(0, 0)
+            return if (appDetailsOpacity == FOCUSED_OPACITY) {
+                color
+            } else {
+                Color.argb(
+                    appDetailsOpacity,
+                    Color.red(color),
+                    Color.green(color),
+                    Color.blue(color)
+                )
+            }
+        }
+        return 0
     }
 
-    private fun getCaptionMaximizeButtonColor(taskInfo: RunningTaskInfo): Int {
-        return if (shouldUseLightCaptionColors(taskInfo)) {
-            context.getColor(R.color.desktop_mode_caption_maximize_button_light)
-        } else {
-            context.getColor(R.color.desktop_mode_caption_maximize_button_dark)
-        }
-    }
-
-    private fun getCaptionExpandButtonColor(taskInfo: RunningTaskInfo): Int {
-        return if (shouldUseLightCaptionColors(taskInfo)) {
-            context.getColor(R.color.desktop_mode_caption_expand_button_light)
-        } else {
-            context.getColor(R.color.desktop_mode_caption_expand_button_dark)
-        }
+    private fun isDarkMode(): Boolean {
+        return context.resources.configuration.uiMode and
+                Configuration.UI_MODE_NIGHT_MASK ==
+                Configuration.UI_MODE_NIGHT_YES
     }
 
     companion object {
         private const val TAG = "DesktopModeAppControlsWindowDecorationViewHolder"
+        private const val DARK_THEME_UNFOCUSED_OPACITY = 140 // 55%
+        private const val LIGHT_THEME_UNFOCUSED_OPACITY = 166 // 65%
+        private const val FOCUSED_OPACITY = 255
     }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeFocusedWindowDecorationViewHolder.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeFocusedWindowDecorationViewHolder.kt
index b1fb0f1..4930cb7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeFocusedWindowDecorationViewHolder.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeFocusedWindowDecorationViewHolder.kt
@@ -2,9 +2,11 @@
 
 import android.animation.ObjectAnimator
 import android.app.ActivityManager.RunningTaskInfo
+import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
 import android.content.res.ColorStateList
-import android.graphics.drawable.GradientDrawable
+import android.graphics.Color
 import android.view.View
+import android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS
 import android.widget.ImageButton
 import com.android.wm.shell.R
 import com.android.wm.shell.animation.Interpolators
@@ -34,10 +36,8 @@
 
     override fun bindData(taskInfo: RunningTaskInfo) {
         taskInfo.taskDescription?.statusBarColor?.let { captionColor ->
-            val captionDrawable = captionView.background as GradientDrawable
-            captionDrawable.setColor(captionColor)
+            captionView.setBackgroundColor(captionColor)
         }
-
         captionHandle.imageTintList = ColorStateList.valueOf(getCaptionHandleBarColor(taskInfo))
     }
 
@@ -57,6 +57,22 @@
         }
     }
 
+    /**
+     * Whether the caption items should use the 'light' color variant so that there's good contrast
+     * with the caption background color.
+     */
+    private fun shouldUseLightCaptionColors(taskInfo: RunningTaskInfo): Boolean {
+        return taskInfo.taskDescription
+            ?.let { taskDescription ->
+                if (Color.alpha(taskDescription.statusBarColor) != 0 &&
+                    taskInfo.windowingMode == WINDOWING_MODE_FREEFORM) {
+                    Color.valueOf(taskDescription.statusBarColor).luminance() < 0.5
+                } else {
+                    taskDescription.statusBarAppearance and APPEARANCE_LIGHT_STATUS_BARS == 0
+                }
+            } ?: false
+    }
+
     /** Animate appearance/disappearance of caption handle as the handle menu is animated. */
     private fun animateCaptionHandleAlpha(startValue: Float, endValue: Float) {
         val animator =
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeWindowDecorationViewHolder.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeWindowDecorationViewHolder.kt
index 8b405f0..690b4e4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeWindowDecorationViewHolder.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeWindowDecorationViewHolder.kt
@@ -1,11 +1,8 @@
 package com.android.wm.shell.windowdecor.viewholder
 
 import android.app.ActivityManager.RunningTaskInfo
-import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
 import android.content.Context
-import android.graphics.Color
 import android.view.View
-import android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS
 
 /**
  * Encapsulates the root [View] of a window decoration and its children to facilitate looking up
@@ -20,22 +17,6 @@
    */
   abstract fun bindData(taskInfo: RunningTaskInfo)
 
-  /**
-   * Whether the caption items should use the 'light' color variant so that there's good contrast
-   * with the caption background color.
-   */
-  protected fun shouldUseLightCaptionColors(taskInfo: RunningTaskInfo): Boolean {
-    return taskInfo.taskDescription
-        ?.let { taskDescription ->
-          if (Color.alpha(taskDescription.statusBarColor) != 0 &&
-              taskInfo.windowingMode == WINDOWING_MODE_FREEFORM) {
-            Color.valueOf(taskDescription.statusBarColor).luminance() < 0.5
-          } else {
-            taskDescription.statusBarAppearance and APPEARANCE_LIGHT_STATUS_BARS == 0
-          }
-        } ?: false
-  }
-
     /** Callback when the handle menu is opened. */
     abstract fun onHandleMenuOpened()
 
diff --git a/libs/WindowManager/Shell/tests/OWNERS b/libs/WindowManager/Shell/tests/OWNERS
index deebad5..d718e15 100644
--- a/libs/WindowManager/Shell/tests/OWNERS
+++ b/libs/WindowManager/Shell/tests/OWNERS
@@ -9,3 +9,6 @@
 chenghsiuchang@google.com
 atsjenk@google.com
 jorgegil@google.com
+nmusgrave@google.com
+pbdr@google.com
+tkachenkoi@google.com
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/MapsEnterPipTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/MapsEnterPipTest.kt
index d06cf77..e272958 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/MapsEnterPipTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/MapsEnterPipTest.kt
@@ -105,7 +105,8 @@
             )
             locationManager.setTestProviderEnabled(LocationManager.GPS_PROVIDER, true)
             mockLocationEnabled = true
-            mainHandler.post(updateLocation)
+            // postpone first location update to make sure GPS is set as test provider
+            mainHandler.postDelayed(updateLocation, 200)
 
             // normal app open through the Launcher All Apps
             // var mapsAddressOption = "Golden Gate Bridge"
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
index 0395a9b..771876f 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
@@ -182,8 +182,7 @@
     }
 
     private void triggerBackGesture() {
-        doMotionEvent(MotionEvent.ACTION_DOWN, 0);
-        doMotionEvent(MotionEvent.ACTION_MOVE, 0);
+        doStartEvents(0, 0);
         mController.setTriggerBack(true);
     }
 
@@ -244,10 +243,7 @@
                 /* enableAnimation = */ true,
                 /* isAnimationCallback = */ false);
 
-        doMotionEvent(MotionEvent.ACTION_DOWN, 0);
-
-        // Check that back start and progress is dispatched when first move.
-        doMotionEvent(MotionEvent.ACTION_MOVE, 100);
+        doStartEvents(0, 100);
 
         simulateRemoteAnimationStart();
 
@@ -270,10 +266,8 @@
                 /* enableAnimation = */ true,
                 /* isAnimationCallback = */ true);
 
-        doMotionEvent(MotionEvent.ACTION_DOWN, 0);
-
         // Check that back start and progress is dispatched when first move.
-        doMotionEvent(MotionEvent.ACTION_MOVE, 100, 3000);
+        doStartEvents(0, 100);
 
         simulateRemoteAnimationStart();
 
@@ -359,8 +353,7 @@
                 .injectInputEvent(any(KeyEvent.class), any(Integer.class));
 
         // Verify that we start accepting gestures again once transition finishes.
-        doMotionEvent(MotionEvent.ACTION_DOWN, 0);
-        doMotionEvent(MotionEvent.ACTION_MOVE, 100);
+        doStartEvents(0, 100);
 
         simulateRemoteAnimationStart();
         verify(mAnimatorCallback).onBackStarted(any());
@@ -399,8 +392,7 @@
                 .injectInputEvent(any(KeyEvent.class), any(Integer.class));
 
         // Verify that we start accepting gestures again once transition finishes.
-        doMotionEvent(MotionEvent.ACTION_DOWN, 0);
-        doMotionEvent(MotionEvent.ACTION_MOVE, 100);
+        doStartEvents(0, 100);
 
         simulateRemoteAnimationStart();
         verify(mAnimatorCallback).onBackStarted(any());
@@ -427,8 +419,7 @@
         mShellExecutor.flushAll();
         reset(mAnimatorCallback);
 
-        doMotionEvent(MotionEvent.ACTION_DOWN, 0);
-        doMotionEvent(MotionEvent.ACTION_MOVE, 100);
+        doStartEvents(0, 100);
         simulateRemoteAnimationStart();
         verify(mAnimatorCallback).onBackStarted(any());
     }
@@ -441,9 +432,7 @@
                 /* enableAnimation = */ true,
                 /* isAnimationCallback = */ false);
 
-        doMotionEvent(MotionEvent.ACTION_DOWN, 0);
-        // Check that back start and progress is dispatched when first move.
-        doMotionEvent(MotionEvent.ACTION_MOVE, 100);
+        doStartEvents(0, 100);
 
         simulateRemoteAnimationStart();
         verify(mAnimatorCallback).onBackStarted(any());
@@ -563,10 +552,8 @@
                 /* enableAnimation = */ true,
                 /* isAnimationCallback = */ false);
 
-        doMotionEvent(MotionEvent.ACTION_DOWN, 0);
-
         // Check that back start and progress is dispatched when first move.
-        doMotionEvent(MotionEvent.ACTION_MOVE, 100);
+        doStartEvents(0, 100);
 
         simulateRemoteAnimationStart();
 
@@ -593,6 +580,15 @@
                 /* swipeEdge */ BackEvent.EDGE_LEFT);
     }
 
+    /**
+     * Simulate event sequence that starts a back navigation.
+     */
+    private void doStartEvents(int startX, int moveX) {
+        doMotionEvent(MotionEvent.ACTION_DOWN, startX);
+        mController.onPilferPointers();
+        doMotionEvent(MotionEvent.ACTION_MOVE, moveX);
+    }
+
     private void simulateRemoteAnimationStart() throws RemoteException {
         RemoteAnimationTarget animationTarget = createAnimationTarget();
         RemoteAnimationTarget[] targets = new RemoteAnimationTarget[]{animationTarget};
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java
index 4bca96b..dab762f 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java
@@ -221,6 +221,22 @@
     }
 
     @Test
+    public void testAddAppBubble_setsTime() {
+        // Setup
+        mBubbleData.setListener(mListener);
+
+        // Test
+        assertThat(mAppBubble.getLastActivity()).isEqualTo(0);
+        setCurrentTime(1000);
+        mBubbleData.notificationEntryUpdated(mAppBubble, true /* suppressFlyout*/,
+                false /* showInShade */);
+
+        // Verify
+        assertThat(mBubbleData.getBubbleInStackWithKey(mAppBubble.getKey())).isEqualTo(mAppBubble);
+        assertThat(mAppBubble.getLastActivity()).isEqualTo(1000);
+    }
+
+    @Test
     public void testRemoveBubble() {
         // Setup
         sendUpdatedEntryAtTime(mEntryA1, 1000);
@@ -1162,7 +1178,7 @@
     }
 
     @Test
-    public void test_removeAppBubble_skipsOverflow() {
+    public void test_removeAppBubble_overflows() {
         String appBubbleKey = mAppBubble.getKey();
         mBubbleData.notificationEntryUpdated(mAppBubble, true /* suppressFlyout*/,
                 false /* showInShade */);
@@ -1170,7 +1186,7 @@
 
         mBubbleData.dismissBubbleWithKey(appBubbleKey, Bubbles.DISMISS_USER_GESTURE);
 
-        assertThat(mBubbleData.getOverflowBubbleWithKey(appBubbleKey)).isNull();
+        assertThat(mBubbleData.getOverflowBubbleWithKey(appBubbleKey)).isEqualTo(mAppBubble);
         assertThat(mBubbleData.getBubbleInStackWithKey(appBubbleKey)).isNull();
     }
 
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/DividerViewTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/DividerViewTest.java
index 145c8f0..636c632 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/DividerViewTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/DividerViewTest.java
@@ -69,7 +69,7 @@
         SplitWindowManager splitWindowManager = new SplitWindowManager("TestSplitWindowManager",
                 mContext,
                 configuration, mCallbacks);
-        splitWindowManager.init(mSplitLayout, new InsetsState());
+        splitWindowManager.init(mSplitLayout, new InsetsState(), false /* isRestoring */);
         mDividerView = spy((DividerView) splitWindowManager.getDividerView());
     }
 
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java
index 2e5078d..150aa13 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java
@@ -59,7 +59,7 @@
     @Test
     @UiThreadTest
     public void testInitRelease() {
-        mSplitWindowManager.init(mSplitLayout, new InsetsState());
+        mSplitWindowManager.init(mSplitLayout, new InsetsState(), false /* isRestoring */);
         assertThat(mSplitWindowManager.getSurfaceControl()).isNotNull();
         mSplitWindowManager.release(null /* t */);
         assertThat(mSplitWindowManager.getSurfaceControl()).isNull();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManagerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManagerTest.java
index 0652939..9fe2cb1 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManagerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/UserAspectRatioSettingsWindowManagerTest.java
@@ -16,6 +16,9 @@
 
 package com.android.wm.shell.compatui;
 
+import static android.content.Intent.ACTION_MAIN;
+import static android.content.Intent.CATEGORY_LAUNCHER;
+import static android.hardware.usb.UsbManager.ACTION_USB_STATE;
 import static android.view.WindowInsets.Type.navigationBars;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
@@ -33,6 +36,7 @@
 import android.app.ActivityManager;
 import android.app.TaskInfo;
 import android.content.ComponentName;
+import android.content.Intent;
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.testing.AndroidTestingRunner;
@@ -108,7 +112,7 @@
         MockitoAnnotations.initMocks(this);
         mExecutor = new TestShellExecutor();
         mTaskInfo = createTaskInfo(/* eligibleForUserAspectRatioButton= */
-                false, /* topActivityBoundsLetterboxed */ true);
+                false, /* topActivityBoundsLetterboxed */ true, ACTION_MAIN, CATEGORY_LAUNCHER);
         mWindowManager = new UserAspectRatioSettingsWindowManager(mContext, mTaskInfo,
                 mSyncTransactionQueue, mTaskListener, new DisplayLayout(), new CompatUIHintsState(),
                 mOnUserAspectRatioSettingsButtonClicked, mExecutor, flags -> 0,
@@ -179,7 +183,7 @@
         // No diff
         clearInvocations(mWindowManager);
         TaskInfo taskInfo = createTaskInfo(/* eligibleForUserAspectRatioButton= */
-                true, /* topActivityBoundsLetterboxed */ true);
+                true, /* topActivityBoundsLetterboxed */ true, ACTION_MAIN, CATEGORY_LAUNCHER);
         assertTrue(mWindowManager.updateCompatInfo(taskInfo, mTaskListener, /* canShow= */ true));
 
         verify(mWindowManager, never()).updateSurfacePosition();
@@ -200,7 +204,24 @@
         clearInvocations(mWindowManager);
         clearInvocations(mLayout);
         taskInfo = createTaskInfo(/* eligibleForUserAspectRatioButton= */
-                false, /* topActivityBoundsLetterboxed */ true);
+                false, /* topActivityBoundsLetterboxed */ true, ACTION_MAIN, CATEGORY_LAUNCHER);
+        assertFalse(
+                mWindowManager.updateCompatInfo(taskInfo, newTaskListener, /* canShow= */ true));
+        verify(mWindowManager).release();
+
+        // Recreate button
+        clearInvocations(mWindowManager);
+        taskInfo = createTaskInfo(/* eligibleForUserAspectRatioButton= */
+                true, /* topActivityBoundsLetterboxed */ true, ACTION_MAIN, CATEGORY_LAUNCHER);
+        assertTrue(mWindowManager.updateCompatInfo(taskInfo, newTaskListener, /* canShow= */ true));
+
+        verify(mWindowManager).release();
+        verify(mWindowManager).createLayout(/* canShow= */ true);
+
+        // Change has no launcher category and is not main intent, dispose the component
+        clearInvocations(mWindowManager);
+        taskInfo = createTaskInfo(/* eligibleForUserAspectRatioButton= */
+                true, /* topActivityBoundsLetterboxed */ true, ACTION_USB_STATE, "");
         assertFalse(
                 mWindowManager.updateCompatInfo(taskInfo, newTaskListener, /* canShow= */ true));
         verify(mWindowManager).release();
@@ -217,7 +238,7 @@
         // inflated
         clearInvocations(mWindowManager);
         TaskInfo taskInfo = createTaskInfo(/* eligibleForUserAspectRatioButton= */
-                false, /* topActivityBoundsLetterboxed */ true);
+                false, /* topActivityBoundsLetterboxed */ true, ACTION_MAIN, CATEGORY_LAUNCHER);
         mWindowManager.updateCompatInfo(taskInfo, mTaskListener, /* canShow= */ true);
 
         verify(mWindowManager, never()).inflateLayout();
@@ -225,7 +246,7 @@
         // Change topActivityInSizeCompat to true and pass canShow true, layout should be inflated.
         clearInvocations(mWindowManager);
         taskInfo = createTaskInfo(/* eligibleForUserAspectRatioButton= */
-                true, /* topActivityBoundsLetterboxed */ true);
+                true, /* topActivityBoundsLetterboxed */ true, ACTION_MAIN, CATEGORY_LAUNCHER);
         mWindowManager.updateCompatInfo(taskInfo, mTaskListener, /* canShow= */ true);
 
         verify(mWindowManager).inflateLayout();
@@ -304,7 +325,7 @@
         clearInvocations(mWindowManager);
         spyOn(mWindowManager);
         TaskInfo taskInfo = createTaskInfo(/* eligibleForUserAspectRatioButton= */
-                true, /* topActivityBoundsLetterboxed */ true);
+                true, /* topActivityBoundsLetterboxed */ true, ACTION_MAIN, CATEGORY_LAUNCHER);
 
         // User aspect ratio settings button has not yet been shown.
         doReturn(false).when(mUserAspectRatioButtonShownChecker).get();
@@ -378,7 +399,7 @@
     }
 
     private static TaskInfo createTaskInfo(boolean eligibleForUserAspectRatioButton,
-            boolean topActivityBoundsLetterboxed) {
+            boolean topActivityBoundsLetterboxed, String action, String category) {
         ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo();
         taskInfo.taskId = TASK_ID;
         taskInfo.appCompatTaskInfo.topActivityEligibleForUserAspectRatioButton =
@@ -386,6 +407,7 @@
         taskInfo.appCompatTaskInfo.topActivityBoundsLetterboxed = topActivityBoundsLetterboxed;
         taskInfo.configuration.uiMode &= ~Configuration.UI_MODE_TYPE_DESK;
         taskInfo.realActivity = new ComponentName("com.mypackage.test", "TestActivity");
+        taskInfo.baseIntent = new Intent(action).addCategory(category);
         return taskInfo;
     }
 }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java
index 99cd4f3..855b7ee 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java
@@ -235,7 +235,7 @@
         mSplitScreenController.startIntent(pendingIntent, mContext.getUserId(), null,
                 SPLIT_POSITION_TOP_OR_LEFT, null);
 
-        verify(mSplitScreenController).startTask(anyInt(), eq(SPLIT_POSITION_TOP_OR_LEFT),
+        verify(mStageCoordinator).startTask(anyInt(), eq(SPLIT_POSITION_TOP_OR_LEFT),
                 isNull());
         verify(mSplitScreenController, never()).supportMultiInstancesSplit(any());
         verify(mStageCoordinator, never()).switchSplitPosition(any());
@@ -243,7 +243,6 @@
 
     @Test
     public void startIntent_multiInstancesSupported_startTaskInBackgroundAfterSplitActivated() {
-        doReturn(true).when(mSplitScreenController).supportMultiInstancesSplit(any());
         doNothing().when(mSplitScreenController).startTask(anyInt(), anyInt(), any());
         Intent startIntent = createStartIntent("startActivity");
         PendingIntent pendingIntent =
@@ -260,8 +259,8 @@
 
         mSplitScreenController.startIntent(pendingIntent, mContext.getUserId(), null,
                 SPLIT_POSITION_TOP_OR_LEFT, null);
-
-        verify(mSplitScreenController).startTask(anyInt(), eq(SPLIT_POSITION_TOP_OR_LEFT),
+        verify(mSplitScreenController, never()).supportMultiInstancesSplit(any());
+        verify(mStageCoordinator).startTask(anyInt(), eq(SPLIT_POSITION_TOP_OR_LEFT),
                 isNull());
     }
 
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 421c445..66efa02 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
@@ -40,12 +40,12 @@
 import android.view.SurfaceControl;
 import android.window.TransitionInfo;
 import android.window.TransitionInfo.TransitionMode;
-import android.window.WindowOrganizer;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
 
+import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.ShellTestCase;
 import com.android.wm.shell.TestShellExecutor;
 import com.android.wm.shell.common.DisplayController;
@@ -68,7 +68,7 @@
 @RunWith(AndroidJUnit4.class)
 public class HomeTransitionObserverTest extends ShellTestCase {
 
-    private final WindowOrganizer mOrganizer = mock(WindowOrganizer.class);
+    private final ShellTaskOrganizer mOrganizer = mock(ShellTaskOrganizer.class);
     private final TransactionPool mTransactionPool = mock(TransactionPool.class);
     private final Context mContext =
             InstrumentationRegistry.getInstrumentation().getTargetContext();
@@ -101,7 +101,7 @@
         when(change.getTaskInfo()).thenReturn(taskInfo);
         when(info.getChanges()).thenReturn(new ArrayList<>(List.of(change)));
 
-        setupTransitionInfo(taskInfo, change, ACTIVITY_TYPE_HOME, TRANSIT_OPEN);
+        setupTransitionInfo(taskInfo, change, ACTIVITY_TYPE_HOME, TRANSIT_OPEN, true);
 
         mHomeTransitionObserver.onTransitionReady(mock(IBinder.class),
                 info,
@@ -119,7 +119,7 @@
         when(change.getTaskInfo()).thenReturn(taskInfo);
         when(info.getChanges()).thenReturn(new ArrayList<>(List.of(change)));
 
-        setupTransitionInfo(taskInfo, change, ACTIVITY_TYPE_HOME, TRANSIT_TO_BACK);
+        setupTransitionInfo(taskInfo, change, ACTIVITY_TYPE_HOME, TRANSIT_TO_BACK, true);
 
         mHomeTransitionObserver.onTransitionReady(mock(IBinder.class),
                 info,
@@ -137,7 +137,25 @@
         when(change.getTaskInfo()).thenReturn(taskInfo);
         when(info.getChanges()).thenReturn(new ArrayList<>(List.of(change)));
 
-        setupTransitionInfo(taskInfo, change, ACTIVITY_TYPE_UNDEFINED, TRANSIT_TO_BACK);
+        setupTransitionInfo(taskInfo, change, ACTIVITY_TYPE_UNDEFINED, TRANSIT_TO_BACK, true);
+
+        mHomeTransitionObserver.onTransitionReady(mock(IBinder.class),
+                info,
+                mock(SurfaceControl.Transaction.class),
+                mock(SurfaceControl.Transaction.class));
+
+        verify(mListener, times(0)).onHomeVisibilityChanged(anyBoolean());
+    }
+
+    @Test
+    public void testNonRunningHomeActivityDoesNotTriggerCallback() throws RemoteException {
+        TransitionInfo info = mock(TransitionInfo.class);
+        TransitionInfo.Change change = mock(TransitionInfo.Change.class);
+        ActivityManager.RunningTaskInfo taskInfo = mock(ActivityManager.RunningTaskInfo.class);
+        when(change.getTaskInfo()).thenReturn(taskInfo);
+        when(info.getChanges()).thenReturn(new ArrayList<>(List.of(change)));
+
+        setupTransitionInfo(taskInfo, change, ACTIVITY_TYPE_UNDEFINED, TRANSIT_TO_BACK, false);
 
         mHomeTransitionObserver.onTransitionReady(mock(IBinder.class),
                 info,
@@ -156,7 +174,7 @@
         when(info.getChanges()).thenReturn(new ArrayList<>(List.of(change)));
 
         when(change.hasFlags(FLAG_BACK_GESTURE_ANIMATED)).thenReturn(true);
-        setupTransitionInfo(taskInfo, change, ACTIVITY_TYPE_HOME, TRANSIT_CHANGE);
+        setupTransitionInfo(taskInfo, change, ACTIVITY_TYPE_HOME, TRANSIT_CHANGE, true);
 
         mHomeTransitionObserver.onTransitionReady(mock(IBinder.class),
                 info,
@@ -166,16 +184,16 @@
         verify(mListener, times(1)).onHomeVisibilityChanged(true);
     }
 
-
     /**
      * Helper class to initialize variables for the rest.
      */
     private void setupTransitionInfo(ActivityManager.RunningTaskInfo taskInfo,
             TransitionInfo.Change change,
             @ActivityType int activityType,
-            @TransitionMode int mode) {
+            @TransitionMode int mode,
+            boolean isRunning) {
         when(taskInfo.getActivityType()).thenReturn(activityType);
         when(change.getMode()).thenReturn(mode);
+        taskInfo.isRunning = isRunning;
     }
-
 }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
index 01c9bd0..e22bf3d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
@@ -87,7 +87,6 @@
 import android.window.TransitionRequestInfo;
 import android.window.WindowContainerToken;
 import android.window.WindowContainerTransaction;
-import android.window.WindowOrganizer;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -98,6 +97,7 @@
 import com.android.internal.R;
 import com.android.internal.policy.TransitionAnimation;
 import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
+import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.ShellTestCase;
 import com.android.wm.shell.TestShellExecutor;
 import com.android.wm.shell.common.DisplayController;
@@ -130,7 +130,7 @@
 @RunWith(AndroidJUnit4.class)
 public class ShellTransitionTests extends ShellTestCase {
 
-    private final WindowOrganizer mOrganizer = mock(WindowOrganizer.class);
+    private final ShellTaskOrganizer mOrganizer = mock(ShellTaskOrganizer.class);
     private final TransactionPool mTransactionPool = mock(TransactionPool.class);
     private final Context mContext =
             InstrumentationRegistry.getInstrumentation().getTargetContext();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/unfold/UnfoldTransitionHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/unfold/UnfoldTransitionHandlerTest.java
index 6d73c12..c5e229f 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/unfold/UnfoldTransitionHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/unfold/UnfoldTransitionHandlerTest.java
@@ -18,12 +18,11 @@
 
 import static android.view.WindowManager.TRANSIT_CHANGE;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
+import static android.view.WindowManager.TRANSIT_FLAG_PHYSICAL_DISPLAY_SWITCH;
 import static android.view.WindowManager.TRANSIT_NONE;
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.junit.Assume.assumeFalse;
-import static org.junit.Assume.assumeTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.mock;
@@ -40,22 +39,17 @@
 import android.window.TransitionRequestInfo;
 import android.window.WindowContainerTransaction;
 
-import com.android.window.flags.FakeFeatureFlagsImpl;
-import com.android.window.flags.FeatureFlags;
-import com.android.window.flags.Flags;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.TransactionPool;
 import com.android.wm.shell.sysui.ShellInit;
-import com.android.wm.shell.transition.Transitions;
 import com.android.wm.shell.transition.TransitionInfoBuilder;
+import com.android.wm.shell.transition.Transitions;
 import com.android.wm.shell.transition.Transitions.TransitionFinishCallback;
 import com.android.wm.shell.unfold.animation.FullscreenUnfoldTaskAnimator;
 import com.android.wm.shell.unfold.animation.SplitTaskUnfoldAnimator;
 
 import org.junit.Before;
 import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -98,10 +92,13 @@
     }
 
     @Test
-    public void handleRequest_physicalDisplayChange_handlesTransition() {
+    public void handleRequest_physicalDisplayChangeUnfold_handlesTransition() {
         ActivityManager.RunningTaskInfo triggerTaskInfo = new ActivityManager.RunningTaskInfo();
         TransitionRequestInfo.DisplayChange displayChange = new TransitionRequestInfo.DisplayChange(
-                Display.DEFAULT_DISPLAY).setPhysicalDisplayChanged(true);
+                Display.DEFAULT_DISPLAY)
+                .setPhysicalDisplayChanged(true)
+                .setStartAbsBounds(new Rect(0, 0, 100, 100))
+                .setEndAbsBounds(new Rect(0, 0, 200, 200));
         TransitionRequestInfo requestInfo = new TransitionRequestInfo(TRANSIT_CHANGE,
                 triggerTaskInfo, /* remoteTransition= */ null, displayChange, 0 /* flags */);
 
@@ -112,6 +109,23 @@
     }
 
     @Test
+    public void handleRequest_physicalDisplayChangeFold_doesNotHandleTransition() {
+        ActivityManager.RunningTaskInfo triggerTaskInfo = new ActivityManager.RunningTaskInfo();
+        TransitionRequestInfo.DisplayChange displayChange = new TransitionRequestInfo.DisplayChange(
+                Display.DEFAULT_DISPLAY)
+                .setPhysicalDisplayChanged(true)
+                .setStartAbsBounds(new Rect(0, 0, 200, 200))
+                .setEndAbsBounds(new Rect(0, 0, 100, 100));
+        TransitionRequestInfo requestInfo = new TransitionRequestInfo(TRANSIT_CHANGE,
+                triggerTaskInfo, /* remoteTransition= */ null, displayChange, 0 /* flags */);
+
+        WindowContainerTransaction result = mUnfoldTransitionHandler.handleRequest(mTransition,
+                requestInfo);
+
+        assertThat(result).isNull();
+    }
+
+    @Test
     public void handleRequest_noPhysicalDisplayChange_doesNotHandleTransition() {
         ActivityManager.RunningTaskInfo triggerTaskInfo = new ActivityManager.RunningTaskInfo();
         TransitionRequestInfo.DisplayChange displayChange = new TransitionRequestInfo.DisplayChange(
@@ -176,6 +190,22 @@
     }
 
     @Test
+    public void startAnimation_differentTransitionFromRequestWithResize_doesNotStartAnimation() {
+        mUnfoldTransitionHandler.handleRequest(new Binder(), createNoneTransitionInfo());
+        TransitionFinishCallback finishCallback = mock(TransitionFinishCallback.class);
+
+        boolean animationStarted = mUnfoldTransitionHandler.startAnimation(
+                mTransition,
+                createDisplayResizeTransitionInfo(),
+                mock(SurfaceControl.Transaction.class),
+                mock(SurfaceControl.Transaction.class),
+                finishCallback
+        );
+
+        assertThat(animationStarted).isFalse();
+    }
+
+    @Test
     public void startAnimation_differentTransitionFromRequestWithoutUnfold_doesNotStart() {
         mUnfoldTransitionHandler.handleRequest(new Binder(), createNoneTransitionInfo());
         TransitionFinishCallback finishCallback = mock(TransitionFinishCallback.class);
@@ -306,7 +336,10 @@
     private TransitionRequestInfo createUnfoldTransitionRequestInfo() {
         ActivityManager.RunningTaskInfo triggerTaskInfo = new ActivityManager.RunningTaskInfo();
         TransitionRequestInfo.DisplayChange displayChange = new TransitionRequestInfo.DisplayChange(
-                Display.DEFAULT_DISPLAY).setPhysicalDisplayChanged(true);
+                Display.DEFAULT_DISPLAY)
+                .setPhysicalDisplayChanged(true)
+                .setStartAbsBounds(new Rect(0, 0, 100, 100))
+                .setEndAbsBounds(new Rect(0, 0, 200, 200));
         return new TransitionRequestInfo(TRANSIT_CHANGE,
                 triggerTaskInfo, /* remoteTransition= */ null, displayChange, 0 /* flags */);
     }
@@ -380,24 +413,18 @@
         }
     }
 
-    static class TestCase {
-        private final boolean mShouldHandleMixedUnfold;
-
-        public TestCase(boolean shouldHandleMixedUnfold) {
-            mShouldHandleMixedUnfold = shouldHandleMixedUnfold;
-        }
-
-        public boolean mixedUnfoldFlagEnabled() {
-            return mShouldHandleMixedUnfold;
-        }
-
-        @Override
-        public String toString() {
-            return "shouldHandleMixedUnfold flag = " + mShouldHandleMixedUnfold;
-        }
+    private TransitionInfo createUnfoldTransitionInfo() {
+        TransitionInfo transitionInfo = new TransitionInfo(TRANSIT_CHANGE, /* flags= */ 0);
+        TransitionInfo.Change change = new TransitionInfo.Change(null, mock(SurfaceControl.class));
+        change.setStartAbsBounds(new Rect(0, 0, 10, 10));
+        change.setEndAbsBounds(new Rect(0, 0, 100, 100));
+        change.setFlags(TransitionInfo.FLAG_IS_DISPLAY);
+        transitionInfo.addChange(change);
+        transitionInfo.setFlags(TRANSIT_FLAG_PHYSICAL_DISPLAY_SWITCH);
+        return transitionInfo;
     }
 
-    private TransitionInfo createUnfoldTransitionInfo() {
+    private TransitionInfo createDisplayResizeTransitionInfo() {
         TransitionInfo transitionInfo = new TransitionInfo(TRANSIT_CHANGE, /* flags= */ 0);
         TransitionInfo.Change change = new TransitionInfo.Change(null, mock(SurfaceControl.class));
         change.setStartAbsBounds(new Rect(0, 0, 10, 10));
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 79a7357..4741170 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -79,14 +79,6 @@
         "external/skia/src/core",
     ],
 
-    product_variables: {
-        eng: {
-            lto: {
-                never: true,
-            },
-        },
-    },
-
     target: {
         android: {
             include_dirs: [
diff --git a/libs/hwui/jni/YuvToJpegEncoder.cpp b/libs/hwui/jni/YuvToJpegEncoder.cpp
index 0275e4f..3533001 100644
--- a/libs/hwui/jni/YuvToJpegEncoder.cpp
+++ b/libs/hwui/jni/YuvToJpegEncoder.cpp
@@ -401,7 +401,7 @@
     if (int success = jpegREncoder.encodeJPEGR(&p010, &yuv420,
             hdrTransferFunction,
             &jpegR, jpegQuality,
-            exif.length > 0 ? &exif : NULL); success != android::OK) {
+            exif.length > 0 ? &exif : NULL); success != JPEGR_NO_ERROR) {
         ALOGW("Encode JPEG/R failed, error code: %d.", success);
         return false;
     }
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 94f35fd..facf30b 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -37,6 +37,9 @@
 // Android-specific addition that is used to show when frames began in systrace
 EGLAPI void EGLAPIENTRY eglBeginFrame(EGLDisplay dpy, EGLSurface surface);
 
+static constexpr auto P3_XRB = static_cast<android_dataspace>(
+        ADATASPACE_STANDARD_DCI_P3 | ADATASPACE_TRANSFER_SRGB | ADATASPACE_RANGE_EXTENDED);
+
 namespace android {
 namespace uirenderer {
 namespace renderthread {
@@ -497,9 +500,7 @@
         // This relies on knowing that EGL will not re-set the dataspace after the call to
         // eglCreateWindowSurface. Since the handling of the colorspace extension is largely
         // implemented in libEGL in the platform, we can safely assume this is the case
-        int32_t err = ANativeWindow_setBuffersDataSpace(
-                window,
-                static_cast<android_dataspace>(STANDARD_DCI_P3 | TRANSFER_SRGB | RANGE_EXTENDED));
+        int32_t err = ANativeWindow_setBuffersDataSpace(window, P3_XRB);
         LOG_ALWAYS_FATAL_IF(err, "Failed to ANativeWindow_setBuffersDataSpace %d", err);
     }
 
diff --git a/libs/hwui/renderthread/VulkanSurface.cpp b/libs/hwui/renderthread/VulkanSurface.cpp
index 20b743b..a8e8547 100644
--- a/libs/hwui/renderthread/VulkanSurface.cpp
+++ b/libs/hwui/renderthread/VulkanSurface.cpp
@@ -29,6 +29,9 @@
 namespace uirenderer {
 namespace renderthread {
 
+static constexpr auto P3_XRB = static_cast<android_dataspace>(
+        ADATASPACE_STANDARD_DCI_P3 | ADATASPACE_TRANSFER_SRGB | ADATASPACE_RANGE_EXTENDED);
+
 static int InvertTransform(int transform) {
     switch (transform) {
         case ANATIVEWINDOW_TRANSFORM_ROTATE_90:
@@ -214,8 +217,7 @@
     outWindowInfo->colorMode = colorMode;
 
     if (colorMode == ColorMode::Hdr || colorMode == ColorMode::Hdr10) {
-        outWindowInfo->dataspace =
-                static_cast<android_dataspace>(STANDARD_DCI_P3 | TRANSFER_SRGB | RANGE_EXTENDED);
+        outWindowInfo->dataspace = P3_XRB;
     } else {
         outWindowInfo->dataspace = ColorSpaceToADataSpace(colorSpace.get(), colorType);
     }
@@ -541,8 +543,7 @@
     }
 
     if (mWindowInfo.colorMode == ColorMode::Hdr || mWindowInfo.colorMode == ColorMode::Hdr10) {
-        mWindowInfo.dataspace =
-                static_cast<android_dataspace>(STANDARD_DCI_P3 | TRANSFER_SRGB | RANGE_EXTENDED);
+        mWindowInfo.dataspace = P3_XRB;
     } else {
         mWindowInfo.dataspace = ColorSpaceToADataSpace(
                 mWindowInfo.colorspace.get(), BufferFormatToColorType(mWindowInfo.bufferFormat));
diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp
index 65e1605..bba9c97 100644
--- a/libs/input/PointerController.cpp
+++ b/libs/input/PointerController.cpp
@@ -218,6 +218,15 @@
 
     mLocked.presentation = presentation;
 
+    if (input_flags::enable_pointer_choreographer()) {
+        // When pointer choreographer is enabled, the presentation mode is only set once when the
+        // PointerController is constructed, before the display viewport is provided.
+        // TODO(b/293587049): Clean up the PointerController interface after pointer choreographer
+        // is permanently enabled. The presentation can be set in the constructor.
+        mCursorController.setStylusHoverMode(presentation == Presentation::STYLUS_HOVER);
+        return;
+    }
+
     if (!mCursorController.isViewportValid()) {
         return;
     }
diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp
index 8445032..69718a6 100644
--- a/libs/input/tests/Android.bp
+++ b/libs/input/tests/Android.bp
@@ -43,12 +43,15 @@
     },
     shared_libs: [
         "libandroid_runtime",
+        "libbase",
+        "libinput",
         "libinputservice",
         "libhwui",
         "libgui",
         "libutils",
     ],
     static_libs: [
+        "libflagtest",
         "libgmock",
         "libgtest",
     ],
diff --git a/libs/input/tests/PointerController_test.cpp b/libs/input/tests/PointerController_test.cpp
index d9efd3c..adfa91e 100644
--- a/libs/input/tests/PointerController_test.cpp
+++ b/libs/input/tests/PointerController_test.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include <com_android_input_flags.h>
+#include <flag_macros.h>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 #include <input/PointerController.h>
@@ -28,6 +30,8 @@
 
 namespace android {
 
+namespace input_flags = com::android::input::flags;
+
 enum TestCursorType {
     CURSOR_TYPE_DEFAULT = 0,
     CURSOR_TYPE_HOVER,
@@ -261,7 +265,20 @@
     mPointerController->reloadPointerResources();
 }
 
-TEST_F(PointerControllerTest, updatePointerIcon) {
+TEST_F_WITH_FLAGS(PointerControllerTest, setPresentationBeforeDisplayViewportDoesNotLoadResources,
+                  REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(input_flags, enable_pointer_choreographer))) {
+    // Setting the presentation mode before a display viewport is set will not load any resources.
+    mPointerController->setPresentation(PointerController::Presentation::POINTER);
+    ASSERT_TRUE(mPolicy->noResourcesAreLoaded());
+
+    // When the display is set, then the resources are loaded.
+    ensureDisplayViewportIsSet();
+    ASSERT_TRUE(mPolicy->allResourcesAreLoaded());
+}
+
+TEST_F_WITH_FLAGS(PointerControllerTest, updatePointerIcon,
+                  REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(input_flags,
+                                                       enable_pointer_choreographer))) {
     ensureDisplayViewportIsSet();
     mPointerController->setPresentation(PointerController::Presentation::POINTER);
     mPointerController->unfade(PointerController::Transition::IMMEDIATE);
@@ -277,6 +294,24 @@
     mPointerController->updatePointerIcon(static_cast<PointerIconStyle>(type));
 }
 
+TEST_F_WITH_FLAGS(PointerControllerTest, updatePointerIconWithChoreographer,
+                  REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(input_flags, enable_pointer_choreographer))) {
+    // When PointerChoreographer is enabled, the presentation mode is set before the viewport.
+    mPointerController->setPresentation(PointerController::Presentation::POINTER);
+    ensureDisplayViewportIsSet();
+    mPointerController->unfade(PointerController::Transition::IMMEDIATE);
+
+    int32_t type = CURSOR_TYPE_ADDITIONAL;
+    std::pair<float, float> hotspot = getHotSpotCoordinatesForType(type);
+    EXPECT_CALL(*mPointerSprite, setVisible(true));
+    EXPECT_CALL(*mPointerSprite, setAlpha(1.0f));
+    EXPECT_CALL(*mPointerSprite,
+                setIcon(AllOf(Field(&SpriteIcon::style, static_cast<PointerIconStyle>(type)),
+                              Field(&SpriteIcon::hotSpotX, hotspot.first),
+                              Field(&SpriteIcon::hotSpotY, hotspot.second))));
+    mPointerController->updatePointerIcon(static_cast<PointerIconStyle>(type));
+}
+
 TEST_F(PointerControllerTest, setCustomPointerIcon) {
     ensureDisplayViewportIsSet();
     mPointerController->unfade(PointerController::Transition::IMMEDIATE);
diff --git a/location/java/android/location/GnssNavigationMessage.java b/location/java/android/location/GnssNavigationMessage.java
index 32e636f..5e3f803 100644
--- a/location/java/android/location/GnssNavigationMessage.java
+++ b/location/java/android/location/GnssNavigationMessage.java
@@ -78,7 +78,7 @@
     public static final int TYPE_GAL_F = 0x0602;
     /**
      * NavIC L5 C/A message contained in the structure.
-     * @deprecated Use {@link #TYPE_IRN_L5} instead.
+     * @deprecated deprecated.
      */
     @Deprecated
     public static final int TYPE_IRN_L5CA = 0x0701;
diff --git a/media/OWNERS b/media/OWNERS
index 4a6648e..994a7b8 100644
--- a/media/OWNERS
+++ b/media/OWNERS
@@ -21,7 +21,6 @@
 include platform/frameworks/av:/media/janitors/media_solutions_OWNERS
 
 # SEO
-sungsoo@google.com
 
 # SEA/KIR/BVE
 jtinker@google.com
diff --git a/media/java/android/media/OWNERS b/media/java/android/media/OWNERS
index bbe5e06..058c5be 100644
--- a/media/java/android/media/OWNERS
+++ b/media/java/android/media/OWNERS
@@ -2,7 +2,6 @@
 fgoldfain@google.com
 elaurent@google.com
 lajos@google.com
-sungsoo@google.com
 jmtrivi@google.com
 
 # go/android-fwk-media-solutions for info on areas of ownership.
diff --git a/media/java/android/media/flags/media_better_together.aconfig b/media/java/android/media/flags/media_better_together.aconfig
index 3c0b002..07f63e5 100644
--- a/media/java/android/media/flags/media_better_together.aconfig
+++ b/media/java/android/media/flags/media_better_together.aconfig
@@ -62,3 +62,10 @@
     description: "Allows clients of privileged MediaRouter2 that hold INTERACT_ACROSS_USERS_FULL to control routing across users."
     bug: "288580225"
 }
+
+flag {
+    name: "enable_use_of_bluetooth_device_get_alias_for_mr2info_get_name"
+    namespace: "media_solutions"
+    description: "Use BluetoothDevice.getAlias to populate the name of Bluetooth MediaRoute2Infos."
+    bug: "314324170"
+}
diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl
index 901ea46..a8ffd2b 100644
--- a/media/java/android/media/tv/ITvInputManager.aidl
+++ b/media/java/android/media/tv/ITvInputManager.aidl
@@ -110,6 +110,10 @@
     void pauseRecording(in IBinder sessionToken, in Bundle params, int userId);
     void resumeRecording(in IBinder sessionToken, in Bundle params, int userId);
 
+    // For playback control
+    void startPlayback(in IBinder sessionToken, int userId);
+    void stopPlayback(in IBinder sessionToken, int mode, int userId);
+
     // For broadcast info
     void requestBroadcastInfo(in IBinder sessionToken, in BroadcastInfoRequest request, int userId);
     void removeBroadcastInfo(in IBinder sessionToken, int id, int userId);
diff --git a/media/java/android/media/tv/ITvInputSession.aidl b/media/java/android/media/tv/ITvInputSession.aidl
index 5246f5c4..e37ee6e 100644
--- a/media/java/android/media/tv/ITvInputSession.aidl
+++ b/media/java/android/media/tv/ITvInputSession.aidl
@@ -63,6 +63,9 @@
     void timeShiftSetMode(int mode);
     void timeShiftEnablePositionTracking(boolean enable);
 
+    void startPlayback();
+    void stopPlayback(int mode);
+
     // For the recording session
     void startRecording(in Uri programUri, in Bundle params);
     void stopRecording();
diff --git a/media/java/android/media/tv/ITvInputSessionWrapper.java b/media/java/android/media/tv/ITvInputSessionWrapper.java
index d749b91..ae3ee65 100644
--- a/media/java/android/media/tv/ITvInputSessionWrapper.java
+++ b/media/java/android/media/tv/ITvInputSessionWrapper.java
@@ -79,6 +79,8 @@
     private static final int DO_TIME_SHIFT_SET_MODE = 30;
     private static final int DO_SET_TV_MESSAGE_ENABLED = 31;
     private static final int DO_NOTIFY_TV_MESSAGE = 32;
+    private static final int DO_STOP_PLAYBACK = 33;
+    private static final int DO_START_PLAYBACK = 34;
 
     private final boolean mIsRecordingSession;
     private final HandlerCaller mCaller;
@@ -286,6 +288,14 @@
                 mTvInputSessionImpl.onTvMessageReceived((Integer) args.arg1, (Bundle) args.arg2);
                 break;
             }
+            case DO_STOP_PLAYBACK: {
+                mTvInputSessionImpl.stopPlayback(msg.arg1);
+                break;
+            }
+            case DO_START_PLAYBACK: {
+                mTvInputSessionImpl.startPlayback();
+                break;
+            }
             default: {
                 Log.w(TAG, "Unhandled message code: " + msg.what);
                 break;
@@ -483,6 +493,17 @@
                 enabled));
     }
 
+    @Override
+    public void stopPlayback(int mode) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_STOP_PLAYBACK, mode));
+    }
+
+    @Override
+    public void startPlayback() {
+        mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_START_PLAYBACK));
+    }
+
+
     private final class TvInputEventReceiver extends InputEventReceiver {
         TvInputEventReceiver(InputChannel inputChannel, Looper looper) {
             super(inputChannel, looper);
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 631ab9a..c685a5a 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -339,6 +339,14 @@
      */
     public static final int VIDEO_UNAVAILABLE_REASON_CAS_UNKNOWN = VIDEO_UNAVAILABLE_REASON_END;
 
+    /**
+     * Reason for {@link TvInputService.Session#notifyVideoUnavailable(int)} and
+     * {@link TvView.TvInputCallback#onVideoUnavailable(String, int)}: Video is unavailable because
+     * it has been stopped by stopPlayback.
+     * @hide
+     */
+    public static final int VIDEO_UNAVAILABLE_REASON_STOPPED = 19;
+
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({TIME_SHIFT_STATUS_UNKNOWN, TIME_SHIFT_STATUS_UNSUPPORTED,
@@ -3302,6 +3310,30 @@
             }
         }
 
+        void stopPlayback(int mode) {
+            if (mToken == null) {
+                Log.w(TAG, "The session has been already released");
+                return;
+            }
+            try {
+                mService.stopPlayback(mToken, mode, mUserId);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+
+        void startPlayback() {
+            if (mToken == null) {
+                Log.w(TAG, "The session has been already released");
+                return;
+            }
+            try {
+                mService.startPlayback(mToken, mUserId);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+
         /**
          * Sends TV messages to the service for testing purposes
          */
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 720d9a6..55fa517 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -34,6 +34,7 @@
 import android.hardware.hdmi.HdmiDeviceInfo;
 import android.media.AudioPresentation;
 import android.media.PlaybackParams;
+import android.media.tv.interactive.TvInteractiveAppService;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Build;
@@ -1531,6 +1532,32 @@
         }
 
         /**
+         * Called when the application requests playback of the Audio, Video, and CC streams to be
+         * stopped, but the metadata should continue to be filtered.
+         *
+         * <p>The metadata that will continue to be filtered includes the PSI
+         * (Program specific information) and SI (Service Information), part of ISO/IEC 13818-1.
+         *
+         * <p> Note that this is different form {@link #timeShiftPause()} as should release the
+         * stream, making it impossible to resume from this position again.
+         * @param mode
+         * @hide
+         */
+        public void onStopPlayback(@TvInteractiveAppService.PlaybackCommandStopMode int mode) {
+        }
+
+        /**
+         * Starts playback of the Audio, Video, and CC streams.
+         *
+         * <p> Note that this is different form {@link #timeShiftResume()} as this is intended to be
+         * used after stopping playback. This is used to restart playback from the current position
+         * in the live broadcast.
+         * @hide
+         */
+        public void onStartPlayback() {
+        }
+
+        /**
          * Called when the application requests to play a given recorded TV program.
          *
          * @param recordedProgramUri The URI of a recorded TV program.
@@ -1993,6 +2020,20 @@
         }
 
         /**
+         * Calls {@link #onStopPlayback(int)}.
+         */
+        void stopPlayback(int mode) {
+            onStopPlayback(mode);
+        }
+
+        /**
+         * Calls {@link #onStartPlayback()}.
+         */
+        void startPlayback() {
+            onStartPlayback();
+        }
+
+        /**
          * Calls {@link #onTimeShiftPlay(Uri)}.
          */
         void timeShiftPlay(Uri recordedProgramUri) {
diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java
index 196b5c3..233f966 100644
--- a/media/java/android/media/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -37,6 +37,7 @@
 import android.media.tv.TvInputManager.Session;
 import android.media.tv.TvInputManager.Session.FinishedInputEventCallback;
 import android.media.tv.TvInputManager.SessionCallback;
+import android.media.tv.interactive.TvInteractiveAppService;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
@@ -643,6 +644,35 @@
         }
     }
 
+    /**
+     * Stops playback of the Audio, Video, and CC streams, but continue filtering the metadata.
+     *
+     * <p>The metadata that will continue to be filtered includes the PSI
+     * (Program specific information) and SI (Service Information), part of ISO/IEC 13818-1.
+     *
+     * <p> Note that this is different form {@link #timeShiftPause()} as this completely drops
+     * the stream, making it impossible to resume from this position again.
+     * @hide
+     */
+    public void stopPlayback(@TvInteractiveAppService.PlaybackCommandStopMode int mode) {
+        if (mSession != null) {
+            mSession.stopPlayback(mode);
+        }
+    }
+
+    /**
+     * Starts playback of the Audio, Video, and CC streams.
+     *
+     * <p> Note that this is different form {@link #timeShiftResume()} as this is intended to be
+     * used after stopping playback. This is used to restart playback from the current position
+     * in the live broadcast.
+     * @hide
+     */
+    public void startPlayback() {
+        if (mSession != null) {
+            mSession.startPlayback();
+        }
+    }
 
     /**
      * Sends TV messages to the session for testing purposes
diff --git a/media/java/android/media/tv/ad/TvAdService.java b/media/java/android/media/tv/ad/TvAdService.java
index 61101f0..6897a78 100644
--- a/media/java/android/media/tv/ad/TvAdService.java
+++ b/media/java/android/media/tv/ad/TvAdService.java
@@ -28,6 +28,14 @@
     private static final String TAG = "TvAdService";
 
     /**
+     * Name under which a TvAdService component publishes information about itself. This meta-data
+     * must reference an XML resource containing an
+     * <code>&lt;{@link android.R.styleable#TvAdService tv-ad-service}&gt;</code> tag.
+     * @hide
+     */
+    public static final String SERVICE_META_DATA = "android.media.tv.ad.service";
+
+    /**
      * Base class for derived classes to implement to provide a TV AD session.
      */
     public abstract static class Session implements KeyEvent.Callback {
diff --git a/packages/CompanionDeviceManager/res/values-af/strings.xml b/packages/CompanionDeviceManager/res/values-af/strings.xml
index 6c54f70..285d2d1 100644
--- a/packages/CompanionDeviceManager/res/values-af/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-af/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Mikrofoon"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Oproeprekords"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Toestelle in die omtrek"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Verander media-uitset"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Foto\'s en media"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Kennisgewings"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Stroming"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Kan foonoproepe maak en bestuur"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Kan foonoproeprekord lees en skryf"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Kan SMS-boodskappe stuur en ontvang"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Kan by jou kontakte ingaan"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Kan by jou kalender ingaan"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Kan oudio opneem"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Kan toestelle in die omtrek opspoor, aan hulle koppel en hul relatiewe posisie bepaal"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Kan alle kennisgewings lees, insluitend inligting soos kontakte, boodskappe en foto\'s"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Stroom jou foon se apps"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Stroom apps en ander stelselkenmerke van jou foon af"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Kry toegang tot ’n lys beskikbare toestelle en beheer watter een oudio of video van ander apps af stroom of uitsaai"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"foon"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tablet"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-am/strings.xml b/packages/CompanionDeviceManager/res/values-am/strings.xml
index d9ddf71..996d2ea 100644
--- a/packages/CompanionDeviceManager/res/values-am/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-am/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"ማይክሮፎን"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"የጥሪ ምዝገባ ማስታወሻዎች"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"በአቅራቢያ ያሉ መሣሪያዎች"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"የሚዲያ ውጤትን ይቀይሩ"</string>
     <string name="permission_storage" msgid="6831099350839392343">"ፎቶዎች እና ሚዲያ"</string>
-    <string name="permission_notification" msgid="693762568127741203">"ማሳወቂያዎች"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"መተግበሪያዎች"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"በዥረት መልቀቅ"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"የስልክ ጥሪዎችን ማድረግ እና ማስተዳደር ይችላል"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"የስልክ ጥሪ ምዝገባ ማስታወሻን ማንበብ እና መጻፍ ይችላል"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"የኤስኤምኤስ መልዕክቶችን መላክ እና ማየት ይችላል"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"ዕውቂያዎችዎን መድረስ ይችላል"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"የቀን መቁጠሪያዎን መድረስ ይችላል"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"ኦዲዮ መቅዳት ይችላል"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"በአቅራቢያ ያሉ መሣሪያዎችን ማግኘት፣ ከእነሱ ጋር መገናኘት እና አንጻራዊ ቦታቸውን መወሰን ይችላል"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"እንደ እውቂያዎች፣ መልዕክቶች እና ፎቶዎች ያሉ መረጃዎችን ጨምሮ ሁሉንም ማሳወቂያዎች ማንበብ ይችላል"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"የስልክዎን መተግበሪያዎች በዥረት ይልቀቁ"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"ከስልክዎ ሆነው መተግበሪያዎች እና ሌሎች የስርዓት ባህሪያትን በዥረት ይልቀቁ"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"የሚገኙትን መሣሪያዎች ዝርዝር ይድረሱ እና የትኛዎቹ ኦዲዮን ወይም ቪዲዮን ከሌሎች መተግበሪያዎች በዥረት እንደሚለቅቁ ይቆጣጠሩ"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"ስልክ"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"ጡባዊ"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-ar/strings.xml b/packages/CompanionDeviceManager/res/values-ar/strings.xml
index 8a6f227..58cf926 100644
--- a/packages/CompanionDeviceManager/res/values-ar/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ar/strings.xml
@@ -54,21 +54,36 @@
     <string name="permission_microphone" msgid="2152206421428732949">"الميكروفون"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"سجلّ المكالمات"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"الأجهزة المجاورة"</string>
+    <!-- no translation found for permission_media_routing_control (5498639511586715253) -->
+    <skip />
     <string name="permission_storage" msgid="6831099350839392343">"الصور والوسائط"</string>
-    <string name="permission_notification" msgid="693762568127741203">"الإشعارات"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"التطبيقات"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"البثّ"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"يمكن إجراء المكالمات الهاتفية وإدارتها."</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"يمكن قراءة سجلّ المكالمات الهاتفية والكتابة فيه."</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"يمكن إرسال الرسائل القصيرة وعرضها."</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"يمكن الوصول إلى جهات الاتصال."</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"يمكن الوصول إلى التقويم."</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"يمكنه تسجيل الصوت."</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"يمكن العثور على الموضع النسبي للأجهزة المجاورة والربط بها وتحديدها."</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"يمكن لهذا الملف الشخصي قراءة جميع الإشعارات، بما في ذلك المعلومات، مثل جهات الاتصال والرسائل والصور."</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"بث تطبيقات هاتفك"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"بثّ التطبيقات وميزات النظام الأخرى من هاتفك"</string>
+    <!-- no translation found for permission_media_routing_control_summary (2714631092321412250) -->
+    <skip />
     <string name="device_type" product="default" msgid="8268703872070046263">"هاتف"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"جهاز لوحي"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-as/strings.xml b/packages/CompanionDeviceManager/res/values-as/strings.xml
index 28a06e6..fddc24c 100644
--- a/packages/CompanionDeviceManager/res/values-as/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-as/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"মাইক্ৰ’ফ’ন"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"কল লগ"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"নিকটৱৰ্তী ডিভাইচ"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"মিডিয়া আউটপুট সলনি কৰক"</string>
     <string name="permission_storage" msgid="6831099350839392343">"ফট’ আৰু মিডিয়া"</string>
-    <string name="permission_notification" msgid="693762568127741203">"জাননী"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"এপ্"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"ষ্ট্ৰীম কৰি থকা হৈছে"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"ফ’ন কল কৰিব আৰু পৰিচালনা কৰিব পাৰে"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"ফ’নৰ কল লগ পঢ়িব আৰু লিখিব পাৰে"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"এছএমএছ বাৰ্তা পঠিয়াব আৰু চাব পাৰে"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"আপোনাৰ সম্পৰ্কসূচী এক্সেছ কৰিব পাৰে"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"আপোনাৰ কেলেণ্ডাৰ এক্সেছ কৰিব পাৰে"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"অডিঅ’ ৰেকৰ্ড কৰিব পাৰে"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"নিকটৱৰ্তী ডিভাইচসমূহ বিচাৰিব, সেইসমূহৰ সৈতে সংযুক্ত হ’ব আৰু সেইসমূহৰ আপেক্ষিক স্থান নিৰ্ধাৰণ কৰিব পাৰে"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"সম্পৰ্কসূচী, বাৰ্তা আৰু ফট’ৰ দৰে তথ্যকে ধৰি আটাইবোৰ জাননী পঢ়িব পাৰে"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"আপোনাৰ ফ’নৰ এপ্ ষ্ট্ৰীম কৰক"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"আপোনাৰ ফ’নৰ পৰা এপ্‌ আৰু ছিষ্টেমৰ অন্য সুবিধাসমূহ ষ্ট্ৰীম কৰক"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"উপলব্ধ ডিভাইচৰ সূচী এখন এক্সেছ কৰক আৰু কোনটোৱে ষ্ট্ৰীম কৰে অথবা অন্য এপৰ পৰা অডিঅ’ অথবা ভিডিঅ’ কাষ্ট কৰে সেয়া নিয়ন্ত্ৰণ কৰক"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"ফ’ন"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"টেবলেট"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-az/strings.xml b/packages/CompanionDeviceManager/res/values-az/strings.xml
index 18ac2ae..a3ed669 100644
--- a/packages/CompanionDeviceManager/res/values-az/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-az/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Zəng qeydləri"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Yaxınlıqdakı cihazlar"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Media çıxışını dəyişin"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Foto və media"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Bildirişlər"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Tətbiqlər"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Yayım"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Telefon zəngi edə və onları idarə edə bilər"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Telefonun zəng qeydini oxuya və yaza bilər"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"SMS mesajları göndərə və baxa bilər"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Kontaktlarınıza giriş edə bilər"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Təqviminizə giriş edə bilər"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Audio qeydə ala bilər"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Yaxınlıqdakı cihazları tapa, qoşula və nisbi mövqeyi təyin edə bilər"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Bütün bildirişləri, o cümlədən kontaktlar, mesajlar və fotolar kimi məlumatları oxuya bilər"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Telefonunuzun tətbiqlərini yayımlayın"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Telefondan tətbiq və digər sistem funksiyalarını yayımlayın"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Əlçatan cihazların siyahısına daxil olun, digər tətbiqlərdən audio və ya video yayımlayacaq cihazı idarə edin"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"telefonda"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"planşetdə"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml b/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
index b37ab4b9..071d93e 100644
--- a/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Evidencije poziva"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Uređaji u blizini"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Promena medijskog izlaza"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Slike i mediji"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Obaveštenja"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Aplikacije"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Striming"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Može da upućuje telefonske pozive i upravlja njima"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Može da čita i piše evidenciju poziva na telefonu"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Može da šalje i pregleda SMS poruke"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Može da pristupa kontaktima"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Može da pristupa kalendaru"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Može da snima zvuk"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Može da pronalazi i utvrđuje relativnu poziciju uređaja u blizini, kao i da se povezuje sa njima"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Može da čita sva obaveštenja, uključujući informacije poput kontakata, poruka i slika"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Strimujte aplikacije na telefonu"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Strimujte aplikacije i druge sistemske funkcije sa telefona"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Pristup listi dostupnih uređaja i kontrola uređaja koji strimuje ili prebacuje audio ili video iz drugih aplikacija"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"telefonu"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tabletu"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-be/strings.xml b/packages/CompanionDeviceManager/res/values-be/strings.xml
index 41889fd..d99b815 100644
--- a/packages/CompanionDeviceManager/res/values-be/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-be/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Мікрафон"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Журналы выклікаў"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Прылады паблізу"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Змяніць прыладу вываду медыя"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Фота і медыяфайлы"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Апавяшчэнні"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Праграмы"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Перадача плынню"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Можа рабіць тэлефонныя выклікі і кіраваць імі"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Можа счытваць і запісваць даныя ў журнале тэлефонных выклікаў"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Можа адпраўляць і праглядаць SMS-паведамленні"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Можа атрымліваць доступ да вашых кантактаў"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Можа атрымліваць доступ да вашага календара"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Можа запісваць аўдыя"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Можа знаходзіць прылады паблізу, падключацца да іх і вызначаць іх прыблізнае месцазнаходжанне"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Можа счытваць усе апавяшчэнні, уключаючы паведамленні, фота і інфармацыю пра кантакты"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Трансляцыя змесціва праграм з вашага тэлефона"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Перадача плынню змесціва праграм і іншых функцый сістэмы з вашага тэлефона"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Прагляд спіса даступных прылад і кіраванне тым, на якой з іх будзе трансліравацца аўдыя і відэа з іншых праграм"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"тэлефон"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"планшэт"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-bg/strings.xml b/packages/CompanionDeviceManager/res/values-bg/strings.xml
index bb53c5c..3840698 100644
--- a/packages/CompanionDeviceManager/res/values-bg/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bg/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Микрофон"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Списъци с обажданията"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Устройства в близост"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Промяна на мултимедийния изход"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Снимки и мултимедия"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Известия"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Приложения"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Поточно предаване"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Може да извършва и управлява телефонни обаждания"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Може да чете списъка с телефонните обаждания и да записва в него"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Може да изпраща и преглежда SMS съобщения"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Може да осъществява достъп до контактите ви"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Може да осъществява достъп до календара ви"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Може да записва звук"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Може да намира и да се свързва с устройства в близост, както и да определя относителната им позиция"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Може да чете всички известия, включително различна информация, като например контакти, съобщения и снимки"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Поточно предаване на приложенията на телефона ви"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Поточно предаване на приложения и други системни функции от телефона ви"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Осъществяване на достъп до списъка с налични устройства и контролиране на това кое да се използва за поточно предаване или предаване на аудио/видео от други приложения"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"телефон"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"таблет"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-bn/strings.xml b/packages/CompanionDeviceManager/res/values-bn/strings.xml
index bc0af0bd..38521d6 100644
--- a/packages/CompanionDeviceManager/res/values-bn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bn/strings.xml
@@ -54,21 +54,36 @@
     <string name="permission_microphone" msgid="2152206421428732949">"মাইক্রোফোন"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"কল লগ"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"আশেপাশের ডিভাইস"</string>
+    <!-- no translation found for permission_media_routing_control (5498639511586715253) -->
+    <skip />
     <string name="permission_storage" msgid="6831099350839392343">"ফটো ও মিডিয়া"</string>
-    <string name="permission_notification" msgid="693762568127741203">"বিজ্ঞপ্তি"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"অ্যাপ"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"স্ট্রিমিং"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"ফোন কল করতে ও ম্যানেজ করতে পারবে"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"ফোনের কল লগ পড়তে ও লিখতে পারবে"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"এসএমএস মেসেজ পাঠাতে ও দেখতে পারবে"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"আপনার পরিচিতি অ্যাক্সেস করতে পারবে"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"আপনার ক্যালেন্ডার অ্যাক্সেস করতে পারবে"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"অডিও রেকর্ড করতে পারে"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"আশেপাশের ডিভাইস খুঁজে দেখতে, তার সাথে কানেক্ট করতে এবং তার আপেক্ষিক অবস্থান নির্ধারণ করতে পারবে"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"সব বিজ্ঞপ্তি পড়তে পারবে, যার মধ্যে পরিচিতি, মেসেজ ও ফটোর মতো তথ্য অন্তর্ভুক্ত"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"আপনার ফোনের অ্যাপ স্ট্রিম করুন"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"আপনার ফোন থেকে অ্যাপ ও অন্যান্য সিস্টেম ফিচার স্ট্রিম করে"</string>
+    <!-- no translation found for permission_media_routing_control_summary (2714631092321412250) -->
+    <skip />
     <string name="device_type" product="default" msgid="8268703872070046263">"ফোন"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"ট্যাবলেট"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-bs/strings.xml b/packages/CompanionDeviceManager/res/values-bs/strings.xml
index 538ee35..6b03d24 100644
--- a/packages/CompanionDeviceManager/res/values-bs/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bs/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Zapisnici poziva"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Uređaji u blizini"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Promijeni izlaz med. sadržaja"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Fotografije i mediji"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Obavještenja"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Aplikacije"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Prijenos"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Može uspostavljati telefonske pozive i upravljati njima"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Može čitati i zapisivati zapisnik telefonskih poziva"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Može slati i prikazivati SMS poruke"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Može pristupiti kontaktima"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Može pristupiti kalendaru"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Može snimati zvuk"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Može pronaći uređaje u blizini, povezati se s njima i odrediti im relativan položaj"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Može čitati sva obavještenja, uključujući informacije kao što su kontakti, poruke i fotografije"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Prenosite aplikacije s telefona"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Prijenos aplikacija i drugih funkcija sistema s vašeg telefona"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Pristupa listi dostupnih uređaja i kontrolira koji od njih prenosi ili emitira zvuk ili videozapis iz drugih aplikacija"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"telefon"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tablet"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-ca/strings.xml b/packages/CompanionDeviceManager/res/values-ca/strings.xml
index b84be40..dcafb07c 100644
--- a/packages/CompanionDeviceManager/res/values-ca/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ca/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Micròfon"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Registres de trucades"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Dispositius propers"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Canvia la sortida multimèdia"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Fotos i contingut multimèdia"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Notificacions"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Aplicacions"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Reproducció en línia"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Pot fer i gestionar trucades"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Pot llegir i escriure el registre de trucades del telèfon"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Pot enviar i consultar missatges SMS"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Pot accedir als contactes"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Pot accedir al calendari"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Pot gravar àudio"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Pot determinar la posició relativa dels dispositius propers, cercar-los i connectar-s\'hi"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Pot llegir totes les notificacions, inclosa informació com ara els contactes, els missatges i les fotos"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Reprodueix en continu aplicacions del telèfon"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Reprodueix en continu aplicacions i altres funcions del sistema des del telèfon"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Accedeix a una llista de dispositius disponibles i controla quin reprodueix o emet àudio o vídeo des d\'altres aplicacions"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"telèfon"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tauleta"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-cs/strings.xml b/packages/CompanionDeviceManager/res/values-cs/strings.xml
index b62496d..98412c81 100644
--- a/packages/CompanionDeviceManager/res/values-cs/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-cs/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Seznamy hovorů"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Zařízení v okolí"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Změna mediálního výstupu"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Fotky a média"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Oznámení"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Aplikace"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Streamování"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Může uskutečňovat a spravovat telefonní hovory"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Může číst seznam telefonních hovorů a zapisovat do něj"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Může odesílat a číst zprávy SMS"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Má přístup k vašim kontaktům"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Má přístup k vašemu kalendáři"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Může nahrávat zvuk"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Může nacházet zařízení v okolí, připojovat se k nim a zjišťovat jejich relativní polohu"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Může číst veškerá oznámení včetně informací, jako jsou kontakty, zprávy a fotky"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Streamujte aplikace v telefonu"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Streamování aplikací a dalších systémových funkcí z telefonu"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Přístup k seznamu dostupných zařízení a určení, které bude streamovat nebo odesílat zvuk či video z ostatních aplikací"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"telefonu"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tabletu"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-da/strings.xml b/packages/CompanionDeviceManager/res/values-da/strings.xml
index df63e6c..86be312 100644
--- a/packages/CompanionDeviceManager/res/values-da/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-da/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Opkaldshistorik"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Enheder i nærheden"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Skift medieoutput"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Billeder og medier"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Notifikationer"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Streaming"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Kan foretage og administrere telefonopkald"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Kan læse og redigere opkaldshistorik"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Kan sende og se sms-beskeder"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Kan tilgå dine kontakter"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Kan tilgå din kalender"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Kan optage lyd"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Kan finde, oprette forbindelse til og fastslå den omtrentlige lokation af enheder i nærheden"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Kan læse alle notifikationer, herunder oplysninger som f.eks. kontakter, beskeder og billeder"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Stream din telefons apps"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Stream apps og andre systemfunktioner fra din telefon"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Få adgang til en liste over tilgængelige enheder, og vælg, hvilken enhed der skal streame eller caste lyd eller video fra andre apps"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"telefon"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tablet"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-de/strings.xml b/packages/CompanionDeviceManager/res/values-de/strings.xml
index f487f94..1bc2fed 100644
--- a/packages/CompanionDeviceManager/res/values-de/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-de/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Anrufliste"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Geräte in der Nähe"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Medienausgabe ändern"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Fotos und Medien"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Benachrichtigungen"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Streaming"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Kann Anrufe tätigen und verwalten"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Kann auf die Anrufliste zugreifen und sie bearbeiten"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Kann SMS senden und abrufen"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Kann auf deine Kontakte zugreifen"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Kann auf deinen Kalender zugreifen"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Darf Audio aufnehmen"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Kann Geräte in der Nähe finden, eine Verbindung zu ihnen herstellen und ihren relativen Standort ermitteln"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Kann alle Benachrichtigungen lesen, einschließlich Informationen wie Kontakten, Nachrichten und Fotos"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Smartphone-Apps streamen"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Apps und andere Systemfunktionen von deinem Smartphone streamen"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Auf eine Liste mit verfügbaren Geräten zugreifen und festlegen, welches Gerät Audio- oder Videoinhalte aus anderen Apps streamt oder überträgt"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"Smartphone"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"Tablet"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-el/strings.xml b/packages/CompanionDeviceManager/res/values-el/strings.xml
index 201a392..c8d6904 100644
--- a/packages/CompanionDeviceManager/res/values-el/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-el/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Μικρόφωνο"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Αρχεία καταγραφής κλήσεων"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Συσκευές σε κοντινή απόσταση"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Αλλαγή εξόδου μέσων"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Φωτογραφίες και μέσα"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Ειδοποιήσεις"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Εφαρμογές"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Ροή"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Μπορεί να πραγματοποιήσει και να διαχειριστεί τηλεφωνικές κλήσεις"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Έχει άδεια ανάγνωσης και εγγραφής στο αρχείο καταγραφής κλήσεων του τηλεφώνου"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Μπορεί να στείλει και να προβάλλει μηνύματα SMS"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Έχει πρόσβαση στις επαφές σας"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Έχει πρόσβαση στο ημερολόγιό σας"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Μπορεί να κάνει εγγραφή ήχου"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Δεν μπορεί να βρει, να συνδεθεί και να προσδιορίσει τη σχετική τοποθεσία των κοντινών συσκευών"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Μπορεί να διαβάσει όλες τις ειδοποιήσεις, συμπεριλαμβανομένων πληροφοριών όπως επαφές, μηνύματα και φωτογραφίες"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Μεταδώστε σε ροή τις εφαρμογές του τηλεφώνου σας"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Ροή εφαρμογών και άλλων λειτουργιών του συστήματος από το τηλέφωνό σας"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Αποκτήστε πρόσβαση σε μια λίστα διαθέσιμων συσκευών και ελέγξτε ποιες κάνουν ροή ή μετάδοση ήχου ή βίντεο από άλλες εφαρμογές"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"τηλέφωνο"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tablet"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml b/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml
index ca12145..8b506ed 100644
--- a/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml
@@ -54,21 +54,24 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Microphone"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Call logs"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Nearby devices"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Change media output"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Photos and media"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Notifications"</string>
+    <string name="permission_notifications" msgid="4099418516590632909">"Notifications"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Streaming"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Can make and manage phone calls"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Can read and write phone call log"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Can send and view SMS messages"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Can access your contacts"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Can access your calendar"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Can record audio"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Can find, connect to and determine the relative position of nearby devices"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Can read all notifications, including information like contacts, messages and photos"</string>
+    <string name="permission_phone_summary" msgid="8246321093970051702">"Make and manage phone calls"</string>
+    <string name="permission_call_logs_summary" msgid="7545243592757693321">"Read and write phone call log"</string>
+    <string name="permission_sms_summary" msgid="8499509535410068616">"Send and view SMS messages"</string>
+    <string name="permission_contacts_summary" msgid="2840800622763086808">"Access your contacts"</string>
+    <string name="permission_calendar_summary" msgid="8430353935747336165">"Access your calendar"</string>
+    <string name="permission_microphone_summary" msgid="4862628553869973259">"Record audio"</string>
+    <string name="permission_nearby_devices_summary" msgid="1306752848196464817">"Find, connect to and determine the relative position of Nearby devices"</string>
+    <string name="permission_notification_listener_access_summary" msgid="7856071768185367749">"Read all notifications, including information like contacts, messages and photos"</string>
+    <string name="permission_notifications_summary" msgid="2272810466047367030">"• Read all notifications, including info like contacts, messages and photos&lt;br/&gt;• Send notifications&lt;br/&gt;&lt;br/&gt;You can manage this app\'s ability to read and send notifications at any time in Settings &gt; Notifications."</string>
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Stream your phone’s apps"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Stream apps and other system features from your phone"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Access a list of available devices and control which one streams or casts audio or video from other apps"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"phone"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tablet"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml b/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml
index bd0342d..4f463f6 100644
--- a/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml
@@ -54,21 +54,24 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Microphone"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Call logs"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Nearby devices"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Change media output"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Photos and media"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Notifications"</string>
+    <string name="permission_notifications" msgid="4099418516590632909">"Notifications"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Streaming"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Can make and manage phone calls"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Can read and write phone call log"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Can send and view SMS messages"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Can access your contacts"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Can access your calendar"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Can record audio"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Can find, connect to, and determine the relative position of nearby devices"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Can read all notifications, including information like contacts, messages, and photos"</string>
+    <string name="permission_phone_summary" msgid="8246321093970051702">"Make and manage phone calls"</string>
+    <string name="permission_call_logs_summary" msgid="7545243592757693321">"Read and write phone call log"</string>
+    <string name="permission_sms_summary" msgid="8499509535410068616">"Send and view SMS messages"</string>
+    <string name="permission_contacts_summary" msgid="2840800622763086808">"Access your contacts"</string>
+    <string name="permission_calendar_summary" msgid="8430353935747336165">"Access your calendar"</string>
+    <string name="permission_microphone_summary" msgid="4862628553869973259">"Record audio"</string>
+    <string name="permission_nearby_devices_summary" msgid="1306752848196464817">"Find, connect to, and determine the relative position of nearby devices"</string>
+    <string name="permission_notification_listener_access_summary" msgid="7856071768185367749">"Read all notifications, including information like contacts, messages, and photos"</string>
+    <string name="permission_notifications_summary" msgid="2272810466047367030">"• Read all notifications, including info like contacts, messages, and photos&lt;br/&gt;• Send notifications&lt;br/&gt;&lt;br/&gt;You can manage this app\'s ability to read and send notifications anytime in Settings &gt; Notifications."</string>
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Stream your phone’s apps"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Stream apps and other system features from your phone"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Access a list of available devices and control which one streams or casts audio or video from other apps"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"phone"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tablet"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml b/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml
index ca12145..8b506ed 100644
--- a/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml
@@ -54,21 +54,24 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Microphone"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Call logs"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Nearby devices"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Change media output"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Photos and media"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Notifications"</string>
+    <string name="permission_notifications" msgid="4099418516590632909">"Notifications"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Streaming"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Can make and manage phone calls"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Can read and write phone call log"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Can send and view SMS messages"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Can access your contacts"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Can access your calendar"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Can record audio"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Can find, connect to and determine the relative position of nearby devices"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Can read all notifications, including information like contacts, messages and photos"</string>
+    <string name="permission_phone_summary" msgid="8246321093970051702">"Make and manage phone calls"</string>
+    <string name="permission_call_logs_summary" msgid="7545243592757693321">"Read and write phone call log"</string>
+    <string name="permission_sms_summary" msgid="8499509535410068616">"Send and view SMS messages"</string>
+    <string name="permission_contacts_summary" msgid="2840800622763086808">"Access your contacts"</string>
+    <string name="permission_calendar_summary" msgid="8430353935747336165">"Access your calendar"</string>
+    <string name="permission_microphone_summary" msgid="4862628553869973259">"Record audio"</string>
+    <string name="permission_nearby_devices_summary" msgid="1306752848196464817">"Find, connect to and determine the relative position of Nearby devices"</string>
+    <string name="permission_notification_listener_access_summary" msgid="7856071768185367749">"Read all notifications, including information like contacts, messages and photos"</string>
+    <string name="permission_notifications_summary" msgid="2272810466047367030">"• Read all notifications, including info like contacts, messages and photos&lt;br/&gt;• Send notifications&lt;br/&gt;&lt;br/&gt;You can manage this app\'s ability to read and send notifications at any time in Settings &gt; Notifications."</string>
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Stream your phone’s apps"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Stream apps and other system features from your phone"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Access a list of available devices and control which one streams or casts audio or video from other apps"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"phone"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tablet"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml b/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml
index ca12145..8b506ed 100644
--- a/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml
@@ -54,21 +54,24 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Microphone"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Call logs"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Nearby devices"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Change media output"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Photos and media"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Notifications"</string>
+    <string name="permission_notifications" msgid="4099418516590632909">"Notifications"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Streaming"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Can make and manage phone calls"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Can read and write phone call log"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Can send and view SMS messages"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Can access your contacts"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Can access your calendar"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Can record audio"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Can find, connect to and determine the relative position of nearby devices"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Can read all notifications, including information like contacts, messages and photos"</string>
+    <string name="permission_phone_summary" msgid="8246321093970051702">"Make and manage phone calls"</string>
+    <string name="permission_call_logs_summary" msgid="7545243592757693321">"Read and write phone call log"</string>
+    <string name="permission_sms_summary" msgid="8499509535410068616">"Send and view SMS messages"</string>
+    <string name="permission_contacts_summary" msgid="2840800622763086808">"Access your contacts"</string>
+    <string name="permission_calendar_summary" msgid="8430353935747336165">"Access your calendar"</string>
+    <string name="permission_microphone_summary" msgid="4862628553869973259">"Record audio"</string>
+    <string name="permission_nearby_devices_summary" msgid="1306752848196464817">"Find, connect to and determine the relative position of Nearby devices"</string>
+    <string name="permission_notification_listener_access_summary" msgid="7856071768185367749">"Read all notifications, including information like contacts, messages and photos"</string>
+    <string name="permission_notifications_summary" msgid="2272810466047367030">"• Read all notifications, including info like contacts, messages and photos&lt;br/&gt;• Send notifications&lt;br/&gt;&lt;br/&gt;You can manage this app\'s ability to read and send notifications at any time in Settings &gt; Notifications."</string>
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Stream your phone’s apps"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Stream apps and other system features from your phone"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Access a list of available devices and control which one streams or casts audio or video from other apps"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"phone"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tablet"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml b/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml
index 70af915..c3ae8a6 100644
--- a/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml
@@ -54,21 +54,24 @@
     <string name="permission_microphone" msgid="2152206421428732949">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‏‏‏‎‏‏‏‏‎‎‎‏‎‏‏‎‎‎‏‎‏‎‏‏‎‎‏‏‎‎‎‎‎‏‎‎‏‎‎‏‏‎‎‎‎‎‏‎‎‎‎‎‏‎‏‎‏‎Microphone‎‏‎‎‏‎"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‏‏‏‏‏‎‏‎‎‎‎‎‏‏‏‎‎‎‎‏‏‏‏‏‎‎‎‏‎‎‏‏‏‎‎‎‎‏‏‏‎‎‏‎‎‏‎‎‏‎‏‏‏‎‎‏‎Call logs‎‏‎‎‏‎"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‎‎‎‎‏‏‎‏‏‎‎‏‎‎‎‏‎‏‎‎‎‎‎‏‎‎‎‎‎‎‏‎‎‏‎‎‏‎‏‏‎‎‎‏‏‎‏‎‎‏‏‎‎‏‎Nearby devices‎‏‎‎‏‎"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‏‎‎‏‏‏‏‎‎‎‏‎‏‏‏‏‎‎‎‎‎‎‎‏‎‏‏‎‏‎‎‎‎‎‎‏‏‎‏‏‎‏‏‎‏‏‎‎‏‏‏‎‏‎‏‎Change media output‎‏‎‎‏‎"</string>
     <string name="permission_storage" msgid="6831099350839392343">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‎‎‏‏‎‎‏‏‏‏‎‎‎‎‏‎‏‎‏‎‏‎‏‎‏‏‏‎‎‎‎‎‏‎‏‏‏‎‏‏‏‏‏‎‎‎‎‏‎‏‎‏‏‏‎Photos and media‎‏‎‎‏‎"</string>
-    <string name="permission_notification" msgid="693762568127741203">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‏‎‏‎‎‎‎‎‏‎‏‏‏‏‎‏‎‏‏‎‎‎‎‏‎‏‎‎‎‏‏‏‏‎‏‏‎‏‏‏‎‏‏‏‏‏‎‏‎‎‎‏‎‎‏‏‎Notifications‎‏‎‎‏‎"</string>
+    <string name="permission_notifications" msgid="4099418516590632909">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‎‏‏‏‎‎‏‎‎‎‎‎‎‏‏‏‏‎‏‏‎‏‎‏‏‏‏‎‏‎‎‏‏‎‎‎‎‏‎‏‏‎‎‎‏‏‏‏‏‏‏‎‎‏‏‎‏‎Notifications‎‏‎‎‏‎"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‏‏‎‎‏‏‎‏‎‏‏‏‎‎‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‏‎‎‏‎‏‎‎‎‎‎‏‎‏‎‎‏‏‎‎‎‏‎‏‏‎‎Apps‎‏‎‎‏‎"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‎‎‏‏‎‎‏‏‏‎‎‏‎‏‎‏‎‎‏‎‎‎‏‏‎‏‎‏‏‏‏‎‎‎‎‎‏‎‏‎‎‎‎‏‏‏‎‎‎‏‏‏‏‎‏‏‎Streaming‎‏‎‎‏‎"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‎‏‎‎‎‎‎‎‏‏‏‎‏‏‏‎‎‎‏‎‎‎‏‏‏‎‏‎‏‎‏‎‏‎‏‏‏‎‎‎Can make and manage phone calls‎‏‎‎‏‎"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‏‎‎‏‎‏‏‏‎‏‎‎‎‏‎‎‎‎‏‏‎‎‎‏‎‏‏‎‎‏‏‏‏‎‎‏‎‎‏‎‎‎‎‏‏‏‎‎‏‏‏‎‎Can read and write phone call log‎‏‎‎‏‎"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‎‏‏‎‎‎‎‎‏‏‏‏‏‏‎‎‎‎‎‏‎‎‎‎‏‎‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‏‎‎‎‏‎Can send and view SMS messages‎‏‎‎‏‎"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‎‏‏‎‎‎‎‏‎‎‏‎‎‏‎‎‏‏‏‎‎‎‏‏‏‎‏‏‎‎‏‏‏‏‎‏‎‏‏‎‎‏‎‏‎‎‏‎‏‎‏‎‎‏‎‎‎Can access your contacts‎‏‎‎‏‎"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‎‎‏‏‎‏‎‎‎‏‎‎‎‏‎‎‏‏‏‎‎‏‏‎‎‏‎‏‏‎‎‎‎‎‎‏‎‎‏‏‏‎‎‏‎‏‏‎‏‎‎‏‎‎Can access your calendar‎‏‎‎‏‎"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‏‏‏‏‎‎‏‏‏‏‎‎‎‏‏‎‏‏‎‎‎‏‏‏‎‏‎‏‎‎‎‏‏‏‎‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‎‎‏‎‎Can record audio‎‏‎‎‏‎"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‏‏‏‎‏‏‏‎‏‏‏‎‏‎‏‎‏‏‏‏‏‎‎‎‎‎‏‎‏‎‎‎‎‏‎‎‏‎‎‎‎‎‏‎‎‎‏‏‎‏‏‎‏‏‏‏‎Can find, connect to, and determine the relative position of nearby devices‎‏‎‎‏‎"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‎‏‎‎‎‏‎‎‏‏‎‏‏‏‎‏‏‏‎‏‎‎‎‎‏‎‎‎‎‏‎‏‎‏‎‎‎‎‎‏‏‎‏‏‎‎‎‏‏‏‏‎‎‎‏‏‎Can read all notifications, including information like contacts, messages, and photos‎‏‎‎‏‎"</string>
+    <string name="permission_phone_summary" msgid="8246321093970051702">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‏‎‎‎‎‏‏‎‏‎‎‎‏‎‏‎‏‏‎‎‎‎‎‎‏‎‏‎‏‏‏‏‎‎‏‎‏‎‏‎‎‎‎‏‎‎‏‏‏‎‏‏‎‎Make and manage phone calls‎‏‎‎‏‎"</string>
+    <string name="permission_call_logs_summary" msgid="7545243592757693321">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‏‏‎‏‏‎‎‎‎‏‎‏‏‏‎‎‎‏‎‎‏‎‎‎‏‏‏‎‏‎‎‎‎‏‏‏‎‏‎‏‎‎‏‎‏‏‏‎‎‎‏‎‎‏‎Read and write phone call log‎‏‎‎‏‎"</string>
+    <string name="permission_sms_summary" msgid="8499509535410068616">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‏‎‏‎‎‎‏‎‏‎‎‏‎‏‏‏‎‎‎‏‏‏‏‎‏‏‏‏‏‎‎‏‎‏‎‎‏‏‎‎‏‏‏‎‎‏‎‎‎‏‎‎‎‎Send and view SMS messages‎‏‎‎‏‎"</string>
+    <string name="permission_contacts_summary" msgid="2840800622763086808">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‎‏‏‎‏‏‎‎‏‎‎‎‏‏‎‏‎‎‎‏‏‏‎‏‎‏‏‏‏‏‎‏‏‎‎‎‎‎‎‎‏‎‎‏‎‎‏‏‏‏‎‏‏‎‎‎‎Access your contacts‎‏‎‎‏‎"</string>
+    <string name="permission_calendar_summary" msgid="8430353935747336165">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‎‎‎‏‏‏‏‎‏‎‎‎‏‎‏‏‏‎‎‎‎‏‎‎‏‎‏‎‎‎‏‏‏‏‏‏‎‎‏‎‏‎Access your calendar‎‏‎‎‏‎"</string>
+    <string name="permission_microphone_summary" msgid="4862628553869973259">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‏‏‏‏‎‏‏‏‎‎‎‎‏‏‎‏‏‏‎‏‎‎‎‎‎‎‎‏‏‎‎‎‎‎‏‎‏‏‏‎‏‎‏‎‏‏‏‎‎‎‎‏‎‏‏‎Record audio‎‏‎‎‏‎"</string>
+    <string name="permission_nearby_devices_summary" msgid="1306752848196464817">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‎‎‏‎‎‎‏‎‏‎‎‎‎‏‎‎‏‏‎‎‏‎‏‎‏‎‏‏‏‏‎‏‏‏‏‏‏‎‏‎‏‏‏‏‎‎‎‎‏‎‏‏‎‎‎‏‎Find, connect to, and determine the relative position of nearby devices‎‏‎‎‏‎"</string>
+    <string name="permission_notification_listener_access_summary" msgid="7856071768185367749">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‎‎‎‏‏‎‎‏‎‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‏‎‎‎‎‎‏‎‏‎‏‎‎‏‏‏‏‎‏‏‎‎‏‏‎‎‎‏‎‏‎Read all notifications, including information like contacts, messages, and photos‎‏‎‎‏‎"</string>
+    <string name="permission_notifications_summary" msgid="2272810466047367030">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‎‏‎‎‏‎‏‎‎‎‏‎‎‏‏‏‎‏‏‎‏‏‎‏‎‎‎‏‎‏‏‎‎‎‏‎‏‏‏‎‏‏‏‎‏‏‎‎• Read all notifications, including info like contacts, messages, and photos&lt;br/&gt;• Send notifications&lt;br/&gt;&lt;br/&gt;You can manage this app\'s ability to read and send notifications anytime in Settings &gt; Notifications.‎‏‎‎‏‎"</string>
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‎‏‏‎‏‏‎‎‎‎‏‏‏‎‎‏‏‎‎‎‏‏‎‎‏‎‎‏‎‎‎‏‎‎‎‎‏‎‎‏‎‎‎‏‎‏‎‏‎‏‏‎‎‎‎‎‎Stream your phone’s apps‎‏‎‎‏‎"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‏‎‏‏‎‏‏‎‎‏‏‎‎‏‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‏‎‎Stream apps and other system features from your phone‎‏‎‎‏‎"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‏‏‎‏‎‏‏‎‎‎‏‎‎‏‏‏‎‏‎‎‏‏‎‎‎‏‎‎‎‎‎‏‎‎‎‎‎‏‏‎‎‎‏‏‎‎‏‎‎‏‎‎‏‏‎‏‎‎Access a list of available devices and control which one streams or casts audio or video from other apps‎‏‎‎‏‎"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‎‎‎‎‎‎‎‏‎‏‎‏‏‎‎‏‎‏‏‏‎‎‏‎‏‏‎‏‏‏‏‎‏‎‎‎‎‏‏‏‎‏‎‎‏‎‎‎‏‏‎‏‏‏‎phone‎‏‎‎‏‎"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‎‏‏‎‎‎‏‎‏‎‎‏‎‏‏‎‎‎‎‏‏‏‎‏‏‏‎‏‏‏‎‎‏‎‏‎‎‎‎‎‎‏‏‏‏‏‏‎‎tablet‎‏‎‎‏‎"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
index cba0b46..e42ee5e 100644
--- a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Micrófono"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Registros de llamadas"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Dispositivos cercanos"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Cambia la salida multimedia"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Fotos y contenido multimedia"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Notificaciones"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Transmisión"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Puede hacer y administrar llamadas telefónicas"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Puede leer y escribir el registro de llamadas telefónicas"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Puede enviar y ver mensajes SMS"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Puede acceder a los contactos"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Puede acceder al calendario"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Puede grabar audio"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Puede encontrar, conectarse con y determinar la ubicación relativa de los dispositivos cercanos"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Puede leer todas las notificaciones, incluso con información como contactos, mensajes y fotos"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Transmitir las apps de tu teléfono"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Transmite apps y otras funciones del sistema desde tu teléfono"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Accede a una lista de dispositivos disponibles y controla el que transmite audio o video de otras apps"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"teléfono"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tablet"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-es/strings.xml b/packages/CompanionDeviceManager/res/values-es/strings.xml
index 50d8806..40b0a64 100644
--- a/packages/CompanionDeviceManager/res/values-es/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-es/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Micrófono"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Registros de llamadas"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Dispositivos cercanos"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Cambiar salida multimedia"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Fotos y elementos multimedia"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Notificaciones"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Aplicaciones"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Emitir"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Puede hacer y gestionar llamadas"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Puede leer y escribir en el registro de llamadas del teléfono"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Puede enviar y ver mensajes SMS"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Puede acceder a tus contactos"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Puede acceder a tu calendario"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Puede grabar audio"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Puede buscar, conectarse y determinar la posición relativa de dispositivos cercanos"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Puede leer todas las notificaciones, incluida información como contactos, mensajes y fotos"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Muestra en streaming las aplicaciones de tu teléfono"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Emite aplicaciones y otras funciones del sistema desde tu teléfono"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Accede a una lista de dispositivos disponibles y controla cuál transmite o envía audio o vídeo desde otras aplicaciones"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"teléfono"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tablet"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-et/strings.xml b/packages/CompanionDeviceManager/res/values-et/strings.xml
index 2eff7eb..8a436b3 100644
--- a/packages/CompanionDeviceManager/res/values-et/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-et/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Kõnelogid"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Läheduses olevad seadmed"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Muutke meediaväljundit"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Fotod ja meedia"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Märguanded"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Rakendused"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Voogesitus"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Saab teha ja hallata telefonikõnesid"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Saab telefoni kõnelogi lugeda ja sinna kirjutada"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Saab saata ja vaadata SMS-sõnumeid"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Pääseb juurde teie kontaktidele"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Pääseb juurde teie kalendrile"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Saab salvestada heli"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Leiab läheduses olevaid seadmeid, saab nendega ühenduse luua ja määrata nende suhtelise asendi"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Kõikide märguannete, sealhulgas teabe, nagu kontaktid, sõnumid ja fotod, lugemine"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Telefoni rakenduste voogesitamine"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Rakenduste ja muude süsteemi funktsioonide voogesitamine teie telefonist"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Juurdepääs saadaolevate seadmete loendile ja juhtida, milline neist voogesitab või edastab heli või videot teistest rakendustest"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"telefon"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tahvelarvuti"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-eu/strings.xml b/packages/CompanionDeviceManager/res/values-eu/strings.xml
index e5d9c28..38f0512 100644
--- a/packages/CompanionDeviceManager/res/values-eu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-eu/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Mikrofonoa erabiltzeko baimena"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Deien erregistroak"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Inguruko gailuak"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Aldatu multimedia-irteera"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Argazkiak eta multimedia-edukia"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Jakinarazpenak"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Aplikazioak"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Igortzea"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Telefono-deiak egin eta kudea ditzake"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Telefonoko deien erregistroa irakurri, eta bertan idatz dezake"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"SMS mezuak bidali eta ikus ditzake"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Kontaktuak atzi ditzake"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Egutegia atzi dezake"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Audioa graba dezake"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Inguruko gailuak aurki ditzake, haietara konekta daiteke eta haien posizio erlatiboa zehatz dezake"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Jakinarazpen guztiak irakur ditzake; besteak beste, kontaktuak, mezuak, argazkiak eta antzeko informazioa"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Igorri zuzenean telefonoko aplikazioak"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Igorri aplikazioak eta sistemaren beste eginbide batzuk telefonotik"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Erabilgarri dauden gailuen zerrenda atzitu eta beste aplikazio batzuen bidez audioa edo bideoa zuzenean erreproduzitzen edo igortzen zein gailu ari den kontrolatu"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"Telefonoa"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"Tableta"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-fa/strings.xml b/packages/CompanionDeviceManager/res/values-fa/strings.xml
index 5e78aa5..5d0ad19 100644
--- a/packages/CompanionDeviceManager/res/values-fa/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fa/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"میکروفون"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"گزارش‌های تماس"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"دستگاه‌های اطراف"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"تغییر دادن خروجی رسانه"</string>
     <string name="permission_storage" msgid="6831099350839392343">"عکس‌ها و رسانه‌ها"</string>
-    <string name="permission_notification" msgid="693762568127741203">"اعلان‌ها"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"برنامه‌ها"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"جاری‌سازی"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"می‌تواند تماس تلفنی برقرار کند و این تماس‌ها را مدیریت کند"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"می‌تواند گزارش تماس‌های تلفنی را بنویسد و بخواند"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"می‌تواند پیامک ارسال کند و متن پیامک را مشاهده کند"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"می‌تواند به مخاطبین شما دسترسی داشته باشد"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"می‌تواند به تقویم شما دسترسی داشته باشد"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"می‌تواند صدا ضبط کند"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"می‌تواند دستگاه‌های اطراف را پیدا کند، به آن‌ها متصل شود، و موقعیت نسبی آن‌ها را تعیین کند"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"می‌تواند همه اعلان‌ها، ازجمله اطلاعاتی مثل مخاطبین، پیام‌ها، و عکس‌ها را بخواند"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"جاری‌سازی برنامه‌های تلفن"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"برنامه‌ها و دیگر ویژگی‌های سیستم را از تلفن شما جاری‌سازی می‌کند"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"دسترسی به فهرست دستگاه‌های دردسترس و کنترل اینکه کدام دستگاه صدا یا ویدیو را از برنامه‌های دیگر جاری‌سازی یا پخش کند"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"تلفن"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"رایانه لوحی"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-fi/strings.xml b/packages/CompanionDeviceManager/res/values-fi/strings.xml
index 552c473..b40de5f 100644
--- a/packages/CompanionDeviceManager/res/values-fi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fi/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Mikrofoni"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Puhelulokit"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Lähellä olevat laitteet"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Median ulostulon muuttaminen"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Kuvat ja media"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Ilmoitukset"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Sovellukset"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Striimaus"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Voi soittaa ja hallinnoida puheluita"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Voi lukea puhelulokia ja kirjoittaa siihen"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Voi lähettää ja nähdä tekstiviestejä"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Voi nähdä yhteystietosi"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Voi nähdä kalenterisi"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Voi tallentaa audiota"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Voi löytää lähellä olevia laitteita, muodostaa niihin yhteyden ja määrittää niiden suhteellisen sijainnin"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Voi lukea kaikkia ilmoituksia, esim. kontakteihin, viesteihin ja kuviin liittyviä tietoja"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Striimaa puhelimen sovelluksia"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Striimaa sovelluksia ja muita järjestelmän ominaisuuksia puhelimesta"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Näkee saatavilla olevat laitteet ja voi ohjata sitä, millä niistä striimataan muiden sovellusten audiota tai videota"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"puhelin"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tabletti"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml b/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
index 753875b..9b5707c 100644
--- a/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
@@ -54,21 +54,36 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Microphone"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Journaux d\'appels"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Appareils à proximité"</string>
+    <!-- no translation found for permission_media_routing_control (5498639511586715253) -->
+    <skip />
     <string name="permission_storage" msgid="6831099350839392343">"Photos et fichiers multimédias"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Notifications"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Applications"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Diffusion en continu"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Peut passer et gérer des appels téléphoniques"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Peut lire et écrire les journaux d\'appels téléphoniques"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Peut envoyer et voir les messages texte"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Peut accéder à vos contacts"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Peut accéder à votre agenda"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Peut enregistrer des données audio"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Peut trouver et déterminer la position relative des appareils à proximité, et s\'y connecter"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Peut lire toutes les notifications, y compris les renseignements tels que les contacts, les messages et les photos"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Diffusez les applications de votre téléphone"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Diffusez des applications et d\'autres fonctionnalités du système à partir de votre téléphone"</string>
+    <!-- no translation found for permission_media_routing_control_summary (2714631092321412250) -->
+    <skip />
     <string name="device_type" product="default" msgid="8268703872070046263">"téléphone"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tablette"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-fr/strings.xml b/packages/CompanionDeviceManager/res/values-fr/strings.xml
index d3704a0..3437988 100644
--- a/packages/CompanionDeviceManager/res/values-fr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fr/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Micro"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Journaux d\'appels"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Appareils à proximité"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Modifier la sortie multimédia"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Photos et contenus multimédias"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Notifications"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Applis"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Streaming"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Peut passer des appels téléphoniques et les gérer"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Peut consulter et modifier les journaux d\'appels du téléphone"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Peut envoyer et afficher des SMS"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Peut accéder à vos contacts"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Peut accéder à votre agenda"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Impossible d\'enregistrer l\'audio"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Peut trouver les appareils à proximité, s\'y connecter et déterminer leur position relative"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Peut lire toutes les notifications, y compris des informations comme les contacts, messages et photos"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Diffuser en streaming les applis de votre téléphone"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Diffusez des applis et d\'autres fonctionnalités système en streaming depuis votre téléphone"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Accédez à une liste d\'appareils disponibles et choisissez lequel caste ou lit en streaming une piste audio ou une vidéo à partir d\'autres applis."</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"téléphone"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tablette"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-gl/strings.xml b/packages/CompanionDeviceManager/res/values-gl/strings.xml
index a7aa72d..e84f2d9 100644
--- a/packages/CompanionDeviceManager/res/values-gl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-gl/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Micrófono"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Rexistros de chamadas"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Dispositivos próximos"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Cambiar a saída multimedia"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Fotos e contido multimedia"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Notificacións"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Aplicacións"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Reprodución en tempo real"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Pode facer e xestionar chamadas"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Pode ler e editar o rexistro de chamadas do teléfono"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Pode enviar e ver mensaxes SMS"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Pode acceder aos contactos"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Pode acceder ao calendario"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Pode gravar audio"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Pode atopar dispositivos próximos, conectarse a eles e determinar a súa posición relativa"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Pode ler todas as notificacións (que poden incluír información como contactos, mensaxes e fotos)"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Emite as aplicacións do teu teléfono"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Emite o contido das aplicacións e doutras funcións do sistema desde o teléfono"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Accede a unha lista de dispositivos dispoñibles e controla cal deles reproduce en tempo real ou emite audio ou vídeo desde outras aplicacións"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"teléfono"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tableta"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-gu/strings.xml b/packages/CompanionDeviceManager/res/values-gu/strings.xml
index 443fb4b..62e518a 100644
--- a/packages/CompanionDeviceManager/res/values-gu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-gu/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"માઇક્રોફોન"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"કૉલ લૉગ"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"નજીકના ડિવાઇસ"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"મીડિયા આઉટપુટ બદલો"</string>
     <string name="permission_storage" msgid="6831099350839392343">"ફોટા અને મીડિયા"</string>
-    <string name="permission_notification" msgid="693762568127741203">"નોટિફિકેશન"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"ઍપ"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"સ્ટ્રીમિંગ"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"ફોન કૉલ કરી શકે છે અને તેને મેનેજ કરી શકે છે"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"ફોન કૉલ લૉગ વાંચી અને લખી શકે છે"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"SMS મેસેજ મોકલી શકે છે અને જોઈ શકે છે"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"તમારા સંપર્કો ઍક્સેસ કરી શકે છે"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"તમારા કૅલેન્ડરનો ઍક્સેસ કરી શકે છે"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"ઑડિયો રેકોર્ડ કરી શકે છે"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"નજીકના ડિવાઇસ શોધી શકે છે, તેમની સાથે કનેક્ટ કરી શકે છે અને તેમની સંબંધિત સ્થિતિ નિર્ધારિત કરી શકે છે"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"સંપર્કો, મેસેજ અને ફોટા જેવી માહિતી સહિતના બધા નોટિફિકેશન વાંચી શકે છે"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"તમારા ફોનની ઍપ સ્ટ્રીમ કરો"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"તમારા ફોન પરથી ઍપ અને સિસ્ટમની અન્ય સુવિધાઓ સ્ટ્રીમ કરો"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"ઉપલબ્ધ ડિવાઇસની સૂચિ ઍક્સેસ કરો અને અન્ય ઍપમાંથી ઑડિયો કે વીડિયો ક્યા ડિવાઇસ દ્વારા સ્ટ્રીમ કે કાસ્ટ કરવામાં આવે તેનું નિયંત્રણ કરો"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"ફોન"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"ટૅબ્લેટ"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-hi/strings.xml b/packages/CompanionDeviceManager/res/values-hi/strings.xml
index 494af37..3d3a2c1 100644
--- a/packages/CompanionDeviceManager/res/values-hi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hi/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"माइक्रोफ़ोन"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"कॉल लॉग"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"आस-पास मौजूद डिवाइस"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"मीडिया आउटपुट बदलें"</string>
     <string name="permission_storage" msgid="6831099350839392343">"फ़ोटो और मीडिया"</string>
-    <string name="permission_notification" msgid="693762568127741203">"सूचनाएं"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"ऐप्लिकेशन"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"स्ट्रीमिंग"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"फ़ोन कॉल करने और उन्हें मैनेज करने की अनुमति है"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"कॉल लॉग देखने और उसमें बदलाव करने की अनुमति है"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"एसएमएस भेजने और उन्हें देखने की अनुमति है"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"आपकी संपर्क सूची को ऐक्सेस करने की अनुमति है"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"कैलेंडर को ऐक्सेस करने की अनुमति है"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"ऑडियो को रिकॉर्ड किया जा सकता है"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"आपको आस-पास मौजूद डिवाइसों को खोजने, उनसे कनेक्ट करने, और उनकी जगह की जानकारी का पता लगाने की अनुमति है"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"इससे सभी सूचनाएं देखी जा सकती हैं. इनमें संपर्क, मैसेज, और फ़ोटो जैसी जानकारी शामिल होती है"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"अपने फ़ोन पर मौजूद ऐप्लिकेशन स्ट्रीम करें"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"अपने फ़ोन से ऐप्लिकेशन और सिस्टम की दूसरी सुविधाओं को स्ट्रीम करें"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"उपलब्ध डिवाइसों की लिस्ट देखें. साथ ही, कंट्रोल करें कि कौनसा डिवाइस, स्ट्रीम कर सकता है या दूसरे ऐप्लिकेशन से ऑडियो या वीडियो कास्ट कर सकता है"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"फ़ोन"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"टैबलेट"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-hr/strings.xml b/packages/CompanionDeviceManager/res/values-hr/strings.xml
index 5e175bc..d6fbf2f 100644
--- a/packages/CompanionDeviceManager/res/values-hr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hr/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Zapisnici poziva"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Uređaji u blizini"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Promjena medijskog izlaza"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Fotografije i mediji"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Obavijesti"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Aplikacije"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Streaming"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Može uspostavljati telefonske pozive i upravljati njima"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Može čitati i pisati zapisnik poziva telefona"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Može slati i pregledavati SMS poruke"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Može pristupiti vašim kontaktima"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Može pristupiti vašem kalendaru"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Može snimati zvuk"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Može pronaći i odrediti relativni položaj uređaja u blizini i povezati se s njima"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Može čitati sve obavijesti, uključujući informacije kao što su kontakti, poruke i fotografije"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Streaming aplikacija vašeg telefona"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Emitirajte stream aplikacija i drugih značajki sustava s vašeg telefona"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Pristupite popisu dostupnih uređaja i upravljajte time koji streama ili emitira zvuk ili videozapise iz drugih aplikacija"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"telefonu"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tabletu"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-hu/strings.xml b/packages/CompanionDeviceManager/res/values-hu/strings.xml
index ba480f6..0db1f70 100644
--- a/packages/CompanionDeviceManager/res/values-hu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hu/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Hívásnaplók"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Közeli eszközök"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Médiakiment módosítása"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Fotók és médiatartalmak"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Értesítések"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Alkalmazások"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Streamelés"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Hívásokat indíthat és kezelhet"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Olvashatja és írhatja a telefon hívásnaplóját"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"SMS-üzeneteket küldhet és tekinthet meg"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Hozzáférhet a névjegyekhez"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Hozzáférhet a naptárhoz"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Rögzíthet hangot"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Megkeresheti a közeli eszközöket, meghatározhatja viszonylagos helyzetüket és csatlakozhat hozzájuk"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Elolvashat minden értesítést, ideértve az olyan információkat, mint a névjegyek, az üzenetek és a fotók"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"A telefon alkalmazásainak streamelése"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Alkalmazások és más rendszerfunkciók streamelése a telefonról"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Hozzáférhet a rendelkezésre álló eszközök listájához, és szabályozhatja, hogy melyik streamelhet vagy küldhet át hang- vagy videotartalmat más alkalmazásokból"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"telefonján"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"táblagépén"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-hy/strings.xml b/packages/CompanionDeviceManager/res/values-hy/strings.xml
index 9385fd1..6e08a97 100644
--- a/packages/CompanionDeviceManager/res/values-hy/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hy/strings.xml
@@ -54,21 +54,36 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Խոսափող"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Կանչերի ցուցակ"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Մոտակա սարքեր"</string>
+    <!-- no translation found for permission_media_routing_control (5498639511586715253) -->
+    <skip />
     <string name="permission_storage" msgid="6831099350839392343">"Լուսանկարներ և մուլտիմեդիա"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Ծանուցումներ"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Հավելվածներ"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Հեռարձակում"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Կարող է կատարել հեռախոսազանգեր և կառավարել դրանք"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Կարող է դիտել և գրանցել կանչերը"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Կարող է ուղարկել SMS հաղորդագրություններ և դիտել դրանք"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Կարող է օգտագործել ձեր կոնտակտները"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Կարող է օգտագործել ձեր օրացույցը"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Կարող է ձայնագրել"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Կարող է գտնել և որոշել մոտակա սարքերի մոտավոր դիրքը և միանալ դրանց"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Կարող է կարդալ բոլոր ծանուցումները, ներառյալ տեղեկությունները, օրինակ՝ կոնտակտները, հաղորդագրությունները և լուսանկարները"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Հեռարձակել հեռախոսի հավելվածները"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Հեռարձակել հավելվածներ և համակարգի այլ գործառույթներ հեռախոսում"</string>
+    <!-- no translation found for permission_media_routing_control_summary (2714631092321412250) -->
+    <skip />
     <string name="device_type" product="default" msgid="8268703872070046263">"հեռախոս"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"պլանշետ"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-in/strings.xml b/packages/CompanionDeviceManager/res/values-in/strings.xml
index c03a5ab..c0b8245 100644
--- a/packages/CompanionDeviceManager/res/values-in/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-in/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Log panggilan"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Perangkat di sekitar"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Mengubah output media"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Foto dan media"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Notifikasi"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Aplikasi"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Streaming"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Dapat melakukan dan mengelola panggilan telepon"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Dapat membaca dan menulis log panggilan telepon"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Dapat mengirim dan melihat pesan SMS"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Dapat mengakses kontak Anda"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Dapat mengakses kalender Anda"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Dapat merekam audio"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Dapat menemukan, terhubung ke, dan menentukan posisi relatif perangkat di sekitar"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Dapat membaca semua notifikasi, termasuk informasi seperti kontak, pesan, dan foto"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Streaming aplikasi ponsel"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Menstreaming aplikasi dan fitur sistem lainnya dari ponsel Anda"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Mengakses daftar perangkat yang tersedia dan mengontrol perangkat mana yang melakukan streaming atau transmisi audio atau video dari aplikasi lain"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"ponsel"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tablet"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-is/strings.xml b/packages/CompanionDeviceManager/res/values-is/strings.xml
index fc9f5a1..5951a1d 100644
--- a/packages/CompanionDeviceManager/res/values-is/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-is/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Hljóðnemi"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Símtalaskrár"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Nálæg tæki"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Breyta margmiðlunarúttaki"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Myndir og efni"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Tilkynningar"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Forrit"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Streymi"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Getur hringt og stjórnað símtölum"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Getur lesið og skrifað símtalaskrá símans"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Getur sent og skoðað SMS-skilaboð"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Hefur aðgang að tengiliðum"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Hefur aðgang að dagatalinu"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Getur tekið upp hljóð"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Getur fundið, tengst og áætlað staðsetningu nálægra tækja"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Getur lesið allar tilkynningar, þar á meðal upplýsingar á borð við tengiliði, skilaboð og myndir"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Streymdu forritum símans"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Streymdu forritum og öðrum kerfiseiginleikum úr símanum"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Fá aðgang að lista yfir tæki sem eru í boði og stjórna hver þeirra geta streymt og sent út hljóð og vídeó úr öðrum forritum"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"símanum"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"spjaldtölvunni"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-it/strings.xml b/packages/CompanionDeviceManager/res/values-it/strings.xml
index be431b6..9ce1241 100644
--- a/packages/CompanionDeviceManager/res/values-it/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-it/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Microfono"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Registri chiamate"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Dispositivi nelle vicinanze"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Cambia uscita conten. multim."</string>
     <string name="permission_storage" msgid="6831099350839392343">"Foto e contenuti multimediali"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Notifiche"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"App"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Streaming"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Consente di effettuare e gestire telefonate"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Consente di leggere e modificare il registro chiamate del telefono"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Consente di inviare e visualizzare SMS"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Consente di accedere ai tuoi contatti"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Consente di accedere al tuo calendario"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Consente di registrare audio"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Consente di trovare e connettersi a dispositivi nelle vicinanze, nonché di stabilirne la posizione relativa"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Puoi leggere tutte le notifiche, incluse le informazioni come contatti, messaggi e foto"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Trasmetti in streaming le app del tuo telefono"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Trasmettere in streaming app e altre funzionalità di sistema dal telefono"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Accedi a un elenco di dispositivi disponibili e controlla quale di questi riproduce in streaming o trasmette audio o video da altre app"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"telefono"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tablet"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-iw/strings.xml b/packages/CompanionDeviceManager/res/values-iw/strings.xml
index 8982660..8e2b715 100644
--- a/packages/CompanionDeviceManager/res/values-iw/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-iw/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"מיקרופון"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"יומני שיחות"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"מכשירים בקרבת מקום"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"שינוי פלט המדיה"</string>
     <string name="permission_storage" msgid="6831099350839392343">"תמונות ומדיה"</string>
-    <string name="permission_notification" msgid="693762568127741203">"התראות"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"אפליקציות"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"סטרימינג"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"אפשרות לבצע ולנהל שיחות טלפון"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"אפשרות ולקרוא ולכתוב נתונים ביומן השיחות של הטלפון"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"‏אפשרות לשלוח הודעות SMS ולצפות בהן"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"גישה לאנשי הקשר"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"אפשרות לגשת ליומן"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"המיקרופון יכול להקליט אודיו"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"אפשרות למצוא מכשירים בקרבת מקום, להתחבר אליהם ולהעריך את המיקום היחסי שלהם"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"גישת קריאה לכל ההתראות, כולל מידע כמו אנשי קשר, הודעות ותמונות."</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"שידור אפליקציות מהטלפון"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"העברה של אפליקציות ותכונות מערכת אחרות בסטרימינג מהטלפון"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"‏גישה לרשימה של מכשירים זמינים ובחירה איזה מהם ישמש כדי לשדר או להעביר (cast) אודיו או וידאו מאפליקציות אחרות"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"טלפון"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"טאבלט"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-ja/strings.xml b/packages/CompanionDeviceManager/res/values-ja/strings.xml
index 186944a..175ea0f 100644
--- a/packages/CompanionDeviceManager/res/values-ja/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ja/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"マイク"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"通話履歴"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"付近のデバイス"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"メディア出力の変更"</string>
     <string name="permission_storage" msgid="6831099350839392343">"写真とメディア"</string>
-    <string name="permission_notification" msgid="693762568127741203">"通知"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"アプリ"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"ストリーミング"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"電話の発信と管理を行えます"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"通話履歴の読み取りと書き込みを行えます"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"SMS メッセージの送信、表示を行えます"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"連絡先にアクセスできます"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"カレンダーにアクセスできます"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"録音できる"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"付近のデバイスの検出、接続、相対位置の特定を行えます"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"連絡先、メッセージ、写真に関する情報を含め、すべての通知を読み取ることができます"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"スマートフォンのアプリをストリーミングします"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"アプリやその他のシステム機能をスマートフォンからストリーミングする"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"他のアプリから音声や動画をストリーミングまたはキャストする際に使用可能なデバイスとコントロールのリストにアクセスできます"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"スマートフォン"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"タブレット"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-ka/strings.xml b/packages/CompanionDeviceManager/res/values-ka/strings.xml
index a7c6042..c655344 100644
--- a/packages/CompanionDeviceManager/res/values-ka/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ka/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"მიკროფონი"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"ზარების ჟურნალები"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"ახლომახლო მოწყობილობები"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"გამომავალი მედიის გამოტანის"</string>
     <string name="permission_storage" msgid="6831099350839392343">"ფოტოები და მედია"</string>
-    <string name="permission_notification" msgid="693762568127741203">"შეტყობინებები"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"აპები"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"სტრიმინგი"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"შეძლოს სატელეფონო ზარების განხორციელება და მართვა"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"შეეძლოს ზარების ჟურნალის წაკითხვა და მასში ჩაწერა"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"შეძლოს SMS ტექსტური შეტყობინებების გაგზავნა და მიღება"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"ჰქონდეს თქვენს კონტაქტებზე წვდომის საშუალება"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"ჰქონდეს თქვენს კალენდარზე წვდომის საშუალება"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"შეიძლებოდეს აუდიოს ჩაწერა"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"შეძლოს ახლომახლო მოწყობილობების აღმოჩენა, მათთან დაკავშირება და მათი შედარებითი პოზიციის დადგენა"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"შეუძლია წაიკითხოს ყველა შეტყობინება, მათ შორის ისეთი ინფორმაცია, როგორიცაა კონტაქტები, ტექსტური შეტყობინებები და ფოტოები"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"თქვენი ტელეფონის აპების სტრიმინგი"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"აწარმოეთ აპების და სისტემის სხვა ფუნქციების სტრიმინგი თქვენი ტელეფონიდან"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"წვდომა ხელმისაწვდომი მოწყობილობების სიაზე და აკონტროლეთ რომელი უშვებს აუდიოს ან ვიდეოს სხვა აპებიდან."</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"ტელეფონი"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"ტაბლეტი"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-kk/strings.xml b/packages/CompanionDeviceManager/res/values-kk/strings.xml
index 5c6d24a..c4928da 100644
--- a/packages/CompanionDeviceManager/res/values-kk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-kk/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Микрофон"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Қоңырау журналдары"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Маңайдағы құрылғылар"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Мультимедиа шығысын өзгерту"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Фотосуреттер мен медиафайлдар"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Хабарландырулар"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Қолданбалар"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Трансляция"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Қоңырау шалып, оларды басқара алады."</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Телефонның қоңыраулар журналын оқып, жаза алады."</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"SMS хабарларды көріп, жібере алады."</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Контактілеріңізді пайдалана алады."</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Күнтізбеңізді пайдалана алады."</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Аудио жаза алады."</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Маңайдағы құрылғыларды тауып, олармен байланысып, бір-біріне қатысты локациясын анықтайды."</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Барлық хабарландыруды, соның ішінде контактілер, хабарлар және фотосуреттер сияқты ақпаратты оқи алады."</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Телефон қолданбаларын трансляциялайды."</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Қолданбалар мен басқа да жүйе функцияларын телефоннан трансляциялау"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Қолжетімді құрылғылар тізімін ашып, қай құрылғының басқа қолданбалардан аудионы не бейнені трансляциялайтынын басқара аласыз."</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"телефон"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"планшет"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-km/strings.xml b/packages/CompanionDeviceManager/res/values-km/strings.xml
index c734cb6..28b6340 100644
--- a/packages/CompanionDeviceManager/res/values-km/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-km/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"មីក្រូហ្វូន"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"កំណត់​ហេតុ​ហៅ​ទូរសព្ទ"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"ឧបករណ៍នៅជិត"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"ប្ដូរឧបករណ៍មេឌៀ"</string>
     <string name="permission_storage" msgid="6831099350839392343">"រូបថត និងមេឌៀ"</string>
-    <string name="permission_notification" msgid="693762568127741203">"ការ​ជូនដំណឹង"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"កម្មវិធី"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"ការផ្សាយ"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"អាចហៅទូរសព្ទ និងគ្រប់គ្រងការហៅទូរសព្ទ"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"អាចអាន និងសរសេរ​កំណត់​ហេតុ​ហៅ​ទូរសព្ទ"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"អាចផ្ញើ និងមើលសារ SMS"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"អាចចូលប្រើទំនាក់ទំនងរបស់អ្នក"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"អាចចូលប្រើប្រតិទិនរបស់អ្នក"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"អាចថតសំឡេង"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"អាចស្វែងរក ភ្ជាប់ទៅ និងកំណត់​ចម្ងាយពាក់ព័ន្ធ​រវាងឧបករណ៍​ដែលនៅជិត"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"អាចអាន​ការជូនដំណឹង​ទាំងអស់ រួមទាំង​ព័ត៌មាន​ដូចជាទំនាក់ទំនង សារ និងរូបថត"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"ផ្សាយកម្មវិធីរបស់ទូរសព្ទអ្នក"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"ចាក់ផ្សាយ​កម្មវិធី និងមុខងារប្រព័ន្ធ​ផ្សេងទៀត​ពីទូរសព្ទ​របស់អ្នក"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"ចូលប្រើប្រាស់បញ្ជីឧបករណ៍ដែលអាចប្រើបាន និងគ្រប់គ្រងថាតើឧបករណ៍ណាចាក់ ឬបញ្ជូនសំឡេង ឬវីដេអូពីកម្មវិធីផ្សេងទៀត"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"ទូរសព្ទ"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"ថេប្លេត"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-kn/strings.xml b/packages/CompanionDeviceManager/res/values-kn/strings.xml
index 5f04cd3..eb94178 100644
--- a/packages/CompanionDeviceManager/res/values-kn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-kn/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"ಮೈಕ್ರೊಫೋನ್"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"ಕರೆಯ ಲಾಗ್‌ಗಳು"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"ಸಮೀಪದಲ್ಲಿರುವ ಸಾಧನಗಳು"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"ಮೀಡಿಯಾ ಔಟ್‌‌ಪುಟ್ ಬದಲಾಯಿಸಿ"</string>
     <string name="permission_storage" msgid="6831099350839392343">"ಫೋಟೋಗಳು ಮತ್ತು ಮಾಧ್ಯಮ"</string>
-    <string name="permission_notification" msgid="693762568127741203">"ಅಧಿಸೂಚನೆಗಳು"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"ಆ್ಯಪ್‌ಗಳು"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"ಸ್ಟ್ರೀಮಿಂಗ್"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"ಫೋನ್ ಕರೆಗಳನ್ನು ಮಾಡಬಹುದು ಮತ್ತು ನಿರ್ವಹಿಸಬಹುದು"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"ಪೋನ್‌ ಕರೆಯ ಲಾಗ್‌ ಅನ್ನು ಓದಬಹುದು ಮತ್ತು ಬರೆಯಬಹುದು"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"SMS ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸಬಹುದು ಮತ್ತು ವೀಕ್ಷಿಸಬಹುದು"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"ನಿಮ್ಮ ಸಂಪರ್ಕಗಳನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಬಹುದು"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"ನಿಮ್ಮ ಕ್ಯಾಲೆಂಡರ್ ಅನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಬಹುದು"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"ಆಡಿಯೋ ರೆಕಾರ್ಡ್ ಮಾಡಬಹುದು"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"ಸಮೀಪದಲ್ಲಿರುವ ಸಾಧನಗಳನ್ನು ಹುಡುಕಬಹುದು, ಅವುಗಳಿಗೆ ಕನೆಕ್ಟ್ ಆಗಬಹುದು ಮತ್ತು ಅವುಗಳ ಸಂಬಂಧಿತ ಸ್ಥಾನವನ್ನು ನಿರ್ಧರಿಸಬಹುದು"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"ಸಂಪರ್ಕಗಳು, ಸಂದೇಶಗಳು ಮತ್ತು ಫೋಟೋಗಳಂತಹ ಮಾಹಿತಿಯನ್ನು ಒಳಗೊಂಡಂತೆ ಎಲ್ಲಾ ಅಧಿಸೂಚನೆಗಳನ್ನು ಓದಬಹುದು"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"ನಿಮ್ಮ ಫೋನ್‍ನ ಆ್ಯಪ್‌ಗಳನ್ನು ಸ್ಟ್ರೀಮ್ ಮಾಡಿ"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"ನಿಮ್ಮ ಫೋನ್‌ನಿಂದ ಆ್ಯಪ್‌ಗಳು ಮತ್ತು ಇತರ ಸಿಸ್ಟಂ ಫೀಚರ್‌ಗಳನ್ನು ಸ್ಟ್ರೀಮ್ ಮಾಡಿ"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"ಲಭ್ಯವಿರುವ ಸಾಧನಗಳ ಪಟ್ಟಿಯನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಿ ಮತ್ತು ಇತರ ಆ್ಯಪ್‌ಗಳಿಂದ ಯಾವುದು ಆಡಿಯೋ ಅಥವಾ ವೀಡಿಯೊವನ್ನು ಸ್ಟ್ರೀಮ್ ಮಾಡುವುದು ಅಥವಾ ಕ್ಯಾಸ್ಟ್ ಮಾಡುವುದನ್ನು ಕಂಟ್ರೋಲ್ ಮಾಡಿ"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"ಫೋನ್"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"ಟ್ಯಾಬ್ಲೆಟ್"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-ko/strings.xml b/packages/CompanionDeviceManager/res/values-ko/strings.xml
index ca9e541..4685397 100644
--- a/packages/CompanionDeviceManager/res/values-ko/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ko/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"마이크"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"통화 기록"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"근처 기기"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"미디어 출력 변경"</string>
     <string name="permission_storage" msgid="6831099350839392343">"사진 및 미디어"</string>
-    <string name="permission_notification" msgid="693762568127741203">"알림"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"앱"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"스트리밍"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"전화를 걸고 통화를 관리할 수 있습니다."</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"통화 기록을 읽고 쓸 수 있습니다."</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"SMS 메시지를 전송하고 볼 수 있습니다."</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"연락처에 액세스할 수 있습니다."</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"캘린더에 액세스할 수 있습니다."</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"오디오 녹음 가능"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"근처 기기를 찾아 연결하고 기기 간 상대적 위치를 파악할 수 있습니다."</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"연락처, 메시지, 사진 등의 정보를 포함한 모든 알림을 읽을 수 있습니다."</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"휴대전화의 앱을 스트리밍합니다."</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"내 휴대전화의 앱 및 기타 시스템 기능 스트리밍"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"사용할 수 있는 기기 목록에 액세스하고, 다른 앱에서 오디오 또는 동영상을 스트리밍하거나 전송할 기기를 제어합니다."</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"스마트폰"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"태블릿"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-ky/strings.xml b/packages/CompanionDeviceManager/res/values-ky/strings.xml
index d33cced..76aefe1 100644
--- a/packages/CompanionDeviceManager/res/values-ky/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ky/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Микрофон"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Чалуулар тизмеси"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Жакын жердеги түзмөктөр"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Медиа чыгарылышын өзгөртүү"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Сүрөттөр жана медиафайлдар"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Билдирмелер"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Колдонмолор"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Алып ойнотуу"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Телефон чалууларды аткарып жана тескей алат"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Телефондогу чалуулар тизмесин окуп жана жаза алат"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"SMS билдирүүлөрдү жөнөтүп жана көрө алат"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Байланыштарыңызга кире алат"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Жылнаамаңызга кире алат"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Аудио жаздыра алат"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Жакын жердеги түзмөктөрдү таап, аларга туташып, абалын аныктай алат"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Бардык билдирмелерди, анын ичинде байланыштар, билдирүүлөр жана сүрөттөр сыяктуу маалыматты окуй алат"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Телефондогу колдонмолорду алып ойнотуу"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Телефонуңуздагы колдонмолорду жана системанын башка функцияларын алып ойнотуу"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Жеткиликтүү түзмөктөрдүн тизмесине кирип, кайсынысы башка колдонмолордон аудио же видеону алып ойнотуп же тышкы экранга чыгара турганын көзөмөлдөңүз"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"телефон"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"планшет"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-lo/strings.xml b/packages/CompanionDeviceManager/res/values-lo/strings.xml
index 0072e4b..bbf0be3 100644
--- a/packages/CompanionDeviceManager/res/values-lo/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-lo/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"ໄມໂຄຣໂຟນ"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"ບັນທຶກການໂທ"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"ອຸປະກອນທີ່ຢູ່ໃກ້ຄຽງ"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"ປ່ຽນເອົ້າພຸດສື່"</string>
     <string name="permission_storage" msgid="6831099350839392343">"ຮູບພາບ ແລະ ມີເດຍ"</string>
-    <string name="permission_notification" msgid="693762568127741203">"ການແຈ້ງເຕືອນ"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"ແອັບ"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"ກຳລັງສະຕຣີມ"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"ສາມາດໂທອອກ ແລະ ຈັດການການໂທໄດ້"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"ສາມາດອ່ານ ແລະ ຂຽນບັນທຶກການໂທຂອງໂທລະສັບ"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"ສາມາດສົ່ງ ແລະ ເບິ່ງຂໍ້ຄວາມ SMS"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"ສາມາດເຂົ້າເຖິງລາຍຊື່ຜູ້ຕິດຕໍ່ຂອງທ່ານ"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"ສາມາດເຂົ້າເຖິງປະຕິທິນຂອງທ່ານ"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"ສາມາດບັນທຶກສຽງໄດ້"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"ສາມາດຊອກຫາ, ເຊື່ອມຕໍ່ ແລະ ລະບຸສະຖານທີ່ທີ່ກ່ຽວຂ້ອງກັນຂອງອຸປະກອນທີ່ຢູ່ໃກ້ຄຽງ"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"ສາມາດອ່ານການແຈ້ງເຕືອນທັງໝົດ, ຮວມທັງຂໍ້ມູນ ເຊັ່ນ: ລາຍຊື່ຜູ້ຕິດຕໍ່, ຂໍ້ຄວາມ ແລະ ຮູບພາບ"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"ສະຕຣີມແອັບຂອງໂທລະສັບທ່ານ"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"ສະຕຣີມແອັບ ແລະ ຄຸນສົມບັດລະບົບອື່ນໆຈາກໂທລະສັບຂອງທ່ານ"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"ເຂົ້າເຖິງລາຍຊື່ຂອງອຸປະກອນທີ່ມີ ແລະ ຄວບຄຸມອຸປະກອນທີ່ຈະສະຕຣີມ ຫຼື ສົ່ງສັນຍານສຽງ ຫຼື ວິດີໂອຈາກແອັບອື່ນໆ"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"ໂທລະສັບ"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"ແທັບເລັດ"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-lt/strings.xml b/packages/CompanionDeviceManager/res/values-lt/strings.xml
index 65a266d..1c28f14 100644
--- a/packages/CompanionDeviceManager/res/values-lt/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-lt/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Mikrofonas"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Skambučių žurnalai"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Įrenginiai netoliese"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Keisti medijos išvestį"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Nuotraukos ir medija"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Pranešimai"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Programos"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Srautinis perdavimas"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Gali atlikti ir tvarkyti telefono skambučius"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Gali skaityti ir rašyti telefono skambučių žurnalą"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Gali siųsti ir peržiūrėti SMS pranešimus"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Gali pasiekti jūsų kontaktus"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Gali pasiekti jūsų kalendorių"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Gali įrašyti garsą"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Gali rasti apytikslę netoliese esančių įrenginių poziciją, aptikti juos ir prisijungti prie jų"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Galima skaityti visus pranešimus, įskaitant tokią informaciją kaip kontaktai, pranešimai ir nuotraukos"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Telefono programų perdavimas srautu"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Srautu perduokite programas ir kitas sistemos funkcijas iš telefono"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Pasiekti pasiekiamų įrenginių sąrašą ir valdyti, kuris leidžia garso arba vaizdo įrašo srautą arba perduoda įrašą iš kitų programų"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"telefone"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"planšetiniame kompiuteryje"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-lv/strings.xml b/packages/CompanionDeviceManager/res/values-lv/strings.xml
index 1d29edc..5126812 100644
--- a/packages/CompanionDeviceManager/res/values-lv/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-lv/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Mikrofons"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Zvanu žurnāli"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Tuvumā esošas ierīces"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Mainīt multivides izvadi"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Fotoattēli un multivides faili"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Paziņojumi"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Lietotnes"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Straumēšana"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Var veikt un pārvaldīt tālruņa zvanus"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Var lasīt un rakstīt tālruņa zvanu žurnālu"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Var sūtīt un skatīt īsziņas"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Var piekļūt jūsu kontaktpersonām"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Var piekļūt jūsu kalendāram"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Var ierakstīt audio"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Var atrast tuvumā esošas ierīces, izveidot ar tām savienojumu un noteikt to relatīvo atrašanās vietu"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Var lasīt visus paziņojumus, tostarp tādu informāciju kā kontaktpersonas, ziņojumi un fotoattēli."</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Straumēt jūsu tālruņa lietotnes"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"No sava tālruņa straumējiet lietotnes un citas sistēmas funkcijas"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Piekļuve pieejamo ierīču sarakstam un iespēja kontrolēt, kura ierīce straumē vai apraida audio vai video no citām lietotnēm"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"tālrunī"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"planšetdatorā"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-mk/strings.xml b/packages/CompanionDeviceManager/res/values-mk/strings.xml
index e72e960..24fbaa7 100644
--- a/packages/CompanionDeviceManager/res/values-mk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mk/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Микрофон"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Евиденција на повици"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Уреди во близина"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Промена на излезот за аудио"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Аудиовизуелни содржини"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Известувања"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Апликации"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Стриминг"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Може да упатува и управува со телефонски повици"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Може да чита и пишува евиденција на повици во телефонот"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Може да испраќа и гледа SMS-пораки"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Може да пристапува до вашите контакти"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Може да пристапува до вашиот календар"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Може да снима аудио"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Може да наоѓа и да се поврзува со уреди во близина и да ја утврдува нивната релативна положба"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"може да ги чита сите известувања, вклучително и податоци како контакти, пораки и фотографии"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Стримувајте ги апликациите на телефонот"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Апликации за стриминг и други системски функции од вашиот телефон"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Пристап до списокот со достапни уреди и контрола кои стримуваат или емитуваат аудио или видео од други апликации"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"Телефон"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"Таблет"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-ml/strings.xml b/packages/CompanionDeviceManager/res/values-ml/strings.xml
index 1703742..a3e07ca 100644
--- a/packages/CompanionDeviceManager/res/values-ml/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ml/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"മൈക്രോഫോൺ"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"കോൾ ചരിത്രം"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"സമീപമുള്ള ഉപകരണങ്ങൾ"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"മീഡിയ ഔട്ട്പുട്ട് മാറ്റുക"</string>
     <string name="permission_storage" msgid="6831099350839392343">"ഫോട്ടോകളും മീഡിയയും"</string>
-    <string name="permission_notification" msgid="693762568127741203">"അറിയിപ്പുകൾ"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"ആപ്പുകൾ"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"സ്ട്രീമിംഗ്"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"ഫോൺ കോളുകൾ ചെയ്യാനും അവ മാനേജ് ചെയ്യാനും കഴിയും"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"ഫോൺ കോൾ ചരിത്രം റീഡ് ചെയ്യാനും റൈറ്റ് ചെയ്യാനും കഴിയും"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"SMS സന്ദേശങ്ങൾ അയയ്‌ക്കാനും കാണാനും കഴിയും"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"നിങ്ങളുടെ കോൺടാക്‌റ്റുകൾ ആക്‌സസ് ചെയ്യാൻ കഴിയും"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"നിങ്ങളുടെ കലണ്ടർ ആക്‌സസ് ചെയ്യാൻ കഴിയും"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"ഓഡിയോ റെക്കോർഡ് ചെയ്യാം"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"സമീപമുള്ള ഉപകരണങ്ങൾ കണ്ടെത്താനും അവയിലേക്ക് കണക്റ്റ് ചെയ്യാനും അവയുടെ ആപേക്ഷിക സ്ഥാനം നിർണ്ണയിക്കാനും കഴിയും"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"കോൺടാക്‌റ്റുകൾ, സന്ദേശങ്ങൾ, ഫോട്ടോകൾ മുതലായ വിവരങ്ങൾ ഉൾപ്പെടെയുള്ള എല്ലാ അറിയിപ്പുകളും വായിക്കാനാകും"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"നിങ്ങളുടെ ഫോണിലെ ആപ്പുകൾ സ്‌ട്രീം ചെയ്യുക"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"നിങ്ങളുടെ ഫോണിൽ നിന്ന് ആപ്പുകളും മറ്റ് സിസ്റ്റം ഫീച്ചറുകളും സ്ട്രീം ചെയ്യാം"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"ലഭ്യമായ ഉപകരണങ്ങളുടെ ലിസ്റ്റ് ആക്സസ് ചെയ്ത്, അവയിൽ ഏതാണ് മറ്റ് ആപ്പുകളിൽ നിന്ന് ഓഡിയോ അല്ലെങ്കിൽ വീഡിയോ സ്‌ട്രീം ചെയ്യേണ്ടത് അല്ലെങ്കിൽ കാസ്റ്റ് ചെയ്യേണ്ടത് എന്ന് നിയന്ത്രിക്കുക"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"ഫോൺ"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"ടാബ്‌ലെറ്റ്"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-mn/strings.xml b/packages/CompanionDeviceManager/res/values-mn/strings.xml
index 613c9aa..584185e 100644
--- a/packages/CompanionDeviceManager/res/values-mn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mn/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Микрофон"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Дуудлагын жагсаалт"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Ойролцоох төхөөрөмжүүд"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Медиа гаралтыг өөрчлөх"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Зураг болон медиа"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Мэдэгдэл"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Аппууд"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Дамжуулах"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Дуудлага хийх, удирдах боломжтой"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Утасны дуудлагын жагсаалтыг уншиж, бичих боломжтой"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"SMS мессеж илгээх, үзэх боломжтой"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Таны харилцагчдад хандах боломжтой"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Таны календарьт хандах боломжтой"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Аудио бичих боломжтой"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Ойролцоох төхөөрөмжүүдийн харьцангуй байршлыг тодорхойлох, холбох, олох боломжтой"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Харилцагчид, мессеж болон зураг зэрэг мэдээллийг оруулаад бүх мэдэгдлийг унших боломжтой"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Утасныхаа аппуудыг дамжуулаарай"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Утаснаасаа аппууд болон системийн бусад онцлогийг дамжуулаарай"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Боломжтой төхөөрөмжүүдийн жагсаалтад хандаж, аль нь бусад аппаас аудио эсвэл видео дамжуулах, нэвтрүүлэхийг хянана уу"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"утас"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"таблет"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-mr/strings.xml b/packages/CompanionDeviceManager/res/values-mr/strings.xml
index 50ab307..de4f7fd 100644
--- a/packages/CompanionDeviceManager/res/values-mr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mr/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"मायक्रोफोन"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"कॉल लॉग"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"जवळपासची डिव्हाइस"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"मीडिया आउटपुट बदला"</string>
     <string name="permission_storage" msgid="6831099350839392343">"फोटो आणि मीडिया"</string>
-    <string name="permission_notification" msgid="693762568127741203">"सूचना"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"ॲप्स"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"स्ट्रीमिंग"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"फोन कॉल करू आणि व्यवस्थापित करू शकते"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"फोन कॉल लॉग रीड अँड राइट करू शकते"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"एसएमएस मेसेज पाठवू आणि पाहू शकते"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"तुमचे संपर्क अ‍ॅक्सेस करू शकते"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"तुमचे कॅलेंडर अ‍ॅक्सेस करू शकते"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"ऑडिओ रेकॉर्ड करू शकते"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"जवळील डिव्हाइस शोधू शकते, त्यांच्याशी कनेक्ट करू शकते आणि त्यांचे संबंधित स्थान निर्धारित करू शकते"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"संपर्क, मेसेज आणि फोटो यांसारख्या माहितीचा समावेश असलेल्या सर्व सूचना वाचू शकते"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"तुमच्या फोनवरील ॲप्स स्ट्रीम करा"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"तुमच्या फोनवरून अ‍ॅप्स आणि इतर सिस्टीम वैशिष्‍ट्ये स्ट्रीम करा"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"उपलब्ध डिव्‍हाइसची सूची अ‍ॅक्सेस करा आणि इतर कोणत्‍या अ‍ॅप्सवरून ऑडिओ किंवा व्हिडिओ स्ट्रीम केला अथवा कास्‍ट केला हे नियंत्रित करा"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"फोन"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"टॅबलेट"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-ms/strings.xml b/packages/CompanionDeviceManager/res/values-ms/strings.xml
index ef110b6..62b68f3 100644
--- a/packages/CompanionDeviceManager/res/values-ms/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ms/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Log panggilan"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Peranti berdekatan"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Tukar output media"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Foto dan media"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Pemberitahuan"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Apl"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Penstriman"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Boleh membuat dan mengurus panggilan telefon"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Boleh membaca dan menulis log panggilan telefon"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Boleh menghantar dan melihat mesej SMS"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Boleh mengakses kenalan anda"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Boleh mengakses kalendar anda"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Boleh merakamkan audio"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Boleh mencari, menyambung dan menentukan kedudukan relatif peranti berdekatan"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Boleh membaca semua pemberitahuan, termasuk maklumat seperti kenalan, mesej dan foto"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Strim apl telefon anda"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Strim apl dan ciri sistem yang lain daripada telefon anda"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Akses senarai peranti tersedia dan kawal peranti yang menstrim atau menghantar audio atau video daripada apl lain"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"telefon"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tablet"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-my/strings.xml b/packages/CompanionDeviceManager/res/values-my/strings.xml
index 57f2e23..f99009c 100644
--- a/packages/CompanionDeviceManager/res/values-my/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-my/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"မိုက်ခရိုဖုန်း"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"ခေါ်ဆိုမှတ်တမ်း"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"အနီးတစ်ဝိုက်ရှိ စက်များ"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"မီဒီယာအထွက် ပြောင်းခြင်း"</string>
     <string name="permission_storage" msgid="6831099350839392343">"ဓာတ်ပုံနှင့် မီဒီယာများ"</string>
-    <string name="permission_notification" msgid="693762568127741203">"အကြောင်းကြားချက်များ"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"အက်ပ်များ"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"တိုက်ရိုက်ဖွင့်ခြင်း"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"ဖုန်းခေါ်ဆိုမှုများကို ပြုလုပ်ခြင်းနှင့် စီမံခြင်းတို့ လုပ်နိုင်သည်"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"ဖုန်းခေါ်ဆိုမှတ်တမ်းကို ဖတ်ခြင်းနှင့် ရေးခြင်းတို့ လုပ်နိုင်သည်"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"SMS မက်ဆေ့ဂျ်များကို ပို့ခြင်းနှင့် ကြည့်ရှုခြင်းတို့ လုပ်နိုင်သည်"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"သင့်အဆက်အသွယ်များကို ဝင်ကြည့်နိုင်သည်"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"သင့်ပြက္ခဒိန်ကို သုံးနိုင်သည်"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"အသံဖမ်းနိုင်သည်"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"အနီးတစ်ဝိုက်ရှိ စက်များ၏ ဆက်စပ်နေရာကို ရှာခြင်း၊ ချိတ်ဆက်ခြင်းနှင့် သတ်မှတ်ခြင်းတို့ လုပ်နိုင်သည်"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"အဆက်အသွယ်၊ မက်ဆေ့ဂျ်နှင့် ဓာတ်ပုံကဲ့သို့ အချက်အလက်များအပါအဝင် အကြောင်းကြားချက်အားလုံးကို ဖတ်နိုင်သည်"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"သင့်ဖုန်းရှိအက်ပ်များကို တိုက်ရိုက်ဖွင့်နိုင်သည်"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"သင့်ဖုန်းမှ အက်ပ်များနှင့် အခြားစနစ်အင်္ဂါရပ်များကို တိုက်ရိုက်ဖွင့်သည်"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"အခြားအက်ပ်များတွင် အသံ (သို့) ဗီဒီယို တိုက်ရိုက်ဖွင့်၍ (သို့) ကာစ်လုပ်၍ ရနိုင်သော စက်ပစ္စည်းစာရင်းကို ဝင်ကြည့်ပြီး ရွေးလိုက်သည့်တစ်ခုကို ထိန်းချုပ်နိုင်သည်"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"ဖုန်း"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"တက်ဘလက်"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-nb/strings.xml b/packages/CompanionDeviceManager/res/values-nb/strings.xml
index 083ec99..7f09149 100644
--- a/packages/CompanionDeviceManager/res/values-nb/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-nb/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Samtalelogger"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Enheter i nærheten"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Bytt medieutgang"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Bilder og medier"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Varsler"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Apper"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Strømming"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Kan ringe ut og administrere anrop"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Kan lese og skrive samtaleloggen"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Kan sende og lese SMS-meldinger"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Kan bruke kontaktene dine"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Kan bruke kalenderen din"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Kan ta opp lyd"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Kan finne, koble til og fastslå den relative posisjonen til enheter i nærheten"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Kan lese alle varsler, inkludert informasjon som kontakter, meldinger og bilder"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Strøm appene på telefonen"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Strøm apper og andre systemfunksjoner fra telefonen"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Se en liste over tilgjengelige enheter, og kontroller hvilken enhet som strømmer eller caster lyd eller video fra andre apper"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"telefon"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"nettbrett"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-ne/strings.xml b/packages/CompanionDeviceManager/res/values-ne/strings.xml
index 7a1df5f..38facb9 100644
--- a/packages/CompanionDeviceManager/res/values-ne/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ne/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"माइक्रोफोन"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"कल लगहरू"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"नजिकैका डिभाइसहरू"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"मिडिया आउटपुट बदल्नुहोस्"</string>
     <string name="permission_storage" msgid="6831099350839392343">"फोटो र मिडिया"</string>
-    <string name="permission_notification" msgid="693762568127741203">"सूचनाहरू"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"एपहरू"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"स्ट्रिमिङ"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"फोन कल गर्न र कलहरू व्यवस्थापन गर्न सक्छ"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"फोनको कल लग रिड र राइट गर्न सक्छ"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"SMS म्यासेजहरू पठाउन र हेर्न सक्छ"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"तपाईंका कन्ट्याक्टहरू हेर्न सक्छ"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"तपाईंको पात्रो हेर्न सक्छ"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"अडियो रेकर्ड गर्न सक्छ"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"नजिकैका डिभाइसहरू भेट्टाउन, ती डिभाइससँग कनेक्ट गर्न र तिनको सापेक्ष स्थिति निर्धारण गर्न सक्छ"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"कन्ट्याक्ट, म्यासेज र फोटोलगायतका जानकारीसहित सबै सूचनाहरू पढ्न सक्छ"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"आफ्नो फोनका एपहरू प्रयोग गर्नुहोस्"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"आफ्नो फोनबाट एप र सिस्टमका अन्य सुविधाहरू स्ट्रिम गर्नुहोस्"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"उपलब्ध डिभाइसहरूको सूची एक्सेस गर्नुहोस् र अन्य एपका अडियो वा भिडियो कुन डिभाइसबाट कास्ट गर्ने भन्ने कुरा नियन्त्रण गर्नुहोस्"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"फोन"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"ट्याब्लेट"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-nl/strings.xml b/packages/CompanionDeviceManager/res/values-nl/strings.xml
index fc5a044..38c92e5 100644
--- a/packages/CompanionDeviceManager/res/values-nl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-nl/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Microfoon"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Gesprekslijsten"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Apparaten in de buurt"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Media-uitvoer wijzigen"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Foto\'s en media"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Meldingen"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Streaming"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Kan telefoongesprekken starten en beheren"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Kan gesprekslijst lezen en ernaar schrijven"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Kan sms-berichten sturen en bekijken"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Heeft toegang tot je contacten"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Heeft toegang tot je agenda"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Kan audio opnemen"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Kan apparaten in de buurt vinden, er verbinding mee maken en de relatieve positie ervan bepalen"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Kan alle meldingen lezen, waaronder informatie zoals contacten, berichten en foto\'s"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Stream de apps van je telefoon"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Apps en andere systeemfuncties streamen vanaf je telefoon"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Krijg toegang tot een lijst met beschikbare apparaten en beheer welk apparaat audio of video streamt of cast via andere apps"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"telefoon"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tablet"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-or/strings.xml b/packages/CompanionDeviceManager/res/values-or/strings.xml
index a058374..16985fa 100644
--- a/packages/CompanionDeviceManager/res/values-or/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-or/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"ମାଇକ୍ରୋଫୋନ"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"କଲ ଲଗଗୁଡ଼ିକ"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"ଆଖପାଖର ଡିଭାଇସଗୁଡ଼ିକ"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"ମିଡିଆ ଆଉଟପୁଟ ପରିବର୍ତ୍ତନ କରନ୍ତୁ"</string>
     <string name="permission_storage" msgid="6831099350839392343">"ଫଟୋ ଏବଂ ମିଡିଆ"</string>
-    <string name="permission_notification" msgid="693762568127741203">"ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"ଆପ୍ସ"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"ଷ୍ଟ୍ରିମିଂ"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"ଫୋନ କଲଗୁଡ଼ିକ କରିପାରିବ ଏବଂ ସେଗୁଡ଼ିକୁ ପରିଚାଳନା କରିପାରିବ"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"ଫୋନ କଲ ଲଗକୁ ପଢ଼ିପାରିବ ଏବଂ ଲେଖିପାରିବ"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"SMS ମେସେଜଗୁଡ଼ିକ ପଠାଇପାରିବ ଏବଂ ଦେଖିପାରିବ"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"ଆପଣଙ୍କ କଣ୍ଟାକ୍ଟଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିପାରିବ"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"ଆପଣଙ୍କ କେଲେଣ୍ଡରକୁ ଆକ୍ସେସ କରିପାରିବ"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"ଅଡିଓ ରେକର୍ଡ କରିପାରିବ"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"ଆଖପାଖର ଡିଭାଇସଗୁଡ଼ିକୁ ଖୋଜିପାରିବ, କନେକ୍ଟ କରିପାରିବ ଏବଂ ସେଗୁଡ଼ିକର ଆପେକ୍ଷିକ ଅବସ୍ଥିତିକୁ ନିର୍ଦ୍ଧାରଣ କରିପାରିବ"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"ଯୋଗାଯୋଗ, ମେସେଜ ଏବଂ ଫଟୋଗୁଡ଼ିକ ପରି ସୂଚନା ସମେତ ସମସ୍ତ ବିଜ୍ଞପ୍ତିକୁ ପଢ଼ିପାରିବ"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"ଆପଣଙ୍କ ଫୋନର ଆପ୍ସକୁ ଷ୍ଟ୍ରିମ କରନ୍ତୁ"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"ଆପଣଙ୍କ ଫୋନରୁ ଆପ୍ସ ଏବଂ ଅନ୍ୟ ସିଷ୍ଟମ ଫିଚରଗୁଡ଼ିକୁ ଷ୍ଟ୍ରିମ କରନ୍ତୁ"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"ଉପଲବ୍ଧ ଡିଭାଇସଗୁଡ଼ିକର ଏକ ତାଲିକାକୁ ଆକ୍ସେସ କରନ୍ତୁ ଏବଂ କେଉଁ ଡିଭାଇସ ଅନ୍ୟ ଆପ୍ସରୁ ଅଡିଓ କିମ୍ୱା ଭିଡିଓ ଷ୍ଟ୍ରିମ ବା କାଷ୍ଟ କରିବ ତାହା ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"ଫୋନ"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"ଟାବଲେଟ"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-pa/strings.xml b/packages/CompanionDeviceManager/res/values-pa/strings.xml
index 984ec48..31f9ec9 100644
--- a/packages/CompanionDeviceManager/res/values-pa/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pa/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"ਮਾਈਕ੍ਰੋਫ਼ੋਨ"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"ਕਾਲ ਲੌਗ"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"ਨਜ਼ਦੀਕੀ ਡੀਵਾਈਸ"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"ਮੀਡੀਆ ਆਊਟਪੁੱਟ ਬਦਲੋ"</string>
     <string name="permission_storage" msgid="6831099350839392343">"ਫ਼ੋਟੋਆਂ ਅਤੇ ਮੀਡੀਆ"</string>
-    <string name="permission_notification" msgid="693762568127741203">"ਸੂਚਨਾਵਾਂ"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"ਐਪਾਂ"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"ਸਟ੍ਰੀਮਿੰਗ"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"ਫ਼ੋਨ ਕਾਲਾਂ ਕਰਨ ਅਤੇ ਉਨ੍ਹਾਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਹੈ"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"ਫ਼ੋਨ ਦੇ ਕਾਲ ਲੌਗ ਨੂੰ ਪੜ੍ਹਣ ਅਤੇ ਲਿਖਣ ਦੀ ਇਜਾਜ਼ਤ ਹੈ"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"SMS ਸੁਨੇਹੇ ਭੇਜਣ ਅਤੇ ਦੇਖਣ ਦੀ ਇਜਾਜ਼ਤ ਹੈ"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"ਆਪਣੇ ਸੰਪਰਕਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਹੈ"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"ਆਪਣੇ ਕੈਲੰਡਰ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਹੈ"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"ਆਡੀਓ ਰਿਕਾਰਡ ਕੀਤੀ ਜਾ ਸਕਦੀ ਹੈ"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"ਨਜ਼ਦੀਕੀ ਡੀਵਾਈਸਾਂ ਨੂੰ ਲੱਭਣ, ਉਨ੍ਹਾਂ ਨਾਲ ਕਨੈਕਟ ਕਰਨ ਅਤੇ ਸੰਬੰਧਿਤ ਸਥਿਤੀ ਨਿਰਧਾਰਿਤ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਹੈ"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"ਤੁਸੀਂ ਸਾਰੀਆਂ ਸੂਚਨਾਵਾਂ ਪੜ੍ਹ ਸਕਦੇ ਹੋ, ਜਿਨ੍ਹਾਂ ਵਿੱਚ ਸੰਪਰਕਾਂ, ਸੁਨੇਹਿਆਂ ਅਤੇ ਫ਼ੋਟੋਆਂ ਵਰਗੀ ਜਾਣਕਾਰੀ ਸ਼ਾਮਲ ਹੁੰਦੀ ਹੈ"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"ਆਪਣੇ ਫ਼ੋਨ ਦੀਆਂ ਐਪਾਂ ਨੂੰ ਸਟ੍ਰੀਮ ਕਰੋ"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"ਆਪਣੇ ਫ਼ੋਨ ਤੋਂ ਐਪਾਂ ਅਤੇ ਹੋਰ ਸਿਸਟਮ ਸੰਬੰਧੀ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਨੂੰ ਸਟ੍ਰੀਮ ਕਰੋ"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"ਉਪਲਬਧ ਡੀਵਾਈਸਾਂ ਦੀ ਸੂਚੀ ਤੱਕ ਪਹੁੰਚ ਕਰੋ ਅਤੇ ਇਹ ਕੰਟਰੋਲ ਕਰੋ ਕਿ ਕਿਹੜਾ ਡੀਵਾਈਸ ਹੋਰ ਐਪਾਂ ਤੋਂ ਆਡੀਓ ਜਾਂ ਵੀਡੀਓ ਨੂੰ ਸਟ੍ਰੀਮ ਜਾਂ ਕਾਸਟ ਕਰ ਸਕਦਾ ਹੈ"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"ਫ਼ੋਨ"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"ਟੈਬਲੈੱਟ"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-pl/strings.xml b/packages/CompanionDeviceManager/res/values-pl/strings.xml
index 4eb8de6..abffff1 100644
--- a/packages/CompanionDeviceManager/res/values-pl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pl/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Rejestry połączeń"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Urządzenia w pobliżu"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Zmień wyjście multimediów"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Zdjęcia i multimedia"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Powiadomienia"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Aplikacje"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Strumieniowanie"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Może wykonywać i odbierać połączenia"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Może odczytywać i zapisywać rejestr połączeń telefonicznych"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Może wysyłać i odbierać SMS-y"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Może uzyskać dostęp do kontaktów"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Może uzyskać dostęp do kalendarza"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Może nagrywać dźwięk"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Może znajdować urządzenia w pobliżu, określać ich względne położenie oraz łączyć się z nimi"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Może odczytywać wszystkie powiadomienia, w tym informacje takie jak kontakty, wiadomości i zdjęcia"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Odtwarzaj strumieniowo aplikacje z telefonu"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Aplikacje do odtwarzania strumieniowego i inne funkcje systemowe na Twoim telefonie"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Uzyskaj dostęp do listy dostępnych urządzeń i określ, które z nich ma strumieniować lub przesyłać ścieżkę audio bądź wideo z innych aplikacji"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"telefon"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tablet"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml b/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml
index 26647c8..a95dcb6 100644
--- a/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Microfone"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Registro de chamadas"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Dispositivos por perto"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Mudar saída de mídia"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Fotos e mídia"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Notificações"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Streaming"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Pode fazer e gerenciar ligações"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Pode ler e gravar o registro de chamadas"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Pode enviar e acessar mensagens SMS"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Pode acessar seus contatos"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Pode acessar sua agenda"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Pode gravar áudio"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Pode encontrar, determinar o posicionamento relativo e se conectar a dispositivos por perto"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Pode ler todas as notificações, incluindo informações como contatos, mensagens e fotos"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Fazer transmissão dos apps no seu smartphone"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Fazer streaming de apps e outros recursos do sistema pelo smartphone"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Acesse uma lista de dispositivos disponíveis e controle quais deles podem reproduzir ou transmitir áudio ou vídeo de outros apps"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"smartphone"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tablet"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml b/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
index ba60f56..1d96c0d 100644
--- a/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
@@ -54,21 +54,24 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Microfone"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Registos de chamadas"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Dispositivos próximos"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Alterar a saída de multimédia"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Fotos e multimédia"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Notificações"</string>
+    <string name="permission_notifications" msgid="4099418516590632909">"Notificações"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Streaming"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Pode fazer e gerir chamadas telefónicas"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Pode ler e escrever o registo de chamadas do telemóvel"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Pode enviar e ver mensagens SMS"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Pode aceder aos seus contactos"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Pode aceder ao seu calendário"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Pode gravar áudio"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Pode encontrar, estabelecer ligação e determinar a posição relativa dos dispositivos próximos"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Pode ler todas as notificações, incluindo informações como contactos, mensagens e fotos"</string>
+    <string name="permission_phone_summary" msgid="8246321093970051702">"Fazer e gerir chamadas"</string>
+    <string name="permission_call_logs_summary" msgid="7545243592757693321">"Ler e escrever o registo de chamadas do telemóvel"</string>
+    <string name="permission_sms_summary" msgid="8499509535410068616">"Enviar e ver mensagens SMS"</string>
+    <string name="permission_contacts_summary" msgid="2840800622763086808">"Aceder aos seus contactos"</string>
+    <string name="permission_calendar_summary" msgid="8430353935747336165">"Aceder ao calendário"</string>
+    <string name="permission_microphone_summary" msgid="4862628553869973259">"Gravar áudio"</string>
+    <string name="permission_nearby_devices_summary" msgid="1306752848196464817">"Encontrar, estabelecer ligação e determinar a posição relativa dos dispositivos próximos"</string>
+    <string name="permission_notification_listener_access_summary" msgid="7856071768185367749">"Ler todas as notificações, incluindo informações como contactos, mensagens e fotos"</string>
+    <string name="permission_notifications_summary" msgid="2272810466047367030">"• Ler todas as notificações, incluindo informações como contactos, mensagens e fotos&lt;br/&gt;• Enviar notificações&lt;br/&gt;&lt;br/&gt;Pode gerir a capacidade de esta app ler e enviar notificações em qualquer altura em Definições &gt; Notificações."</string>
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Faça stream das apps do telemóvel"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Faça stream de apps e outras funcionalidades do sistema a partir do telemóvel"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Aceda a uma lista de dispositivos disponíveis e controle qual deles faz stream ou transmite áudio ou vídeo de outras apps"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"telemóvel"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tablet"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-pt/strings.xml b/packages/CompanionDeviceManager/res/values-pt/strings.xml
index 26647c8..a95dcb6 100644
--- a/packages/CompanionDeviceManager/res/values-pt/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pt/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Microfone"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Registro de chamadas"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Dispositivos por perto"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Mudar saída de mídia"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Fotos e mídia"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Notificações"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Streaming"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Pode fazer e gerenciar ligações"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Pode ler e gravar o registro de chamadas"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Pode enviar e acessar mensagens SMS"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Pode acessar seus contatos"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Pode acessar sua agenda"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Pode gravar áudio"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Pode encontrar, determinar o posicionamento relativo e se conectar a dispositivos por perto"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Pode ler todas as notificações, incluindo informações como contatos, mensagens e fotos"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Fazer transmissão dos apps no seu smartphone"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Fazer streaming de apps e outros recursos do sistema pelo smartphone"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Acesse uma lista de dispositivos disponíveis e controle quais deles podem reproduzir ou transmitir áudio ou vídeo de outros apps"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"smartphone"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tablet"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-ro/strings.xml b/packages/CompanionDeviceManager/res/values-ro/strings.xml
index 84182e8..a89da9dc 100644
--- a/packages/CompanionDeviceManager/res/values-ro/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ro/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Microfon"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Jurnale de apeluri"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Dispozitive din apropiere"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Schimbă ieșirea media"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Fotografii și media"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Notificări"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Aplicații"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Streaming"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Poate să dea și să gestioneze apeluri telefonice"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Poate să citească și să scrie în jurnalul de apeluri telefonice"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Poate să trimită și să vadă mesaje SMS"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Poate accesa agenda"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Poate accesa calendarul"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Poate să înregistreze conținut audio"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Poate să găsească, să se conecteze la și să determine poziția relativă a dispozitivelor apropiate"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Poate să citească toate notificările, inclusiv informații cum ar fi agenda, mesajele și fotografiile"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Să redea în stream aplicațiile telefonului"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Redă în stream conținut din aplicații și alte funcții de sistem de pe telefon"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Accesează lista dispozitivelor disponibile și alege-l pe cel care redă în stream sau proiectează conținut audio sau video din alte aplicații"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"telefon"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tabletă"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-ru/strings.xml b/packages/CompanionDeviceManager/res/values-ru/strings.xml
index 9c04adb..9cd823f 100644
--- a/packages/CompanionDeviceManager/res/values-ru/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ru/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Микрофон"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Список вызовов"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Устройства поблизости"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Смена источника вывода медиа"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Фотографии и медиафайлы"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Уведомления"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Приложения"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Потоковая передача"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Приложение сможет совершать вызовы и управлять ими."</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Приложение сможет читать список вызовов и создавать записи в этом списке."</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Приложение сможет отправлять и просматривать SMS."</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Приложение сможет получать доступ к вашему списку контактов."</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Приложение сможет получать доступ к вашему календарю."</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Может записывать аудио"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Приложение сможет находить устройства поблизости, подключаться к ним и определять их относительное местоположение."</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Чтение всех уведомлений, в том числе сведений о контактах, сообщениях и фотографиях."</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Трансляция приложений с телефона."</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Трансляция приложений и системных функций с телефона"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Просмотр списка доступных устройств и управление тем, на котором будет транслироваться аудио и видео из других приложений"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"телефоне"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"планшете"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-si/strings.xml b/packages/CompanionDeviceManager/res/values-si/strings.xml
index daa2058..d83c1f1 100644
--- a/packages/CompanionDeviceManager/res/values-si/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-si/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"මයික්‍රෆෝනය"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"ඇමතුම් ලොග"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"අවට උපාංග"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"මාධ්‍ය ප්‍රතිදානය වෙනස් කරන්න"</string>
     <string name="permission_storage" msgid="6831099350839392343">"ඡායාරූප සහ මාධ්‍ය"</string>
-    <string name="permission_notification" msgid="693762568127741203">"දැනුම්දීම්"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"යෙදුම්"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"ප්‍රවාහ කිරීම"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"දුරකථන ඇමතුම් ගැනීමට සහ කළමනාකරණය කිරීමට හැක"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"දුරකථන ඇමතුම් ලොගය කියවීමට සහ ලිවීමට හැක"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"SMS පණිවිඩ යැවීමට සහ බැලීමට හැක"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"ඔබේ සම්බන්ධතා වෙත ප්‍රවේශ විය හැක"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"ඔබේ දින දර්ශනයට ප්‍රවේශ විය හැක"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"ශ්‍රව්‍ය පටිගත කළ හැක"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"අවට උපාංගවල සාපේක්ෂ පිහිටීම සොයා ගැනීමට, සම්බන්ධ කිරීමට, සහ තීරණය කිරීමට හැක"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"සම්බන්ධතා, පණිවිඩ සහ ඡායාරූප වැනි තොරතුරු ඇතුළුව සියලු දැනුම්දීම් කියවිය හැකිය"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"ඔබේ දුරකථනයේ යෙදුම් ප්‍රවාහ කරන්න"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"ඔබේ දුරකථනයෙන් යෙදුම් සහ අනෙකුත් පද්ධති විශේෂාංග ප්‍රවාහ කරන්න"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"පවතින උපාංග ලැයිස්තුවකට ප්‍රවේශ වන්න සහ වෙනත් යෙදුම් වෙතින් ශ්‍රව්‍ය හෝ වීඩියෝ ප්‍රවාහ කරන්නේ කුමන එකක් ද යන්න පාලනය කරන්න"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"දුරකථනය"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"ටැබ්ලටය"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-sk/strings.xml b/packages/CompanionDeviceManager/res/values-sk/strings.xml
index 929b56c..55e6daf8 100644
--- a/packages/CompanionDeviceManager/res/values-sk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sk/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Mikrofón"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Zoznam hovorov"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Zariadenia v okolí"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Zmena výstupu médií"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Fotky a médiá"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Upozornenia"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Aplikácie"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Streaming"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Môže uskutočňovať a spravovať telefonické hovory"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Môže čítať zo zoznamu hovorov telefónu a zapisovať doň"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Môže odosielať a zobrazovať správy SMS"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Má prístup k vašim kontaktom"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Má prístup k vášmu kalendáru"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Môže nahrávať zvuk"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Môže vyhľadávať zariadenia v okolí, určovať ich relatívnu pozíciu a pripájať sa k nim"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Môže čítať všetky upozornenia vrátane informácií, ako sú kontakty, správy a fotky"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Streamovať aplikácie telefónu"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Streaming aplikácii a ďalších systémových funkcií zo zariadenia"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Získajte prístup k dostupným zariadeniam a ovládajte, ktoré bude streamovať alebo prenášať zvuk či video z iných aplikácií"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"telefón"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tablet"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-sl/strings.xml b/packages/CompanionDeviceManager/res/values-sl/strings.xml
index b1b1e91..097b7b6 100644
--- a/packages/CompanionDeviceManager/res/values-sl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sl/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Dnevniki klicev"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Naprave v bližini"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Spreminjanje izhoda za predstavnost"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Fotografije in predstavnost"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Obvestila"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Aplikacije"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Pretočno predvajanje"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Lahko opravlja in upravlja telefonske klice"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Lahko bere in zapisuje dnevnik klicev v telefonu"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Lahko pošilja in si ogleduje sporočila SMS"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Lahko dostopa do stikov"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Lahko dostopa do koledarja"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Lahko snema zvok"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Lahko išče naprave v bližini, se povezuje z njimi in določa njihov relativni položaj"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Lahko bere vsa obvestila, vključno s podatki, kot so stiki, sporočila in fotografije."</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Pretočno predvajanje aplikacij telefona"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Pretočno predvajanje aplikacij in drugih sistemskih funkcij iz telefona"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Dostop do seznama razpoložljivih naprav in upravljanje, katera naprava pretočno ali na daljavo predvaja zvok ali videoposnetek iz drugih aplikacij"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"telefon"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tablični računalnik"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-sq/strings.xml b/packages/CompanionDeviceManager/res/values-sq/strings.xml
index 037a707..416de58 100644
--- a/packages/CompanionDeviceManager/res/values-sq/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sq/strings.xml
@@ -54,21 +54,36 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Mikrofoni"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Evidencat e telefonatave"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Pajisjet në afërsi"</string>
+    <!-- no translation found for permission_media_routing_control (5498639511586715253) -->
+    <skip />
     <string name="permission_storage" msgid="6831099350839392343">"Fotografitë dhe media"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Njoftimet"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Aplikacionet"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Transmetimi"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Mund të bëjë dhe të menaxhojë telefonatat"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Mund të lexojë dhe të shkruajë në evidencën e telefonatave"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Mund të dërgojë dhe të shikojë mesazhet SMS"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Mund të ketë qasje te kontaktet e tua"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Mund të ketë qasje te kalendari"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Mund të regjistrojë audio"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Mund të gjejë, të lidhet dhe të përcaktojë pozicionin e përafërt të pajisjeve në afërsi"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Mund të lexojë të gjitha njoftimet, duke përfshirë informacione si kontaktet, mesazhet dhe fotografitë"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Transmeto aplikacionet e telefonit tënd"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Transmeto aplikacionet dhe veçoritë e tjera të sistemit nga telefoni yt"</string>
+    <!-- no translation found for permission_media_routing_control_summary (2714631092321412250) -->
+    <skip />
     <string name="device_type" product="default" msgid="8268703872070046263">"telefon"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tablet"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-sr/strings.xml b/packages/CompanionDeviceManager/res/values-sr/strings.xml
index 3817d58..9b95769 100644
--- a/packages/CompanionDeviceManager/res/values-sr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sr/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Микрофон"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Евиденције позива"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Уређаји у близини"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Промена медијског излаза"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Слике и медији"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Обавештења"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Апликације"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Стриминг"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Може да упућује телефонске позиве и управља њима"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Може да чита и пише евиденцију позива на телефону"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Може да шаље и прегледа SMS поруке"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Може да приступа контактима"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Може да приступа календару"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Може да снима звук"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Може да проналази и утврђује релативну позицију уређаја у близини, као и да се повезује са њима"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Може да чита сва обавештења, укључујући информације попут контаката, порука и слика"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Стримујте апликације на телефону"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Стримујте апликације и друге системске функције са телефона"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Приступ листи доступних уређаја и контрола уређаја који стримује или пребацује аудио или видео из других апликација"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"телефону"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"таблету"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-sv/strings.xml b/packages/CompanionDeviceManager/res/values-sv/strings.xml
index f3be3be..e17fb04 100644
--- a/packages/CompanionDeviceManager/res/values-sv/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sv/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Samtalsloggar"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Enheter i närheten"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Ändra uppspelning av media"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Foton och media"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Aviseringar"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Appar"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Streaming"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Får skapa och hantera telefonsamtal"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Får läsa och skriva samtalslogg"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Får skicka och visa sms"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Får åtkomst till dina kontakter"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Får åtkomst till din kalender"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Kan spela in ljud"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Får hitta, ansluta till och avgöra den relativa positionen för enheter i närheten"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Kan läsa alla aviseringar, inklusive information som kontakter, meddelanden och foton"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Streama telefonens appar"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Streama appar och andra systemfunktioner från din telefon"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Få åtkomst till en lista över tillgängliga enheter och styr vilken som streamar eller castar ljud eller video från andra appar"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"telefon"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"surfplatta"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-sw/strings.xml b/packages/CompanionDeviceManager/res/values-sw/strings.xml
index 7b94239..59a6a0e 100644
--- a/packages/CompanionDeviceManager/res/values-sw/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sw/strings.xml
@@ -52,23 +52,38 @@
     <string name="permission_contacts" msgid="3858319347208004438">"Anwani"</string>
     <string name="permission_calendar" msgid="6805668388691290395">"Kalenda"</string>
     <string name="permission_microphone" msgid="2152206421428732949">"Maikrofoni"</string>
-    <string name="permission_call_logs" msgid="5546761417694586041">"Rekodi za nambari za simu"</string>
+    <string name="permission_call_logs" msgid="5546761417694586041">"Rekodi za namba za simu"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Vifaa vilivyo karibu"</string>
+    <!-- no translation found for permission_media_routing_control (5498639511586715253) -->
+    <skip />
     <string name="permission_storage" msgid="6831099350839392343">"Picha na maudhui"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Arifa"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Programu"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Kutiririsha maudhui"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Inaweza kupiga na kudhibiti simu"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Inaweza kusoma na kuandika rekodi ya nambari za simu"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Inaweza kutuma na kuangalia ujumbe wa SMS"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Inaweza kufikia anwani zako"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Inaweza kufikia kalenda yako"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Inaweza kurekodi sauti"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Inaweza kutafuta, kuunganisha na kubaini nafasi ya makadirio ya vifaa vilivyo karibu"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Inaweza kusoma arifa zote, ikiwa ni pamoja na maelezo kama vile anwani, ujumbe na picha"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Tiririsha programu za simu yako"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Kutiririsha programu na vipengele vya mfumo kwenye simu yako"</string>
+    <!-- no translation found for permission_media_routing_control_summary (2714631092321412250) -->
+    <skip />
     <string name="device_type" product="default" msgid="8268703872070046263">"simu"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"kompyuta kibao"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-ta/strings.xml b/packages/CompanionDeviceManager/res/values-ta/strings.xml
index c1b8352..97d59fd 100644
--- a/packages/CompanionDeviceManager/res/values-ta/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ta/strings.xml
@@ -54,21 +54,36 @@
     <string name="permission_microphone" msgid="2152206421428732949">"மைக்ரோஃபோன்"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"அழைப்புப் பதிவுகள்"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"அருகிலுள்ள சாதனங்கள்"</string>
+    <!-- no translation found for permission_media_routing_control (5498639511586715253) -->
+    <skip />
     <string name="permission_storage" msgid="6831099350839392343">"படங்கள் மற்றும் மீடியா"</string>
-    <string name="permission_notification" msgid="693762568127741203">"அறிவிப்புகள்"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"ஆப்ஸ்"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"ஸ்ட்ரீமிங்"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"மொபைல் அழைப்புகளைச் செய்யலாம் நிர்வகிக்கலாம்"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"மொபைல் அழைப்புப் பதிவைப் படிக்கலாம் எழுதலாம்"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"மெசேஜ்களை அனுப்பலாம் பார்க்கலாம்"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"உங்கள் தொடர்புகளை அணுகலாம்"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"உங்கள் கேலெண்டரை அணுகலாம்"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"ஆடியோவை ரெக்கார்டு செய்யலாம்"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"அருகிலுள்ள சாதனங்களைக் கண்டறியலாம் அவற்றுடன் இணையலாம் அவற்றின் தூரத்தைத் தீர்மானிக்கலாம்"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"தொடர்புகள், மெசேஜ்கள், படங்கள் போன்ற தகவல்கள் உட்பட அனைத்து அறிவிப்புகளையும் படிக்க முடியும்"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"உங்கள் மொபைல் ஆப்ஸை ஸ்ட்ரீம் செய்யலாம்"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"உங்கள் மொபைலில் இருந்து ஆப்ஸையும் பிற சிஸ்டம் அம்சங்களையும் ஸ்ட்ரீம் செய்யலாம்"</string>
+    <!-- no translation found for permission_media_routing_control_summary (2714631092321412250) -->
+    <skip />
     <string name="device_type" product="default" msgid="8268703872070046263">"மொபைல்"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"டேப்லெட்"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-te/strings.xml b/packages/CompanionDeviceManager/res/values-te/strings.xml
index 52316cd..c6af6ed 100644
--- a/packages/CompanionDeviceManager/res/values-te/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-te/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"మైక్రోఫోన్"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"కాల్ లాగ్‌లు"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"సమీపంలోని పరికరాలు"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"మీడియా అవుట్‌పుట్‌ను మార్చండి"</string>
     <string name="permission_storage" msgid="6831099350839392343">"ఫోటోలు, మీడియా"</string>
-    <string name="permission_notification" msgid="693762568127741203">"నోటిఫికేషన్‌లు"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"యాప్‌లు"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"స్ట్రీమింగ్"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"ఫోన్ కాల్స్ చేయగలదు, అలాగే మేనేజ్ చేయగలదు"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"ఫోన్ కాల్ లాగ్‌ను చదవగలదు, రాయగలదు"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"SMS మెసేజ్‌లను పంపగలదు, అలాగే చూడగలదు"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"మీ కాంటాక్ట్‌లను యాక్సెస్ చేయగలదు"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"మీ క్యాలెండర్‌ను యాక్సెస్ చేయగలదు"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"ఆడియోను రికార్డ్ చేయగలదు"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"సమీపంలోని పరికరాలను కనుగొనగలదు, వాటికి కనెక్ట్ అవ్వగలదు, అవి ఎంత దూరంలో ఉన్నాయో తెలుసుకొనగలదు"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"కాంటాక్ట్‌లు, మెసేజ్‌లు, ఫోటోల వంటి సమాచారంతో సహా అన్ని నోటిఫికేషన్‌లను చదవగలదు"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"మీ ఫోన్‌లోని యాప్‌లను స్ట్రీమ్ చేయండి"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"మీ ఫోన్ నుండి యాప్‌లను, ఇతర సిస్టమ్ ఫీచర్‌లను స్ట్రీమ్ చేస్తుంది"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"అందుబాటులో ఉన్న పరికరాల లిస్ట్‌ను యాక్సెస్ చేసి, ఇతర యాప్‌లలోని ఆడియో లేదా వీడియోను ఏ పరికరం స్ట్రీమ్ చేయాలో లేదా ప్రసారం చేయాలో కంట్రోల్ చేయండి"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"ఫోన్"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"టాబ్లెట్"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-th/strings.xml b/packages/CompanionDeviceManager/res/values-th/strings.xml
index 5d491db..3925747 100644
--- a/packages/CompanionDeviceManager/res/values-th/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-th/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"ไมโครโฟน"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"บันทึกการโทร"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"อุปกรณ์ที่อยู่ใกล้เคียง"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"เปลี่ยนเอาต์พุตสื่อ"</string>
     <string name="permission_storage" msgid="6831099350839392343">"รูปภาพและสื่อ"</string>
-    <string name="permission_notification" msgid="693762568127741203">"การแจ้งเตือน"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"แอป"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"สตรีมมิง"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"สามารถโทรออกและจัดการการโทร"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"สามารถอ่านและเขียนบันทึกการโทรของโทรศัพท์"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"สามารถส่งและดูข้อความ SMS"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"สามารถเข้าถึงรายชื่อติดต่อของคุณ"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"สามารถเข้าถึงปฏิทินของคุณ"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"บันทึกเสียงได้"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"สามารถค้นหา เชื่อมต่อ และระบุตำแหน่งซึ่งสัมพันธ์กับอุปกรณ์ที่อยู่ใกล้เคียง"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"สามารถอ่านการแจ้งเตือนทั้งหมด รวมถึงข้อมูลอย่างรายชื่อติดต่อ ข้อความ และรูปภาพ"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"สตรีมแอปของโทรศัพท์คุณ"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"สตรีมแอปและฟีเจอร์อื่นๆ ของระบบจากโทรศัพท์"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"เข้าถึงรายการอุปกรณ์ที่มีและควบคุมอุปกรณ์ที่จะสตรีมหรือแคสต์เสียงหรือวิดีโอจากแอปอื่นๆ"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"โทรศัพท์"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"แท็บเล็ต"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-tl/strings.xml b/packages/CompanionDeviceManager/res/values-tl/strings.xml
index 43d5996..f467770 100644
--- a/packages/CompanionDeviceManager/res/values-tl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-tl/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Mikropono"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Mga log ng tawag"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Mga kalapit na device"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Palitan ang media output"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Mga larawan at media"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Mga Notification"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Mga App"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Streaming"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Puwedeng gumawa at mamahala ng mga tawag sa telepono"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Puwedeng magbasa at magsulat ng log ng tawag sa telepono"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Puwedeng magpadala at tumingin ng mga SMS message"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Puwedeng mag-access ng iyong mga contact"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Puwedeng mag-access ng iyong kalendaryo"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Kayang mag-record ng audio"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Puwedeng mahanap ang, kumonekta sa, at tukuyin ang relatibong posisyon ng mga kalapit na device"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Magbasa ng lahat ng notification, kabilang ang impormasyon gaya ng mga contact, mensahe, at larawan"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"I-stream ang mga app ng iyong telepono"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Mag-stream ng mga app at iba pang feature ng system mula sa iyong telepono"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"I-access ang listahan ng mga available na device at kontrolin kung alin ang magsi-stream o magka-cast ng audio o video mula sa iba pang app"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"telepono"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tablet"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-tr/strings.xml b/packages/CompanionDeviceManager/res/values-tr/strings.xml
index 1e8e842..cc8e898 100644
--- a/packages/CompanionDeviceManager/res/values-tr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-tr/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Arama kayıtları"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Yakındaki cihazlar"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Medya çıkışını değiştirin"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Fotoğraflar ve medya"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Bildirimler"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Uygulamalar"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Yayınlama"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Telefon aramaları yapabilir ve telefon aramalarını yönetebilir"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Telefon arama kaydını okuyabilir ve yazabilir"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"SMS mesajları gönderebilir ve görüntüleyebilir"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Kişilerinize erişebilir"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Takviminize erişebilir"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Ses kaydedebilir"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Yakındaki cihazları keşfedip bağlanabilir ve bu cihazların göreli konumunu belirleyebilir"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Kişiler, mesajlar ve fotoğraflar da dahil olmak üzere tüm bildirimleri okuyabilir"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Telefonunuzun uygulamalarını yayınlayabilir"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Telefonunuzdan uygulamaları ve diğer sistem özelliklerini yayınlayabilir"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Kullanılabilir cihazların listesine erişip diğer uygulamalardan ses veya video akışı ya da yayını yapabilecek cihazları kontrol edin"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"telefon"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"tablet"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-uk/strings.xml b/packages/CompanionDeviceManager/res/values-uk/strings.xml
index 39a2b1b..f0433ae 100644
--- a/packages/CompanionDeviceManager/res/values-uk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-uk/strings.xml
@@ -54,21 +54,36 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Мікрофон"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Журнали викликів"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Пристрої поблизу"</string>
+    <!-- no translation found for permission_media_routing_control (5498639511586715253) -->
+    <skip />
     <string name="permission_storage" msgid="6831099350839392343">"Фотографії та медіафайли"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Сповіщення"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Додатки"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Потокове передавання"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Може здійснювати телефонні виклики й керувати ними"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Може переглядати й редагувати журнал викликів телефона"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Може надсилати й переглядати SMS-повідомлення"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Має доступ до ваших контактів"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Має доступ до вашого календаря"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Може записувати аудіо"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Може знаходити пристрої поблизу, підключатися до них і визначати їх відносне розташування"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Може читати всі сповіщення, зокрема таку інформацію, як контакти, повідомлення та фотографії"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Транслювати додатки телефона"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Транслюйте додатки й інші системні функції зі свого телефона"</string>
+    <!-- no translation found for permission_media_routing_control_summary (2714631092321412250) -->
+    <skip />
     <string name="device_type" product="default" msgid="8268703872070046263">"телефоні"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"планшеті"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-ur/strings.xml b/packages/CompanionDeviceManager/res/values-ur/strings.xml
index ce44941..58c1ab6 100644
--- a/packages/CompanionDeviceManager/res/values-ur/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ur/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"مائیکروفون"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"کال لاگز"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"قریبی آلات"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"میڈیا آؤٹ پٹ کو تبدیل کریں"</string>
     <string name="permission_storage" msgid="6831099350839392343">"تصاویر اور میڈیا"</string>
-    <string name="permission_notification" msgid="693762568127741203">"اطلاعات"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"ایپس"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"سلسلہ بندی"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"فون کالز کر سکتا ہے اور ان کا نظم کر سکتا ہے"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"فون کال لاگ پڑھ کر لکھ سکتا ہے"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"‏SMS پیغامات بھیج اور دیکھ سکتا ہے"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"آپ کے رابطوں تک رسائی حاصل کر سکتا ہے"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"آپ کے کیلنڈر تک رسائی حاصل کر سکتا ہے"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"آڈیو ریکارڈ کر سکتی ہے"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"قریبی آلات کی متعلقہ پوزیشن تلاش کر سکتا ہے، ان سے منسلک ہو سکتا ہے اور اس کا تعین کر سکتا ہے"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"رابطوں، پیغامات اور تصاویر جیسی معلومات سمیت تمام اطلاعات پڑھ سکتے ہیں"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"اپنے فون کی ایپس کی سلسلہ بندی کریں"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"اپنے فون سے ایپس اور سسٹم کی دیگر خصوصیات کی سلسلہ بندی کریں"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"دستیاب آلات کی فہرست تک رسائی حاصل کریں اور کنٹرول کریں کہ کون سی دوسری ایپس سے آڈیو یا ویڈیو کی سلسلہ بندی کرتی ہے یا کاسٹ کرتی ہے"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"فون"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"ٹیبلیٹ"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-uz/strings.xml b/packages/CompanionDeviceManager/res/values-uz/strings.xml
index 82b6937..16a7d1d 100644
--- a/packages/CompanionDeviceManager/res/values-uz/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-uz/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Chaqiruvlar jurnali"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Atrofdagi qurilmalar"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Media chiqishini tanlash"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Suratlar va media"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Bildirishnomalar"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Ilovalar"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Striming"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Telefon chaqiruvlarini bajarishi va boshqarishi mumkin"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Telefon chaqiruvlari jurnalini koʻrishi va oʻzgartirishi mumkin"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"SMS xabarlarni koʻrishi va yuborishi mumkin"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Kontaktlarga ruxsati bor"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Taqvimga ruxsati bor"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Audio yozib olish mumkin"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Atrofdagi qurilmalarni qidirishi, joylashuvini aniqlashi va ularga ulanishi mumkin"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Barcha bildirishnomalarni, jumladan, kontaktlar, xabarlar va suratlarni oʻqishi mumkin"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Telefondagi ilovalarni translatsiya qilish"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Telefoningizdan ilovalar va tizim funksiyalarini translatsiya qilish"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Mavjud qurilmalar roʻyxatini olish va qaysi biri boshqa ilovalarga audio yoki video uzatishini boshqarish"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"telefon"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"planshet"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-vi/strings.xml b/packages/CompanionDeviceManager/res/values-vi/strings.xml
index 951f429..a080a5c 100644
--- a/packages/CompanionDeviceManager/res/values-vi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-vi/strings.xml
@@ -54,21 +54,36 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Micrô"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Nhật ký cuộc gọi"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Thiết bị ở gần"</string>
+    <!-- no translation found for permission_media_routing_control (5498639511586715253) -->
+    <skip />
     <string name="permission_storage" msgid="6831099350839392343">"Ảnh và nội dung nghe nhìn"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Thông báo"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Ứng dụng"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Truyền trực tuyến"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Có thể thực hiện và quản lý các cuộc gọi điện thoại"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Có thể đọc và ghi nhật ký cuộc gọi điện thoại"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Có thể gửi và xem tin nhắn SMS"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Có thể truy cập danh bạ"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Có thể truy cập lịch"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Có thể ghi âm"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Có thể tìm, kết nối và xác định vị trí tương đối của các thiết bị ở gần"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Có thể đọc tất cả các thông báo, kể cả những thông tin như danh bạ, tin nhắn và ảnh"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Truyền các ứng dụng trên điện thoại của bạn"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Truyền trực tuyến ứng dụng và các tính năng khác của hệ thống từ điện thoại của bạn"</string>
+    <!-- no translation found for permission_media_routing_control_summary (2714631092321412250) -->
+    <skip />
     <string name="device_type" product="default" msgid="8268703872070046263">"điện thoại"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"máy tính bảng"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
index 5edf9c0..aaa5bef 100644
--- a/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"麦克风"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"通话记录权限"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"附近的设备"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"更改媒体输出"</string>
     <string name="permission_storage" msgid="6831099350839392343">"照片和媒体内容"</string>
-    <string name="permission_notification" msgid="693762568127741203">"通知"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"应用"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"流式传输"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"可以打电话及管理通话"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"可以读取和写入手机通话记录"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"可以发送和查看短信"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"可以访问您的通讯录"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"可以访问您的日历"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"可以录制音频"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"可以查找、连接附近的设备以及确定附近设备的相对位置"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"可以读取所有通知,包括合同、消息和照片等信息"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"流式传输手机上的应用"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"从您的手机流式传输应用和其他系统功能"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"访问可用设备列表,并控制哪个设备可流式传输或投放其他应用的音频/视频"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"手机"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"平板电脑"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
index 0878c23..7c28623 100644
--- a/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"麥克風"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"通話記錄"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"附近的裝置"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"變更媒體輸出"</string>
     <string name="permission_storage" msgid="6831099350839392343">"相片和媒體"</string>
-    <string name="permission_notification" msgid="693762568127741203">"通知"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"應用程式"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"串流"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"可撥打電話和管理通話"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"可讀取及寫入手機通話記錄"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"可傳送及查看短訊"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"可存取通訊錄"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"可存取日曆"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"可以錄音"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"可尋找、連接及判斷附近裝置的相對位置"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"可以讀取所有通知,包括聯絡人、訊息和電話等資訊"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"串流播放手機應用程式內容"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"串流播放手機中的應用程式和其他系統功能"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"存取可用裝置清單,並控制哪一部裝置可串流播放或投放其他應用程式的音訊或影片"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"手機"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"平板電腦"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
index 889d7c8..fa2d60c 100644
--- a/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"麥克風"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"通話記錄"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"鄰近裝置"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"變更媒體輸出"</string>
     <string name="permission_storage" msgid="6831099350839392343">"相片和媒體"</string>
-    <string name="permission_notification" msgid="693762568127741203">"通知"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"應用程式"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"串流"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"可撥打及管理通話"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"可讀取及寫入通話記錄"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"可傳送及查看簡訊"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"可存取聯絡人"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"可存取日曆"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"可以錄音"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"可尋找、連線及判斷鄰近裝置的相對位置"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"可讀取所有通知,包括聯絡人、訊息和電話等資訊"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"串流傳輸手機應用程式內容"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"串流播放手機中的應用程式和其他系統功能"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"存取可用裝置清單,並控制哪一部裝置可串流播放或投放其他應用程式的音訊或影片"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"手機"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"平板電腦"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-zu/strings.xml b/packages/CompanionDeviceManager/res/values-zu/strings.xml
index 7fb5ece..2d90872 100644
--- a/packages/CompanionDeviceManager/res/values-zu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zu/strings.xml
@@ -54,21 +54,34 @@
     <string name="permission_microphone" msgid="2152206421428732949">"Imakrofoni"</string>
     <string name="permission_call_logs" msgid="5546761417694586041">"Amarekhodi wamakholi"</string>
     <string name="permission_nearby_devices" msgid="7530973297737123481">"Amadivayisi aseduze"</string>
+    <string name="permission_media_routing_control" msgid="5498639511586715253">"Shintsha umphumela wemidiya"</string>
     <string name="permission_storage" msgid="6831099350839392343">"Izithombe nemidiya"</string>
-    <string name="permission_notification" msgid="693762568127741203">"Izaziso"</string>
+    <!-- no translation found for permission_notifications (4099418516590632909) -->
+    <skip />
     <string name="permission_app_streaming" msgid="6009695219091526422">"Ama-app"</string>
     <string name="permission_nearby_device_streaming" msgid="1023325519477349499">"Iyasakaza"</string>
-    <string name="permission_phone_summary" msgid="6684396967861278044">"Ingenza futhi iphathe amakholi wefoni"</string>
-    <string name="permission_call_logs_summary" msgid="6186103394658755022">"Ingafunda futhi ibhale irekhodi lamakholi efoni"</string>
-    <string name="permission_sms_summary" msgid="3508442683678912017">"Ingathumela futhi ibuke imiyalezo ye-SMS"</string>
-    <string name="permission_contacts_summary" msgid="675861979475628708">"Ingakwazi ukufinyelela oxhumana nabo"</string>
-    <string name="permission_calendar_summary" msgid="6460000922511766226">"Ingakwazi ukufinyelela ikhalenda lakho"</string>
-    <string name="permission_microphone_summary" msgid="3692091540613093394">"Ingakwazi ukurekhoda umsindo"</string>
-    <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Ingathola, ixhume, futhi inqume indawo ehlobene yamadivayisi aseduze"</string>
-    <string name="permission_notification_summary" msgid="884075314530071011">"Ingafunda zonke izaziso, okubandakanya ulwazi olufana noxhumana nabo, imilayezo, nezithombe"</string>
+    <!-- no translation found for permission_phone_summary (8246321093970051702) -->
+    <skip />
+    <!-- no translation found for permission_call_logs_summary (7545243592757693321) -->
+    <skip />
+    <!-- no translation found for permission_sms_summary (8499509535410068616) -->
+    <skip />
+    <!-- no translation found for permission_contacts_summary (2840800622763086808) -->
+    <skip />
+    <!-- no translation found for permission_calendar_summary (8430353935747336165) -->
+    <skip />
+    <!-- no translation found for permission_microphone_summary (4862628553869973259) -->
+    <skip />
+    <!-- no translation found for permission_nearby_devices_summary (1306752848196464817) -->
+    <skip />
+    <!-- no translation found for permission_notification_listener_access_summary (7856071768185367749) -->
+    <skip />
+    <!-- no translation found for permission_notifications_summary (2272810466047367030) -->
+    <skip />
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Sakaza ama-app wefoni yakho"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
     <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Sakaza ama-app nezinye izakhi zesistimu kusuka kufoni yakho"</string>
+    <string name="permission_media_routing_control_summary" msgid="2714631092321412250">"Finyelela kuhlu lwamadivayisi atholakalayo futhi ulawule ukuthi iyiphi esakaza umsindo noma ividiyo kusuka kwamanye ama-app"</string>
     <string name="device_type" product="default" msgid="8268703872070046263">"ifoni"</string>
     <string name="device_type" product="tablet" msgid="5038791954983067774">"ithebulethi"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values/strings.xml b/packages/CompanionDeviceManager/res/values/strings.xml
index 281eba6..6019aa8 100644
--- a/packages/CompanionDeviceManager/res/values/strings.xml
+++ b/packages/CompanionDeviceManager/res/values/strings.xml
@@ -156,7 +156,7 @@
     <string name="permission_storage">Photos and media</string>
 
     <!-- Notification permission will be granted of corresponding profile [CHAR LIMIT=30] -->
-    <string name="permission_notification">Notifications</string>
+    <string name="permission_notifications">Notifications</string>
 
     <!-- Apps permission will be granted of corresponding profile [CHAR LIMIT=30] -->
     <string name="permission_app_streaming">Apps</string>
@@ -165,28 +165,31 @@
     <string name="permission_nearby_device_streaming">Streaming</string>
 
     <!-- Description of phone permission of corresponding profile [CHAR LIMIT=NONE] -->
-    <string name="permission_phone_summary">Can make and manage phone calls</string>
+    <string name="permission_phone_summary">Make and manage phone calls</string>
 
     <!-- Description of Call logs permission of corresponding profile [CHAR LIMIT=NONE] -->
-    <string name="permission_call_logs_summary">Can read and write phone call log</string>
+    <string name="permission_call_logs_summary">Read and write phone call log</string>
 
     <!-- Description of SMS permission of corresponding profile [CHAR LIMIT=NONE] -->
-    <string name="permission_sms_summary">Can send and view SMS messages</string>
+    <string name="permission_sms_summary">Send and view SMS messages</string>
 
     <!-- Description of contacts permission of corresponding profile [CHAR LIMIT=NONE] -->
-    <string name="permission_contacts_summary">Can access your contacts</string>
+    <string name="permission_contacts_summary">Access your contacts</string>
 
     <!-- Description of calendar permission of corresponding profile [CHAR LIMIT=NONE] -->
-    <string name="permission_calendar_summary">Can access your calendar</string>
+    <string name="permission_calendar_summary">Access your calendar</string>
 
     <!-- Description of microphone permission of corresponding profile [CHAR LIMIT=NONE] -->
-    <string name="permission_microphone_summary">Can record audio</string>
+    <string name="permission_microphone_summary">Record audio</string>
 
     <!-- Description of nearby devices' permission of corresponding profile [CHAR LIMIT=NONE] -->
-    <string name="permission_nearby_devices_summary">Can find, connect to, and determine the relative position of nearby devices</string>
+    <string name="permission_nearby_devices_summary">Find, connect to, and determine the relative position of nearby devices</string>
 
-    <!-- Description of notification permission of corresponding profile [CHAR LIMIT=NONE] -->
-    <string name="permission_notification_summary">Can read all notifications, including information like contacts, messages, and photos</string>
+    <!-- Description of NLA (notification listener access) of corresponding profile [CHAR LIMIT=NONE] -->
+    <string name="permission_notification_listener_access_summary">Read all notifications, including information like contacts, messages, and photos</string>
+
+    <!-- Description of NLA & POST_NOTIFICATION of corresponding profile [CHAR LIMIT=NONE] -->
+    <string name="permission_notifications_summary">\u2022 Read all notifications, including info like contacts, messages, and photos&lt;br/>\u2022 Send notifications&lt;br/>&lt;br/>You can manage this app\'s ability to read and send notifications anytime in Settings > Notifications.</string>
 
     <!-- Description of app streaming permission of corresponding profile [CHAR LIMIT=NONE] -->
     <string name="permission_app_streaming_summary">Stream your phone\u2019s apps</string>
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
index 97016f5..66282dc 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
@@ -27,13 +27,13 @@
 
 import static com.android.companiondevicemanager.CompanionDeviceDiscoveryService.DiscoveryState;
 import static com.android.companiondevicemanager.CompanionDeviceDiscoveryService.DiscoveryState.FINISHED_TIMEOUT;
-import static com.android.companiondevicemanager.CompanionDeviceResources.PERMISSION_TYPES;
-import static com.android.companiondevicemanager.CompanionDeviceResources.PROFILES_NAME;
-import static com.android.companiondevicemanager.CompanionDeviceResources.PROFILE_ICON;
-import static com.android.companiondevicemanager.CompanionDeviceResources.SUMMARIES;
+import static com.android.companiondevicemanager.CompanionDeviceResources.PROFILE_PERMISSIONS;
+import static com.android.companiondevicemanager.CompanionDeviceResources.PROFILE_NAMES;
+import static com.android.companiondevicemanager.CompanionDeviceResources.PROFILE_ICONS;
+import static com.android.companiondevicemanager.CompanionDeviceResources.PROFILE_SUMMARIES;
 import static com.android.companiondevicemanager.CompanionDeviceResources.SUPPORTED_PROFILES;
 import static com.android.companiondevicemanager.CompanionDeviceResources.SUPPORTED_SELF_MANAGED_PROFILES;
-import static com.android.companiondevicemanager.CompanionDeviceResources.TITLES;
+import static com.android.companiondevicemanager.CompanionDeviceResources.PROFILE_TITLES;
 import static com.android.companiondevicemanager.Utils.getApplicationLabel;
 import static com.android.companiondevicemanager.Utils.getHtmlFromResources;
 import static com.android.companiondevicemanager.Utils.getIcon;
@@ -482,7 +482,7 @@
             return;
         }
 
-        title = getHtmlFromResources(this, TITLES.get(deviceProfile), deviceName);
+        title = getHtmlFromResources(this, PROFILE_TITLES.get(deviceProfile), deviceName);
         setupPermissionList(deviceProfile);
 
         // Summary is not needed for selfManaged dialog.
@@ -525,7 +525,16 @@
 
         mSelectedDevice = requireNonNull(deviceFilterPairs.get(0));
 
-        final Drawable profileIcon = getIcon(this, PROFILE_ICON.get(deviceProfile));
+        final Drawable profileIcon = getIcon(this, PROFILE_ICONS.get(deviceProfile));
+
+        // No need to show permission consent dialog if it is a isSkipPrompt(true)
+        // AssociationRequest. See AssociationRequestsProcessor#mayAssociateWithoutPrompt.
+        if (mRequest.isSkipPrompt()) {
+            Log.d(TAG, "Skipping the permission consent dialog.");
+            mSingleDeviceSpinner.setVisibility(View.GONE);
+            onUserSelectedDevice(mSelectedDevice);
+            return;
+        }
 
         updatePermissionUi();
 
@@ -545,14 +554,14 @@
             throw new RuntimeException("Unsupported profile " + deviceProfile);
         }
 
-        profileIcon = getIcon(this, PROFILE_ICON.get(deviceProfile));
+        profileIcon = getIcon(this, PROFILE_ICONS.get(deviceProfile));
 
         if (deviceProfile == null) {
             title = getHtmlFromResources(this, R.string.chooser_title_non_profile, appLabel);
             mButtonNotAllowMultipleDevices.setText(R.string.consent_no);
         } else {
             title = getHtmlFromResources(this,
-                    R.string.chooser_title, getString(PROFILES_NAME.get(deviceProfile)));
+                    R.string.chooser_title, getString(PROFILE_NAMES.get(deviceProfile)));
         }
 
         mDeviceAdapter = new DeviceListAdapter(this, this::onDeviceClicked);
@@ -598,6 +607,14 @@
 
         Log.d(TAG, "onDeviceClicked(): " + mSelectedDevice.toShortString());
 
+        // No need to show permission consent dialog if it is a isSkipPrompt(true)
+        // AssociationRequest. See AssociationRequestsProcessor#mayAssociateWithoutPrompt.
+        if (mRequest.isSkipPrompt()) {
+            Log.d(TAG, "Skipping the permission consent dialog.");
+            onUserSelectedDevice(mSelectedDevice);
+            return;
+        }
+
         updatePermissionUi();
 
         mSummary.setVisibility(View.VISIBLE);
@@ -609,20 +626,12 @@
 
     private void updatePermissionUi() {
         final String deviceProfile = mRequest.getDeviceProfile();
-        final int summaryResourceId = SUMMARIES.get(deviceProfile);
+        final int summaryResourceId = PROFILE_SUMMARIES.get(deviceProfile);
         final String remoteDeviceName = mSelectedDevice.getDisplayName();
         final Spanned title = getHtmlFromResources(
-                this, TITLES.get(deviceProfile), mAppLabel, remoteDeviceName);
+                this, PROFILE_TITLES.get(deviceProfile), mAppLabel, remoteDeviceName);
         final Spanned summary;
 
-        // No need to show permission consent dialog if it is a isSkipPrompt(true)
-        // AssociationRequest. See AssociationRequestsProcessor#mayAssociateWithoutPrompt.
-        if (mRequest.isSkipPrompt()) {
-            mSingleDeviceSpinner.setVisibility(View.GONE);
-            onUserSelectedDevice(mSelectedDevice);
-            return;
-        }
-
         if (deviceProfile == null && mRequest.isSingleDevice()) {
             summary = getHtmlFromResources(this, summaryResourceId, remoteDeviceName);
             mConstraintList.setVisibility(View.GONE);
@@ -680,7 +689,8 @@
     // and when mPermissionListRecyclerView is fully populated.
     // Lastly, disable the Allow and Don't allow buttons.
     private void setupPermissionList(String deviceProfile) {
-        final List<Integer> permissionTypes = new ArrayList<>(PERMISSION_TYPES.get(deviceProfile));
+        final List<Integer> permissionTypes = new ArrayList<>(
+                PROFILE_PERMISSIONS.get(deviceProfile));
         mPermissionListAdapter.setPermissionType(permissionTypes);
         mPermissionListRecyclerView.setAdapter(mPermissionListAdapter);
         mPermissionListRecyclerView.setLayoutManager(mPermissionsLayoutManager);
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceResources.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceResources.java
index 551e975..23a11d6 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceResources.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceResources.java
@@ -22,28 +22,15 @@
 import static android.companion.AssociationRequest.DEVICE_PROFILE_GLASSES;
 import static android.companion.AssociationRequest.DEVICE_PROFILE_NEARBY_DEVICE_STREAMING;
 import static android.companion.AssociationRequest.DEVICE_PROFILE_WATCH;
-
-import static com.android.companiondevicemanager.PermissionListAdapter.PERMISSION_APP_STREAMING;
-import static com.android.companiondevicemanager.PermissionListAdapter.PERMISSION_CALENDAR;
-import static com.android.companiondevicemanager.PermissionListAdapter.PERMISSION_CALL_LOGS;
-import static com.android.companiondevicemanager.PermissionListAdapter.PERMISSION_CHANGE_MEDIA_OUTPUT;
-import static com.android.companiondevicemanager.PermissionListAdapter.PERMISSION_CONTACTS;
-import static com.android.companiondevicemanager.PermissionListAdapter.PERMISSION_MICROPHONE;
-import static com.android.companiondevicemanager.PermissionListAdapter.PERMISSION_NEARBY_DEVICES;
-import static com.android.companiondevicemanager.PermissionListAdapter.PERMISSION_NEARBY_DEVICE_STREAMING;
-import static com.android.companiondevicemanager.PermissionListAdapter.PERMISSION_NOTIFICATION;
-import static com.android.companiondevicemanager.PermissionListAdapter.PERMISSION_PHONE;
-import static com.android.companiondevicemanager.PermissionListAdapter.PERMISSION_SMS;
-import static com.android.companiondevicemanager.PermissionListAdapter.PERMISSION_STORAGE;
+import static android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
 
 import static java.util.Collections.unmodifiableMap;
 import static java.util.Collections.unmodifiableSet;
 
+import android.os.Build;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 
-import com.android.media.flags.Flags;
-
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
@@ -54,7 +41,85 @@
  * for the corresponding profile.
  */
 final class CompanionDeviceResources {
-    static final Map<String, Integer> TITLES;
+
+    // Permission resources
+    private static final int PERMISSION_NOTIFICATION_LISTENER_ACCESS = 0;
+    private static final int PERMISSION_STORAGE = 1;
+    private static final int PERMISSION_APP_STREAMING = 2;
+    private static final int PERMISSION_PHONE = 3;
+    private static final int PERMISSION_SMS = 4;
+    private static final int PERMISSION_CONTACTS = 5;
+    private static final int PERMISSION_CALENDAR = 6;
+    private static final int PERMISSION_NEARBY_DEVICES = 7;
+    private static final int PERMISSION_NEARBY_DEVICE_STREAMING = 8;
+    private static final int PERMISSION_MICROPHONE = 9;
+    private static final int PERMISSION_CALL_LOGS = 10;
+    // Notification Listener Access & POST_NOTIFICATION permission
+    private static final int PERMISSION_NOTIFICATIONS = 11;
+    private static final int PERMISSION_CHANGE_MEDIA_OUTPUT = 12;
+
+    static final Map<Integer, Integer> PERMISSION_TITLES;
+    static {
+        final Map<Integer, Integer> map = new ArrayMap<>();
+        map.put(PERMISSION_NOTIFICATION_LISTENER_ACCESS, R.string.permission_notifications);
+        map.put(PERMISSION_STORAGE, R.string.permission_storage);
+        map.put(PERMISSION_APP_STREAMING, R.string.permission_app_streaming);
+        map.put(PERMISSION_PHONE, R.string.permission_phone);
+        map.put(PERMISSION_SMS, R.string.permission_sms);
+        map.put(PERMISSION_CONTACTS, R.string.permission_contacts);
+        map.put(PERMISSION_CALENDAR, R.string.permission_calendar);
+        map.put(PERMISSION_NEARBY_DEVICES, R.string.permission_nearby_devices);
+        map.put(PERMISSION_NEARBY_DEVICE_STREAMING, R.string.permission_nearby_device_streaming);
+        map.put(PERMISSION_MICROPHONE, R.string.permission_microphone);
+        map.put(PERMISSION_CALL_LOGS, R.string.permission_call_logs);
+        map.put(PERMISSION_NOTIFICATIONS, R.string.permission_notifications);
+        map.put(PERMISSION_CHANGE_MEDIA_OUTPUT, R.string.permission_media_routing_control);
+        PERMISSION_TITLES = unmodifiableMap(map);
+    }
+
+    static final Map<Integer, Integer> PERMISSION_SUMMARIES;
+    static {
+        final Map<Integer, Integer> map = new ArrayMap<>();
+        map.put(PERMISSION_NOTIFICATION_LISTENER_ACCESS,
+                R.string.permission_notification_listener_access_summary);
+        map.put(PERMISSION_STORAGE, R.string.permission_storage_summary);
+        map.put(PERMISSION_APP_STREAMING, R.string.permission_app_streaming_summary);
+        map.put(PERMISSION_PHONE, R.string.permission_phone_summary);
+        map.put(PERMISSION_SMS, R.string.permission_sms_summary);
+        map.put(PERMISSION_CONTACTS, R.string.permission_contacts_summary);
+        map.put(PERMISSION_CALENDAR, R.string.permission_calendar_summary);
+        map.put(PERMISSION_NEARBY_DEVICES, R.string.permission_nearby_devices_summary);
+        map.put(PERMISSION_NEARBY_DEVICE_STREAMING,
+                R.string.permission_nearby_device_streaming_summary);
+        map.put(PERMISSION_MICROPHONE, R.string.permission_microphone_summary);
+        map.put(PERMISSION_CALL_LOGS, R.string.permission_call_logs_summary);
+        map.put(PERMISSION_NOTIFICATIONS, R.string.permission_notifications_summary);
+        map.put(PERMISSION_CHANGE_MEDIA_OUTPUT, R.string.permission_media_routing_control_summary);
+        PERMISSION_SUMMARIES = unmodifiableMap(map);
+    }
+
+    static final Map<Integer, Integer> PERMISSION_ICONS;
+    static {
+        final Map<Integer, Integer> map = new ArrayMap<>();
+        map.put(PERMISSION_NOTIFICATION_LISTENER_ACCESS, R.drawable.ic_permission_notifications);
+        map.put(PERMISSION_STORAGE, R.drawable.ic_permission_storage);
+        map.put(PERMISSION_APP_STREAMING, R.drawable.ic_permission_app_streaming);
+        map.put(PERMISSION_PHONE, R.drawable.ic_permission_phone);
+        map.put(PERMISSION_SMS, R.drawable.ic_permission_sms);
+        map.put(PERMISSION_CONTACTS, R.drawable.ic_permission_contacts);
+        map.put(PERMISSION_CALENDAR, R.drawable.ic_permission_calendar);
+        map.put(PERMISSION_NEARBY_DEVICES, R.drawable.ic_permission_nearby_devices);
+        map.put(PERMISSION_NEARBY_DEVICE_STREAMING,
+                R.drawable.ic_permission_nearby_device_streaming);
+        map.put(PERMISSION_MICROPHONE, R.drawable.ic_permission_microphone);
+        map.put(PERMISSION_CALL_LOGS, R.drawable.ic_permission_call_logs);
+        map.put(PERMISSION_NOTIFICATIONS, R.drawable.ic_permission_notifications);
+        map.put(PERMISSION_CHANGE_MEDIA_OUTPUT, R.drawable.ic_permission_media_routing_control);
+        PERMISSION_ICONS = unmodifiableMap(map);
+    }
+
+    // Profile resources
+    static final Map<String, Integer> PROFILE_TITLES;
     static {
         final Map<String, Integer> map = new ArrayMap<>();
         map.put(DEVICE_PROFILE_APP_STREAMING, R.string.title_app_streaming);
@@ -65,71 +130,61 @@
         map.put(DEVICE_PROFILE_GLASSES, R.string.confirmation_title_glasses);
         map.put(null, R.string.confirmation_title);
 
-        TITLES = unmodifiableMap(map);
+        PROFILE_TITLES = unmodifiableMap(map);
     }
 
-    static final Map<String, List<Integer>> PERMISSION_TYPES;
-    static {
-        final Map<String, List<Integer>> map = new ArrayMap<>();
-        map.put(DEVICE_PROFILE_APP_STREAMING, Arrays.asList(PERMISSION_APP_STREAMING));
-        map.put(DEVICE_PROFILE_COMPUTER, Arrays.asList(
-                PERMISSION_NOTIFICATION, PERMISSION_STORAGE));
-        map.put(DEVICE_PROFILE_NEARBY_DEVICE_STREAMING,
-                Arrays.asList(PERMISSION_NEARBY_DEVICE_STREAMING));
-        if (!Flags.enablePrivilegedRoutingForMediaRoutingControl()) {
-            map.put(DEVICE_PROFILE_WATCH, Arrays.asList(PERMISSION_NOTIFICATION, PERMISSION_PHONE,
-                    PERMISSION_CALL_LOGS, PERMISSION_SMS, PERMISSION_CONTACTS, PERMISSION_CALENDAR,
-                    PERMISSION_NEARBY_DEVICES));
-        } else {
-            map.put(DEVICE_PROFILE_WATCH, Arrays.asList(PERMISSION_NOTIFICATION, PERMISSION_PHONE,
-                    PERMISSION_CALL_LOGS, PERMISSION_SMS, PERMISSION_CONTACTS, PERMISSION_CALENDAR,
-                    PERMISSION_NEARBY_DEVICES, PERMISSION_CHANGE_MEDIA_OUTPUT));
-        }
-        map.put(DEVICE_PROFILE_GLASSES, Arrays.asList(PERMISSION_NOTIFICATION, PERMISSION_PHONE,
-                PERMISSION_SMS, PERMISSION_CONTACTS, PERMISSION_MICROPHONE,
-                PERMISSION_NEARBY_DEVICES));
-
-        PERMISSION_TYPES = unmodifiableMap(map);
-    }
-
-    static final Map<String, Integer> SUMMARIES;
+    static final Map<String, Integer> PROFILE_SUMMARIES;
     static {
         final Map<String, Integer> map = new ArrayMap<>();
         map.put(DEVICE_PROFILE_WATCH, R.string.summary_watch);
         map.put(DEVICE_PROFILE_GLASSES, R.string.summary_glasses);
         map.put(null, R.string.summary_generic);
 
-        SUMMARIES = unmodifiableMap(map);
+        PROFILE_SUMMARIES = unmodifiableMap(map);
     }
 
-    static final Map<String, Integer> PROFILES_NAME;
+    static final Map<String, List<Integer>> PROFILE_PERMISSIONS;
+    static {
+        final Map<String, List<Integer>> map = new ArrayMap<>();
+        map.put(DEVICE_PROFILE_APP_STREAMING, Arrays.asList(PERMISSION_APP_STREAMING));
+        map.put(DEVICE_PROFILE_COMPUTER, Arrays.asList(
+                PERMISSION_NOTIFICATION_LISTENER_ACCESS, PERMISSION_STORAGE));
+        map.put(DEVICE_PROFILE_NEARBY_DEVICE_STREAMING,
+                Arrays.asList(PERMISSION_NEARBY_DEVICE_STREAMING));
+        if (Build.VERSION.SDK_INT > UPSIDE_DOWN_CAKE) {
+            map.put(DEVICE_PROFILE_WATCH, Arrays.asList(PERMISSION_NOTIFICATIONS, PERMISSION_PHONE,
+                    PERMISSION_CALL_LOGS, PERMISSION_SMS, PERMISSION_CONTACTS, PERMISSION_CALENDAR,
+                    PERMISSION_NEARBY_DEVICES, PERMISSION_CHANGE_MEDIA_OUTPUT));
+        } else {
+            map.put(DEVICE_PROFILE_WATCH, Arrays.asList(PERMISSION_NOTIFICATION_LISTENER_ACCESS,
+                    PERMISSION_PHONE, PERMISSION_CALL_LOGS, PERMISSION_SMS, PERMISSION_CONTACTS,
+                    PERMISSION_CALENDAR, PERMISSION_NEARBY_DEVICES));
+        }
+        map.put(DEVICE_PROFILE_GLASSES, Arrays.asList(PERMISSION_NOTIFICATION_LISTENER_ACCESS,
+                PERMISSION_PHONE, PERMISSION_SMS, PERMISSION_CONTACTS, PERMISSION_MICROPHONE,
+                PERMISSION_NEARBY_DEVICES));
+
+        PROFILE_PERMISSIONS = unmodifiableMap(map);
+    }
+
+    static final Map<String, Integer> PROFILE_NAMES;
     static {
         final Map<String, Integer> map = new ArrayMap<>();
         map.put(DEVICE_PROFILE_WATCH, R.string.profile_name_watch);
         map.put(DEVICE_PROFILE_GLASSES, R.string.profile_name_glasses);
         map.put(null, R.string.profile_name_generic);
 
-        PROFILES_NAME = unmodifiableMap(map);
+        PROFILE_NAMES = unmodifiableMap(map);
     }
 
-    static final Map<String, Integer> PROFILES_NAME_MULTI;
-    static {
-        final Map<String, Integer> map = new ArrayMap<>();
-        map.put(DEVICE_PROFILE_GLASSES, R.string.profile_name_generic);
-        map.put(DEVICE_PROFILE_WATCH, R.string.profile_name_watch);
-        map.put(null, R.string.profile_name_generic);
-
-        PROFILES_NAME_MULTI = unmodifiableMap(map);
-    }
-
-    static final Map<String, Integer> PROFILE_ICON;
+    static final Map<String, Integer> PROFILE_ICONS;
     static {
         final Map<String, Integer> map = new ArrayMap<>();
         map.put(DEVICE_PROFILE_WATCH, R.drawable.ic_watch);
         map.put(DEVICE_PROFILE_GLASSES, R.drawable.ic_glasses);
         map.put(null, R.drawable.ic_device_other);
 
-        PROFILE_ICON = unmodifiableMap(map);
+        PROFILE_ICONS = unmodifiableMap(map);
     }
 
     static final Set<String> SUPPORTED_PROFILES;
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/PermissionListAdapter.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/PermissionListAdapter.java
index e21aee3..4a1f801 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/PermissionListAdapter.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/PermissionListAdapter.java
@@ -16,14 +16,14 @@
 
 package com.android.companiondevicemanager;
 
+import static com.android.companiondevicemanager.CompanionDeviceResources.PERMISSION_ICONS;
+import static com.android.companiondevicemanager.CompanionDeviceResources.PERMISSION_SUMMARIES;
+import static com.android.companiondevicemanager.CompanionDeviceResources.PERMISSION_TITLES;
 import static com.android.companiondevicemanager.Utils.getHtmlFromResources;
 import static com.android.companiondevicemanager.Utils.getIcon;
 
-import static java.util.Collections.unmodifiableMap;
-
 import android.content.Context;
 import android.text.Spanned;
-import android.util.ArrayMap;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -35,7 +35,6 @@
 import androidx.recyclerview.widget.RecyclerView;
 
 import java.util.List;
-import java.util.Map;
 
 class PermissionListAdapter extends RecyclerView.Adapter<PermissionListAdapter.ViewHolder> {
     private final Context mContext;
@@ -43,75 +42,6 @@
     // Add the expand buttons if permissions are more than PERMISSION_SIZE in the permission list.
     private static final int PERMISSION_SIZE = 2;
 
-    static final int PERMISSION_NOTIFICATION = 0;
-    static final int PERMISSION_STORAGE = 1;
-    static final int PERMISSION_APP_STREAMING = 2;
-    static final int PERMISSION_PHONE = 3;
-    static final int PERMISSION_SMS = 4;
-    static final int PERMISSION_CONTACTS = 5;
-    static final int PERMISSION_CALENDAR = 6;
-    static final int PERMISSION_NEARBY_DEVICES = 7;
-    static final int PERMISSION_NEARBY_DEVICE_STREAMING = 8;
-    static final int PERMISSION_MICROPHONE = 9;
-    static final int PERMISSION_CALL_LOGS = 10;
-    static final int PERMISSION_CHANGE_MEDIA_OUTPUT = 11;
-
-    private static final Map<Integer, Integer> sTitleMap;
-    static {
-        final Map<Integer, Integer> map = new ArrayMap<>();
-        map.put(PERMISSION_NOTIFICATION, R.string.permission_notification);
-        map.put(PERMISSION_STORAGE, R.string.permission_storage);
-        map.put(PERMISSION_APP_STREAMING, R.string.permission_app_streaming);
-        map.put(PERMISSION_PHONE, R.string.permission_phone);
-        map.put(PERMISSION_SMS, R.string.permission_sms);
-        map.put(PERMISSION_CONTACTS, R.string.permission_contacts);
-        map.put(PERMISSION_CALENDAR, R.string.permission_calendar);
-        map.put(PERMISSION_NEARBY_DEVICES, R.string.permission_nearby_devices);
-        map.put(PERMISSION_NEARBY_DEVICE_STREAMING, R.string.permission_nearby_device_streaming);
-        map.put(PERMISSION_MICROPHONE, R.string.permission_microphone);
-        map.put(PERMISSION_CALL_LOGS, R.string.permission_call_logs);
-        map.put(PERMISSION_CHANGE_MEDIA_OUTPUT, R.string.permission_media_routing_control);
-        sTitleMap = unmodifiableMap(map);
-    }
-
-    private static final Map<Integer, Integer> sSummaryMap;
-    static {
-        final Map<Integer, Integer> map = new ArrayMap<>();
-        map.put(PERMISSION_NOTIFICATION, R.string.permission_notification_summary);
-        map.put(PERMISSION_STORAGE, R.string.permission_storage_summary);
-        map.put(PERMISSION_APP_STREAMING, R.string.permission_app_streaming_summary);
-        map.put(PERMISSION_PHONE, R.string.permission_phone_summary);
-        map.put(PERMISSION_SMS, R.string.permission_sms_summary);
-        map.put(PERMISSION_CONTACTS, R.string.permission_contacts_summary);
-        map.put(PERMISSION_CALENDAR, R.string.permission_calendar_summary);
-        map.put(PERMISSION_NEARBY_DEVICES, R.string.permission_nearby_devices_summary);
-        map.put(PERMISSION_NEARBY_DEVICE_STREAMING,
-                R.string.permission_nearby_device_streaming_summary);
-        map.put(PERMISSION_MICROPHONE, R.string.permission_microphone_summary);
-        map.put(PERMISSION_CALL_LOGS, R.string.permission_call_logs_summary);
-        map.put(PERMISSION_CHANGE_MEDIA_OUTPUT, R.string.permission_media_routing_control_summary);
-        sSummaryMap = unmodifiableMap(map);
-    }
-
-    private static final Map<Integer, Integer> sIconMap;
-    static {
-        final Map<Integer, Integer> map = new ArrayMap<>();
-        map.put(PERMISSION_NOTIFICATION, R.drawable.ic_permission_notifications);
-        map.put(PERMISSION_STORAGE, R.drawable.ic_permission_storage);
-        map.put(PERMISSION_APP_STREAMING, R.drawable.ic_permission_app_streaming);
-        map.put(PERMISSION_PHONE, R.drawable.ic_permission_phone);
-        map.put(PERMISSION_SMS, R.drawable.ic_permission_sms);
-        map.put(PERMISSION_CONTACTS, R.drawable.ic_permission_contacts);
-        map.put(PERMISSION_CALENDAR, R.drawable.ic_permission_calendar);
-        map.put(PERMISSION_NEARBY_DEVICES, R.drawable.ic_permission_nearby_devices);
-        map.put(PERMISSION_NEARBY_DEVICE_STREAMING,
-                R.drawable.ic_permission_nearby_device_streaming);
-        map.put(PERMISSION_MICROPHONE, R.drawable.ic_permission_microphone);
-        map.put(PERMISSION_CALL_LOGS, R.drawable.ic_permission_call_logs);
-        map.put(PERMISSION_CHANGE_MEDIA_OUTPUT, R.drawable.ic_permission_media_routing_control);
-        sIconMap = unmodifiableMap(map);
-    }
-
     PermissionListAdapter(Context context) {
         mContext = context;
     }
@@ -121,7 +51,8 @@
         View view = LayoutInflater.from(parent.getContext()).inflate(
                 R.layout.list_item_permission, parent, false);
         ViewHolder viewHolder = new ViewHolder(view);
-        viewHolder.mPermissionIcon.setImageDrawable(getIcon(mContext, sIconMap.get(viewType)));
+        viewHolder.mPermissionIcon.setImageDrawable(
+                getIcon(mContext, PERMISSION_ICONS.get(viewType)));
 
         if (viewHolder.mExpandButton.getTag() == null) {
             viewHolder.mExpandButton.setTag(R.drawable.btn_expand_more);
@@ -165,8 +96,8 @@
     @Override
     public void onBindViewHolder(ViewHolder holder, int position) {
         int type = getItemViewType(position);
-        final Spanned title = getHtmlFromResources(mContext, sTitleMap.get(type));
-        final Spanned summary = getHtmlFromResources(mContext, sSummaryMap.get(type));
+        final Spanned title = getHtmlFromResources(mContext, PERMISSION_TITLES.get(type));
+        final Spanned summary = getHtmlFromResources(mContext, PERMISSION_SUMMARIES.get(type));
 
         holder.mPermissionSummary.setText(summary);
         holder.mPermissionName.setText(title);
@@ -192,6 +123,7 @@
         private final TextView mPermissionSummary;
         private final ImageView mPermissionIcon;
         private final ImageButton mExpandButton;
+
         ViewHolder(View itemView) {
             super(itemView);
             mPermissionName = itemView.findViewById(R.id.permission_name);
@@ -203,7 +135,7 @@
 
     private void setAccessibility(View view, int viewType, int action, int statusResourceId,
             int actionResourceId) {
-        final String permission = mContext.getString(sTitleMap.get(viewType));
+        final String permission = mContext.getString(PERMISSION_TITLES.get(viewType));
 
         if (actionResourceId != 0) {
             view.announceForAccessibility(
diff --git a/packages/CredentialManager/res/values-el/strings.xml b/packages/CredentialManager/res/values-el/strings.xml
index 8d06765..089f898 100644
--- a/packages/CredentialManager/res/values-el/strings.xml
+++ b/packages/CredentialManager/res/values-el/strings.xml
@@ -33,7 +33,7 @@
     <string name="passwordless_technology_detail" msgid="6853928846532955882">"Τα κλειδιά πρόσβασης σάς επιτρέπουν να συνδέεστε χωρίς να εξαρτάστε από κωδικούς πρόσβασης. Χρειάζεται μόνο να χρησιμοποιήσετε το δακτυλικό αποτύπωμά σας, την αναγνώριση προσώπου, ένα PIN ή ένα μοτίβο σάρωσης για να επαληθεύσετε την ταυτότητά σας και να δημιουργήσετε ένα κλειδί πρόσβασης."</string>
     <string name="public_key_cryptography_title" msgid="6751970819265298039">"Κρυπτογραφία δημόσιου κλειδιού"</string>
     <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Βάσει του FIDO Alliance (συμμετ. οι Google, Apple, Microsoft κ.ά.) και προτύπων W3C, τα κλειδιά πρόσβ. χρησιμ. συζεύξεις κλειδιών κρυπτογρ. Σε αντίθεση με το όνομα χρήστη και τη συμβολοσειρά χαρακτ. για κωδ. πρόσβ., δημιουργείται μια σύζευξη ιδιωτικού-δημόσιου κλειδ. για εφαρμ./ιστοτόπους. Το ιδιωτ. κλειδί αποθηκεύεται με ασφάλεια στη συσκευή ή στον διαχειρ. κωδ. πρόσβ. και επιβεβαιώνει την ταυτότητά σας. Το δημόσιο κλειδί κοινοπ. στον διακομιστή εφαρμ./ιστοτόπου. Τα αντίστοιχα κλειδιά επιτρέπουν άμεση εγγραφή και σύνδεση."</string>
-    <string name="improved_account_security_title" msgid="1069841917893513424">"Βελτιωμένη ασφάλεια λογαριασμού"</string>
+    <string name="improved_account_security_title" msgid="1069841917893513424">"Βελτιωμένη προστασία λογαριασμού"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Κάθε κλειδί συνδέεται αποκλειστικά με την εφαρμογή ή τον ιστότοπο για τον οποίο δημιουργήθηκε ώστε να μην συνδέεστε ποτέ κατά λάθος σε μη νόμιμες εφαρμογές ή ιστοτόπους. Επιπλέον, οι παραβιάσεις είναι πολύ πιο δύσκολες, επειδή οι διακομιστές διατηρούν μόνο δημόσια κλειδιά."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Απρόσκοπτη μετάβαση"</string>
     <string name="seamless_transition_detail" msgid="4475509237171739843">"Καθώς κινούμαστε προς ένα μέλλον χωρίς κωδικούς πρόσβασης, οι κωδικοί πρόσβασης θα εξακολουθούν να είναι διαθέσιμοι μαζί με τα κλειδιά πρόσβασης."</string>
diff --git a/packages/InputDevices/res/values-nb/strings.xml b/packages/InputDevices/res/values-nb/strings.xml
index 60cac3d..40eb25a 100644
--- a/packages/InputDevices/res/values-nb/strings.xml
+++ b/packages/InputDevices/res/values-nb/strings.xml
@@ -47,7 +47,7 @@
     <string name="keyboard_layout_persian" msgid="3920643161015888527">"Persisk"</string>
     <string name="keyboard_layout_azerbaijani" msgid="7315895417176467567">"Aserbajdsjansk"</string>
     <string name="keyboard_layout_polish" msgid="1121588624094925325">"Polsk"</string>
-    <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Hviterussisk"</string>
+    <string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Belarusisk"</string>
     <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongolsk"</string>
     <string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgisk"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-af/strings.xml b/packages/PackageInstaller/res/values-af/strings.xml
index a3496ca..25afe99 100644
--- a/packages/PackageInstaller/res/values-af/strings.xml
+++ b/packages/PackageInstaller/res/values-af/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Hierdie gebruiker kan nie onbekende programme installeer nie"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Hierdie gebruiker word nie toegelaat om programme te installeer nie"</string>
     <string name="ok" msgid="7871959885003339302">"OK"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Dateer in elk geval op"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Bestuur programme"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Geen spasie oor nie"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Deïnstalleer opdatering"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> is deel van die volgende program:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Wil jy hierdie program deïnstalleer?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Wil jy hierdie program vir "<b>"alle"</b>" gebruikers deïnstalleer? Die program en sy data sal van "<b>"alle"</b>" gebruikers op hierdie toestel verwyder word."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Wil jy hierdie program vir die gebruiker <xliff:g id="USERNAME">%1$s</xliff:g> deïnstalleer?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Wil jy hierdie program op jou werkprofiel deïnstalleer?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Hou <xliff:g id="SIZE">%1$s</xliff:g> se programdata."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Wil jy hierdie app uitvee?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Wil jy hierdie app deïnstalleer? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-kloon sal ook uitgevee word."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Wil jy hierdie app van jou private ruimte deïnstalleer?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Voer tans deïnstallerings uit"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Mislukte deïnstallerings"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Deïnstalleer tans …"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Bestuur gebruikers"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> kon nie gedeïnstalleer word nie."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Kon nie die pakket ontleed nie."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Installeer- en deïnstalleerhandelinge word nie in Wear gesteun nie."</string>
     <string name="message_staging" msgid="8032722385658438567">"Voer tans program uit …"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Onbekend"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Jou tablet word vir jou veiligheid tans nie toegelaat om onbekende programme van hierdie bron af te installeer nie. Jy kan dit in Instellings verander."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Jou tablet en persoonlike data is meer kwesbaar vir aanvalle deur onbekende programme. Deur hierdie program te installeer, stem jy in dat jy verantwoordelik is vir enige skade aan jou tablet of verlies van data wat uit sy gebruik kan spruit."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Jou TV en persoonlike data is meer kwesbaar vir aanvalle deur onbekende programme. Deur hierdie program te installeer, stem jy in dat jy verantwoordelik is vir enige skade aan jou TV of verlies van data wat uit sy gebruik kan spruit."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-kloon"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Gaan voort"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Instellings"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Installeer/deïnstalleer Wear-programme"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Stel <xliff:g id="APPNAME">%1$s</xliff:g> terug vanaf <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Hierdie app sal in die agtergrond begin aflaai"</string>
     <string name="restore" msgid="8460854736328970444">"Stel terug"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Jy is vanlyn"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Hierdie app sal outomaties teruggestel word wanneer jy aan die internet gekoppel is"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Iets het skeefgeloop"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Kon nie hierdie app terugstel nie"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Te min berging"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Jy kan spasie op hierdie toestel beskikbaar maak om hierdie app terug te stel. Berging benodig: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Optrede vereis"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Volg die volgende stappe om hierdie app terug te stel"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> is gedeaktiveer"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Aktiveer <xliff:g id="INSTALLERNAME">%1$s</xliff:g> in Instellings om hierdie app terug te stel"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> is gedeïnstalleer"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Jy sal <xliff:g id="INSTALLERNAME">%1$s</xliff:g> moet installeer om hierdie app terug te stel"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Gaan voort"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Vee berging uit"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Instellings"</string>
+    <string name="close" msgid="5214897374055647996">"Maak toe"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-am/strings.xml b/packages/PackageInstaller/res/values-am/strings.xml
index 9d0fd53..f47ec6a 100644
--- a/packages/PackageInstaller/res/values-am/strings.xml
+++ b/packages/PackageInstaller/res/values-am/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"ያልታወቁ መተግበሪያዎች በዚህ ተጠቃሚ ሊጫኑ አይችሉም"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"ይህ ተጠቃሚ መተግበሪያዎችን እንዲጭን አልተፈቀደለትም"</string>
     <string name="ok" msgid="7871959885003339302">"እሺ"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"የሆነው ሆኖ አዘምን"</string>
     <string name="manage_applications" msgid="5400164782453975580">"መተግበሪያዎችን ያቀናብሩ"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"ቦታ ሞልቷል"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"ዝማኔን አራግፍ"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> የሚከተለው መተግበሪያ አካል ነው፦"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"ይህን መተግበሪያ ማራገፍ ይፈልጋሉ?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"ይህን መተግበሪያ "<b>"ለሁሉም"</b>" ተጠቃሚዎች መጫን ይፈልጋሉ? መተግበሪያው እና ውሂቡ በመሣሪያው ላይ ካሉ "<b>"ሁሉም"</b>" ተጠቃሚዎች ይሰረዛሉ።"</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"ይህን መተግበሪያ ለተጠቃሚ <xliff:g id="USERNAME">%1$s</xliff:g> ማራገፍ ይፈልጋሉ?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"ይህን መተግበሪያ ከስራ መገለጫዎ ማራገፍ ይፈልጋሉ?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"ከመተግበሪያ ውሂብ <xliff:g id="SIZE">%1$s</xliff:g> አቆይ።"</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"ይህን መተግበሪያ መሰረዝ ይፈልጋሉ?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"ይህን መተግበሪያ ማራገፍ ይፈልጋሉ? የተባዛውም <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ይሰረዛል።"</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"ይህን መተግበሪያ ከግል ቦታዎ ማራገፍ ይፈልጋሉ?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"በማሄድ ላይ ያሉ ማራገፎች"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"ያልተሳኩ ማራገፎች"</string>
     <string name="uninstalling" msgid="8709566347688966845">"በማራገፍ ላይ…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"ተጠቃሚዎችን ያስተዳድሩ"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> ሊራገፍ አልቻልም።"</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"ጥቅሉን መተንተን ላይ ችግር ነበረ።"</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"በWear ላይ የመጫን/ማራገፍ እርምጃዎች አይደገፉም።"</string>
     <string name="message_staging" msgid="8032722385658438567">"መተግበሪያን በማዘጋጀት ላይ…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"ያልታወቀ"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"ለእርስዎ ደህንነት ሲባል በአሁኑ ጊዜ ጡባዊዎ ከዚህ ምንጭ ያልታወቁ መተግበሪያዎችን እንዲጭን አይፈቀድለትም። ይህን በቅንብሮች ውስጥ መቀየር ይችላሉ።"</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"የእርስዎ ጡባዊ እና የግል ውሂብ በማይታወቁ መተግበሪያዎች ለሚደርሱ ጥቃቶች በይበልጥ ተጋላጭ ናቸው። ይህን መተግበሪያ በመጫንዎ በእርስዎ ጡባዊ ላይ ለሚደርስ ማናቸውም ጉዳት ወይም መተግበሪያውን በመጠቀም ለሚከሰት የውሂብ መጥፋት ኃላፊነቱን እንደሚወስዱ ተስማምተዋል።"</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"የእርስዎ ቴሌቪዥን እና የግል ውሂብ በማይታወቁ መተግበሪያዎች ለሚደርሱ ጥቃቶች በይበልጥ ተጋላጭ ናቸው። ይህን መተግበሪያ በመጫንዎ በእርስዎ ቴሌቪዥን ላይ ለሚደርስ ማናቸውም ጉዳት ወይም መተግበሪያውን በመጠቀም ለሚከሰት የውሂብ መጥፋት ኃላፊነቱን እንደሚወስዱ ተስማምተዋል።"</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"የተባዛ <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"ቀጥል"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"ቅንብሮች"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"የWear መተግበሪያዎችን መጫን/ማራገፍ"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"ከ <xliff:g id="INSTALLERNAME">%1$s</xliff:g> ወደነበረበት <xliff:g id="APPNAME">%1$s</xliff:g> መልስ?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"ይህ መተግበሪያ በዳራ ማውረድ ይጀምራል።"</string>
     <string name="restore" msgid="8460854736328970444">"ወደነበረበት መልስ"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"ከመስመር ውጭ ነዎት"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"እርስዎ ከበይነመረቡ ጋር ሲገናኙ ይህ መተግበሪያ በራስ-ሰር ወደነበረበት ይመለሳል"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"የሆነ ስህተት ተከስቷል"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"ይህን መተግበሪያ ወደነበረበት ለመመለስ እየተሞከረ ሳለ አንድ ችግር ነበር"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"በቂ ማከማቻ የለም"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"ይህን መተግበሪያ ወደነበረበት ለመመለስ፣ በዚህ መሳሪያ ላይ ቦታን ማስለቀቅ ይችላሉ። ማከማቻ ያስፈልጋል፦ <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"የሚያስፈልግ እርምጃ"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"ይህን መተግበሪያ ወደነበረበት ለመመለስ ቀጣዮቹን ደረጃዎች ይከተሉ"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> ተሰናክሏል"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"ይህን መተግበሪያ ወደነበረበት ለመመለስ፣ <xliff:g id="INSTALLERNAME">%1$s</xliff:g>ን በቅንብሮች ውስጥ ያንቁ"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> ተራግፏል"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"ይህን መተግበሪያ ወደነበረበት ለመመለስ፣ <xliff:g id="INSTALLERNAME">%1$s</xliff:g>ን መጫን አለብዎት"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"ቀጥል"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"ማከማቻን አጽዳ"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"ቅንብሮች"</string>
+    <string name="close" msgid="5214897374055647996">"ዝጋ"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-ar/strings.xml b/packages/PackageInstaller/res/values-ar/strings.xml
index f4c9581..e4da5b7 100644
--- a/packages/PackageInstaller/res/values-ar/strings.xml
+++ b/packages/PackageInstaller/res/values-ar/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"يتعذر على هذا المستخدم تثبيت التطبيقات غير المعروفة"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"غير مسموح لهذا المستخدم بتثبيت التطبيقات"</string>
     <string name="ok" msgid="7871959885003339302">"حسنًا"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"التحديث على أي حال"</string>
     <string name="manage_applications" msgid="5400164782453975580">"إدارة التطبيقات"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"نفدت مساحة التخزين"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"إزالة التحديث"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> هو جزء من التطبيق التالي:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"هل تريد إزالة هذا التطبيق؟"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"هل تريد إزالة هذا التطبيق "<b>"لكل"</b>" المستخدمين؟ ستتم إزالة التطبيق وبياناته من "<b>"كل"</b>" المستخدمين على هذا الجهاز."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"هل تريد إزالة هذا التطبيق للمستخدم <xliff:g id="USERNAME">%1$s</xliff:g>؟"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"هل تريد إزالة تثبيت هذا التطبيق من ملفك الشخصي للعمل؟"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"الاحتفاظ بـ <xliff:g id="SIZE">%1$s</xliff:g> من بيانات التطبيق."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"هل تريد حذف هذا التطبيق؟"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"هل تريد إلغاء تثبيت هذا التطبيق؟ سيتم أيضًا حذف نسخة \"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>\" الطبق الأصل."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"هل تريد إلغاء تثبيت هذا التطبيق من المساحة الخاصة؟"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"عمليات إلغاء التثبيت الجارية"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"عمليات إلغاء التثبيت غير الناجحة"</string>
     <string name="uninstalling" msgid="8709566347688966845">"جارٍ إلغاء التثبيت…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"إدارة حسابات المستخدمين"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"تعذرت إزالة <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"حدثت مشكلة أثناء تحليل الحزمة."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"‏لا تتوافق إجراءات التثبيت/إلغاء التثبيت مع نظام Android Wear."</string>
     <string name="message_staging" msgid="8032722385658438567">"جارٍ الطرح المرحلي للتطبيق…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"غير معروف"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"لأغراض الأمان، غير مسموح حاليًا لجهازك اللوحي بتثبيت تطبيقات غير معروفة من هذا المصدر. ويمكنك تغيير ذلك في \"الإعدادات\"."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"يعتبر الجهاز اللوحي والبيانات الشخصية أكثر عرضة لهجوم التطبيقات غير المعروفة. من خلال تثبيت هذا التطبيق، توافق على تحمل مسؤولية أي ضرر يحدث للجهاز اللوحي أو فقدان البيانات الذي قد ينتج عن استخدامه."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"يعتبر جهاز التلفزيون والبيانات الشخصية أكثر عرضة لهجوم التطبيقات غير المعروفة. من خلال تثبيت هذا التطبيق، توافق على تحمل مسؤولية أي ضرر يحدث لجهاز التلفزيون أو فقدان البيانات الذي قد ينتج عن استخدامه."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"نسخة طبق الأصل من \"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>\""</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"متابعة"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"الإعدادات"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"‏تثبيت / إلغاء تثبيت تطبيقات Android Wear"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"هل تريد استعادة التطبيق \"<xliff:g id="APPNAME">%1$s</xliff:g>\" من \"<xliff:g id="INSTALLERNAME">%1$s</xliff:g>\"؟"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"سيبدأ تنزيل هذا التطبيق في الخلفية."</string>
     <string name="restore" msgid="8460854736328970444">"استعادة"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"لا يتوفر اتصال بالإنترنت"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"ستتم استعادة هذا التطبيق تلقائيًا بمجرد اتصالك بالإنترنت."</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"حدث خطأ"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"حدثت مشكلة أثناء محاولة استعادة هذا التطبيق."</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"مساحة التخزين غير كافية"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"لاستعادة هذا التطبيق، يجب إخلاء بعض المساحة على هذا الجهاز. مساحة التخزين المطلوبة: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"مطلوب اتخاذ إجراء"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"يُرجى اتّباع الخطوات التالية لاستعادة هذا التطبيق."</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"‫<xliff:g id="INSTALLERNAME">%1$s</xliff:g> غير مفعّل"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"لاستعادة هذا التطبيق، يجب تفعيل \"<xliff:g id="INSTALLERNAME">%1$s</xliff:g>\" في \"الإعدادات\"."</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"‫<xliff:g id="INSTALLERNAME">%1$s</xliff:g> غير مثبَّت"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"لاستعادة هذا التطبيق، يجب تثبيت <xliff:g id="INSTALLERNAME">%1$s</xliff:g>."</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"متابعة"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"محو مساحة التخزين"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"الإعدادات"</string>
+    <string name="close" msgid="5214897374055647996">"إغلاق"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-as/strings.xml b/packages/PackageInstaller/res/values-as/strings.xml
index 4d264c6..62a55dc 100644
--- a/packages/PackageInstaller/res/values-as/strings.xml
+++ b/packages/PackageInstaller/res/values-as/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"এই ব্যৱহাৰকাৰীয়ে অজ্ঞাত উৎসৰপৰা পোৱা এপ্‌সমূহ ইনষ্টল কৰিব নোৱাৰে"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"এই ব্যৱহাৰকাৰীজনৰ এপ্ ইনষ্টল কৰাৰ অনুমতি নাই"</string>
     <string name="ok" msgid="7871959885003339302">"ঠিক আছে"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"যিকোনো প্ৰকাৰে আপডে’ট কৰক"</string>
     <string name="manage_applications" msgid="5400164782453975580">"এপ্ পৰিচালনা"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"খালী ঠাই নাই"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"আপডে’ট আনইনষ্টল কৰক"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> হৈছে তলৰ এপ্‌টোৰ এটা অংশ:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"আপুনি এই এপ্‌টো আনইনষ্টল কৰিব বিচাৰে নেকি?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"আপুনি "<b>"সকলো"</b>" ব্যৱহাৰকাৰীৰ বাবে এই এপ্‌টো আনইনষ্টল কৰিব বিচাৰেনে? এপ্লিকেশ্বন আৰু ইয়াৰ ডেটা ডিভাইচটোত থকা "<b>"সকলো"</b>" ব্যৱহাৰকাৰীৰ পৰা আঁতৰোৱা হ\'ব৷"</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"আপুনি ব্যৱহাৰকাৰীৰ <xliff:g id="USERNAME">%1$s</xliff:g> বাবে এই এপ্‌টো আনইনষ্টল কৰিব বিচাৰেনে?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"আপুনি নিজৰ কৰ্মস্থানৰ প্ৰ’ফাইলৰ পৰা এই এপ্‌টো আনইনষ্টল কৰিব বিচাৰেনে?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"এপৰ ডেটাৰ <xliff:g id="SIZE">%1$s</xliff:g> ৰাখক"</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"আপুনি এই এপ্‌টো মচিব বিচাৰেনে?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"আপুনি এই এপ্‌টো আনইনষ্টল কৰিব বিচাৰেনে? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>ৰ ক্ল’নো মচা হ’ব।"</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"আপুনি আপোনাৰ ব্যক্তিগত স্পেচৰ পৰা এই এপ্‌টো আনইনষ্টল কৰিব বিচাৰেনে?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"আনইনষ্টল কৰি থকা হৈছে"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"যিবোৰ আনইনষ্টল পৰা নগ\'ল"</string>
     <string name="uninstalling" msgid="8709566347688966845">"আনইনষ্টল কৰি থকা হৈছে…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"ব্যৱহাৰকাৰী পৰিচালনা কৰক"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> আনইনষ্টল কৰিব নোৱাৰি।"</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"পেকেজটো পাৰ্ছ কৰোঁতে এটা সমস্যাই দেখা দিছিল।"</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android ৱেৰ"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"ৱেৰ-ত ইনষ্টল/আনইনষ্টল কৰিব পৰা নাযায়।"</string>
     <string name="message_staging" msgid="8032722385658438567">"এপৰ অন্তিম পর্যায়ৰ পৰীক্ষণ চলি আছে…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"অজ্ঞাত"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"আপোনাৰ সুৰক্ষাৰ বাবে আপোনাৰ টেবলেটটোক বৰ্তমান এই উৎসটোৰ পৰা অজ্ঞাত এপ্‌ ইনষ্টল কৰাৰ অনুমতি দিয়া হোৱা নাই। আপুনি এইটো ছেটিঙত সলনি কৰিব পাৰে।"</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"আপোনাৰ টেবলেট আৰু ব্যক্তিগত ডেটা অজ্ঞাত এপৰ আক্ৰমণৰ বলি হোৱাৰ সম্ভাৱনা অধিক। আপুনি এই এপ্‌টো ইনষ্টল কৰি এপ্‌টোৰ ব্যৱহাৰৰ ফলত আপোনাৰ টিভিত হ\'ব পৰা যিকোনো ক্ষতি বা ডেটা ক্ষয়ৰ বাবে আপুনি নিজে দায়ী হ\'ব বুলি সন্মতি দিয়ে।"</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"আপোনাৰ টিভি আৰু ব্যক্তিগত ডেটা অজ্ঞাত এপৰ আক্ৰমণৰ বলি হোৱাৰ সম্ভাৱনা অধিক। আপুনি এই এপ্‌টো ইনষ্টল কৰি এপ্‌টোৰ ব্যৱহাৰৰ ফলত আপোনাৰ টিভিত হ\'ব পৰা যিকোনো ক্ষতি বা ডেটা ক্ষয়ৰ বাবে আপুনি নিজে দায়ী হ\'ব বুলি সন্মতি দিয়ে।"</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>ৰ ক্ল’ন"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"অব্যাহত ৰাখক"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"ছেটিং"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"ৱেৰ এপ্‌সমূহ ইনষ্টল/আনইনষ্টল কৰি থকা হৈছে"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g>ৰ পৰা <xliff:g id="APPNAME">%1$s</xliff:g> পুনঃস্থাপন কৰিবনে?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"এই এপ্‌টোৱে নেপথ্যত ডাউনল’ড কৰিবলৈ আৰম্ভ কৰিব"</string>
     <string name="restore" msgid="8460854736328970444">"পুনঃস্থাপন কৰক"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"আপুনি অফলাইন হৈ আছে"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"আপুনি ইণ্টাৰনেটৰ সৈতে সংযুক্ত হ’লে এই এপ্‌টো স্বয়ংক্ৰিয়ভাৱে পুনঃস্থাপন কৰা হ’ব"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"কিবা ভুল হ’ল"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"এই এপ্‌টো পুনঃস্থাপন কৰাত কিবা অসুবিধা হৈছিল"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"ষ্ট’ৰেজত পৰ্যাপ্ত ঠাই নাই"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"এই এপ্‌টো পুনঃস্থাপন কৰিবলৈ, আপুনি এই ডিভাইচটোত ঠাই খালী কৰিব পাৰে। আৱশ্যকীয় ষ্ট’ৰেজ: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"কাৰ্যব্যৱস্থা লোৱাৰ প্ৰয়োজন"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"এই এপ্‌টো পুনঃস্থাপন কৰিবলৈ পৰৱৰ্তী পদক্ষেপসমূহ অনুসৰণ কৰক"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> অক্ষম কৰা আছে"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"এই এপ্‌টো পুনঃস্থাপন কৰিবলৈ, ছেটিঙত <xliff:g id="INSTALLERNAME">%1$s</xliff:g> সক্ষম কৰক"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> আনইনষ্টল কৰা হৈছে"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"এই এপ্‌টো পুনঃস্থাপন কৰিবলৈ, আপুনি <xliff:g id="INSTALLERNAME">%1$s</xliff:g> ইনষ্টল কৰিব লাগিব"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"অব্যাহত ৰাখক"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"ষ্ট’ৰেজ মচক"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"ছেটিং"</string>
+    <string name="close" msgid="5214897374055647996">"বন্ধ কৰক"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-az/strings.xml b/packages/PackageInstaller/res/values-az/strings.xml
index 0807ef7..f5e3974 100644
--- a/packages/PackageInstaller/res/values-az/strings.xml
+++ b/packages/PackageInstaller/res/values-az/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Naməlum tətbiqlər bu istifadəçi tərəfindən quraşdırıla bilməz"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Bu istifadəçinin tətbiqi quraşdırmaq üçün icazəsi yoxdur"</string>
     <string name="ok" msgid="7871959885003339302">"OK"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"İstənilən halda güncəlləyin"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Tətbiqi idarə edin"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Boş yer yoxdur"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Güncəlləməni silin"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> bu tətbiqin hissəsidir:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Bu tətbiqi sistemdən silmək istəyirsiniz?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Bu tətbiqi "<b>"bütün"</b>" istifadəçilər üçün silmək istəyirsiz? Tətbiq və onun datası cihazdakı "<b>"bütün"</b>" istifadəçilər üçün silinəcək."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"<xliff:g id="USERNAME">%1$s</xliff:g> adlı istifadəçi üçün bu tətbiqi sistemdən silmək istəyirsiniz?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Bu tətbiqi iş profilinizdən silmək istəyirsiniz?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Tətbiq datasının <xliff:g id="SIZE">%1$s</xliff:g> hissəsini saxlayın."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Bu tətbiq silinsin?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Bu tətbiqi sistemdən silmək istəyirsiniz? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> kopya da silinəcək."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Bu tətbiqi şəxsi məkandan silmək istəyirsiniz?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"İşləyən sistemlər silinmələr"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Uğursuz olan sistemlər silinmələr"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Sistemdən silinir..."</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"İstifadəçiləri idarə edin"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> sistemdən silinə bilməz."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Paketin təhlilində problem var idi."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Yükləmə/Sistemdən silmə fəaliyyətləri Wear\'də dəstəklənmir."</string>
     <string name="message_staging" msgid="8032722385658438567">"Tətbiq hazırlanır..."</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Naməlum"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Təhlükəsizliyiniz üçün planşetinizə bu mənbədən olan naməlum tətbiqləri quraşdırmağa icazə verilmir. Bunu Ayarlarda dəyişə bilərsiniz."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Planşet və şəxsi data naməlum tətbiqlərin hücumuna qarşı daha həssasdır. Bu tətbiqi quraşdırmaqla planşetə dəyə biləcək zərər və ya onun istifadəsi nəticəsində baş verə biləcək data itkisinə görə məsuliyyət daşıdığınızı qəbul edirsiniz."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Tv və şəxsi data naməlum tətbiqlərin hücumuna qarşı daha həssasdır. Bu tətbiqi quraşdırmaqla Tv-yə dəyə biləcək zərər və ya onun istifadəsi nəticəsində baş verən data itkisinə görə məsuliyyət daşıdığınızı qəbul edirsiniz."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> Kopyalayın"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Davam edin"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Ayarlar"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Wear tətbiqləri quraşdırılır/sistemdən silinir"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="INSTALLERNAME">%1$s</xliff:g> ünvanından bərpa edilsin?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Bu tətbiq arxa fonda endirilməyə başlayacaq"</string>
     <string name="restore" msgid="8460854736328970444">"Bərpa edin"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Oflaynsınız"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"İnternetə qoşulanda bu tətbiq avtomatik bərpa ediləcək"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Xəta oldu"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Bu tətbiqi bərpa edərkən problem oldu"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Kifayət qədər yaddaş yoxdur"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Bu tətbiqi bərpa etmək üçün bu cihazda yer boşalda bilərsiniz. Lazımi yaddaş: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Tədbir görmək tələb edilir"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Bu tətbiqi bərpa etmək üçün növbəti addımları izləyin"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> deaktiv edilib"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Bu tətbiqi bərpa etmək üçün Ayarlarda <xliff:g id="INSTALLERNAME">%1$s</xliff:g> aktivləşdirilməlidir"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> sistemdən silinib"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Bu tətbiqi bərpa etmək üçün <xliff:g id="INSTALLERNAME">%1$s</xliff:g> quraşdırılmalıdır"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Davam edin"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Yaddaşı təmizləyin"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Ayarlar"</string>
+    <string name="close" msgid="5214897374055647996">"Bağlayın"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-b+sr+Latn/strings.xml b/packages/PackageInstaller/res/values-b+sr+Latn/strings.xml
index 6b9cd04..111d90b 100644
--- a/packages/PackageInstaller/res/values-b+sr+Latn/strings.xml
+++ b/packages/PackageInstaller/res/values-b+sr+Latn/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Ovaj korisnik ne može da instalira nepoznate aplikacije"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Ovom korisniku nije dozvoljeno da instalira aplikacije"</string>
     <string name="ok" msgid="7871959885003339302">"Potvrdi"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Ipak ažuriraj"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Upravljajte apl."</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Nema više prostora"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Deinstaliraj ažuriranje"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> je deo sledeće aplikacije:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Želite da deinstalirate ovu aplikaciju?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Da li želite da deinstalirate ovu aplikaciju za "<b>"sve"</b>" korisnike? Aplikacija i podaci uz nje biće uklonjeni za "<b>"sve"</b>" korisnike ovog uređaja."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Želite li da deinstalirate ovu aplikaciju za korisnika <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Da li želite da deinstalirate ovu aplikaciju sa poslovnog profila?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Zadrži <xliff:g id="SIZE">%1$s</xliff:g> podataka aplikacije."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Želite da izbrišete ovu aplikaciju?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Želite da deinstalirate ovu aplikaciju? Klon aplikacije <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> će takođe biti izbrisan."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Želite da deinstalirate ovu aplikaciju iz privatnog prostora?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Aktivna deinstaliranja"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Neuspela deinstaliranja"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Deinstalira se…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Upravljajte korisnicima"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"Nismo uspeli da deinstaliramo aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Došlo je do problema pri raščlanjivanju paketa."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Radnje Instaliraj/Deinstaliraj nisu podržane u Wear-u."</string>
     <string name="message_staging" msgid="8032722385658438567">"Aplikacija se priprema…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Nepoznato"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Iz bezbednosnih razloga tabletu trenutno nije dozvoljeno da instalira nepoznate aplikacije iz ovog izvora. To možete da promenite u podešavanjima."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Tablet i lični podaci su podložniji napadu nepoznatih aplikacija. Ako instalirate ovu aplikaciju, prihvatate da ste odgovorni za eventualna oštećenja tableta ili gubitak podataka do kojih može da dođe zbog njenog korišćenja."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"TV i lični podaci su podložniji napadu nepoznatih aplikacija. Ako instalirate ovu aplikaciju, prihvatate da ste odgovorni za eventualna oštećenja TV-a ili gubitak podataka do kojih može da dođe zbog njenog korišćenja."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Klon aplikacije <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Nastavi"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Podešavanja"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Instaliranje/deinstaliranje Wear aplikac."</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Želite da vratite <xliff:g id="APPNAME">%1$s</xliff:g> iz <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Aplikacija će započeti preuzimanje u pozadini."</string>
     <string name="restore" msgid="8460854736328970444">"Vrati"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Oflajn ste"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Ova aplikacija će biti vraćena automatski kada se povežete na internet"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Došlo je do greške"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Došlo je do problema pri vraćanju ove aplikacije"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Nema dovoljno memorijskog prostora"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Morate da oslobodite prostor na ovom uređaju da biste vratili ovu aplikaciju. Potreban memorijski prostor: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Treba da reagujete"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Pratite dalja uputstva da biste vratili ovu aplikaciju"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> je onemogućen"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Da biste vratili ovu aplikaciju, omogućite <xliff:g id="INSTALLERNAME">%1$s</xliff:g> u Podešavanjima"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> je deinstaliran"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Da biste vratili ovu aplikaciju, treba da instalirate <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Nastavi"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Obriši memorijski prostor"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Podešavanja"</string>
+    <string name="close" msgid="5214897374055647996">"Zatvori"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-be/strings.xml b/packages/PackageInstaller/res/values-be/strings.xml
index 9e6e6fd..d34ecb6 100644
--- a/packages/PackageInstaller/res/values-be/strings.xml
+++ b/packages/PackageInstaller/res/values-be/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Гэты карыстальнік не можа ўсталёўваць невядомыя праграмы"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Гэты карыстальнік не можа ўсталёўваць праграмы"</string>
     <string name="ok" msgid="7871959885003339302">"ОК"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Усё роўна абнавіць"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Кіраваць"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Не хапае месца"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Выдаліць абнаўленне"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> з\'яўляецца часткай наступнай праграмы:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Выдаліць гэту праграму?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Выдаліць гэту праграму для "<b>"ўсіх"</b>" карыстальнікаў? Праграма і яе даныя будуць выдалены для "<b>"ўсіх"</b>" карыстальнікаў прылады."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Хочаце выдаліць гэту праграму для карыстальніка <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Хочаце выдаліць гэту праграму з працоўнага профілю?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Захаваць даныя праграмы (<xliff:g id="SIZE">%1$s</xliff:g>)."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Выдаліць гэту праграму?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Выдаліць гэту праграму? Таксама будзе выдалены клон \"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>\"."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Выдаліць гэту праграму з прыватнай аўдыторыі?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Актыўныя выдаленні"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Нявыкананыя выдаленні"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Ідзе выдаленне…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Кіраваць карыстальнікамі"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"Не ўдалося выдаліць праграму \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Пры аналізе пакета адбылася памылка."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Дзеянні па ўсталяванні або выдаленні не падтрымліваюцца на Wear."</string>
     <string name="message_staging" msgid="8032722385658438567">"Праграма падрыхтоўваецца…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Невядома"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"У мэтах бяспекі вашаму планшэту забаронена ўсталёўваць невядомыя праграмы з гэтай крыніцы. Вы можаце змяніць гэты дазвол у Наладах."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Ваш планшэт і асабістыя даныя больш прыступныя для атак невядомых праграм. Усталёўваючы гэту праграму, вы згаджаецеся з тым, што несяце адказнасць за любыя пашкоджанні планшэта ці страту даных, якія могуць адбыцца ў выніку выкарыстання гэтай праграмы."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Ваш тэлевізар і асабістыя даныя больш прыступныя для атак невядомых праграм. Усталёўваючы гэту праграму, вы згаджаецеся з тым, што несяце адказнасць за любыя пашкоджанні тэлевізара ці страту даных, якія могуць адбыцца ў выніку выкарыстання гэтай праграмы."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Клон \"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>\""</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Далей"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Налады"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Усталяванне і выдаленне праграм Wear"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Аднавіць праграму \"<xliff:g id="APPNAME">%1$s</xliff:g>\" адсюль: <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Праграма пачне спампоўвацца ў фонавым рэжыме"</string>
     <string name="restore" msgid="8460854736328970444">"Аднавіць"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Вы па-за сеткай"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Гэта праграма будзе аўтаматычна адноўлена, калі прылада падключыцца да інтэрнэту"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Адбылася памылка"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Пры аднаўленні праграмы ўзнікла праблема"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Не хапае месца ў сховішчы"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Каб аднавіць гэту праграму, вызваліце месца на прыладзе. Неабходны аб\'ём месца ў сховішчы: <xliff:g id="BYTES">%1$s</xliff:g>."</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Патрабуецца дзеянне"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Каб аднавіць гэту праграму, выканайце далейшыя інструкцыі"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"Усталёўшчык \"<xliff:g id="INSTALLERNAME">%1$s</xliff:g>\" адключаны"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Каб аднавіць гэту праграму, уключыце ў наладах усталёўшчык \"<xliff:g id="INSTALLERNAME">%1$s</xliff:g>\""</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"Усталёўшчык \"<xliff:g id="INSTALLERNAME">%1$s</xliff:g>\" выдалены"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Каб аднавіць гэту праграму, усталюйце праграму \"<xliff:g id="INSTALLERNAME">%1$s</xliff:g>\""</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Працягнуць"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Ачысціць сховішча"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Налады"</string>
+    <string name="close" msgid="5214897374055647996">"Закрыць"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-bg/strings.xml b/packages/PackageInstaller/res/values-bg/strings.xml
index 1c91874..e0cd7a0 100644
--- a/packages/PackageInstaller/res/values-bg/strings.xml
+++ b/packages/PackageInstaller/res/values-bg/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Този потребител не може да инсталира неизвестни приложения"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Този потребител няма разрешение да инсталира приложения"</string>
     <string name="ok" msgid="7871959885003339302">"OK"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Актуализиране въпреки това"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Прил.: Управл."</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Няма място"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Деинст. на актуализацията"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> е част от следното приложение:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Искате ли да деинсталирате това приложение?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Искате ли да деинсталирате това приложение за "<b>"всички"</b>" потребители? Приложението и данните му ще бъдат премахнати от "<b>"всички"</b>" потребители на устройството."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Искате ли да деинсталирате това приложение за потребителя <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Искате ли да деинсталирате това приложение от служебния си потребителски профил?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Запазване на <xliff:g id="SIZE">%1$s</xliff:g> данни от приложението."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Искате ли да изтриете това приложение?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Искате ли да деинсталирате това приложение? Копието на <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> също ще бъде изтрито."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Искате ли да деинсталирате това приложение от личното си пространство?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Активни деинсталирания"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Неуспешни деинсталирания"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Деинсталира се..."</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Управление на потребителите"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> не можа да се деинсталира."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"При синтактичния анализ на пакета възникна проблем."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Действията инсталиране и деинсталиране не се поддържат на устройства с Wear."</string>
     <string name="message_staging" msgid="8032722385658438567">"Приложението се подготвя…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Неизвестно"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"От съображения за сигурност понастоящем на таблета ви не могат да се инсталират неизвестни приложения от този източник. Можете да промените това от „Настройки“."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Таблетът и личните ви данни са по-уязвими към атаки от неизвестни приложения. С инсталирането на това приложение приемате, че носите отговорност при евентуална повреда на таблета или загуба на информация вследствие на използването на приложението."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Телевизорът и личните ви данни са по-уязвими към атаки от неизвестни приложения. С инсталирането на това приложение приемате, че носите отговорност при евентуална повреда на телевизора или загуба на информация вследствие на използването на приложението."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Копие на <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Напред"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Настройки"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Инсталир./деинсталир. на прилож. за Wear"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Да се възстанови ли <xliff:g id="APPNAME">%1$s</xliff:g> от <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Това приложение ще започне да се изтегля на заден план"</string>
     <string name="restore" msgid="8460854736328970444">"Възстановяване"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Офлайн сте"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Това приложение ще бъде възстановено автоматично, когато имате връзка с интернет"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Нещо се обърка"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"При опита за възстановяване на това приложение възникна проблем"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Няма достатъчно място в хранилището"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"За да възстановите това приложение, ще трябва да освободите място на устройството. Необходимо място в хранилището: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Изисква се действие"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Изпълнете следващите стъпки, за да възстановите това приложение"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> е деактивирано"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"За да възстановите това приложение, активирайте <xliff:g id="INSTALLERNAME">%1$s</xliff:g> от настройките"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> е деинсталирано"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"За да възстановите това приложение, ще трябва да инсталирате <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Напред"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Изчистване на данните"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Настройки"</string>
+    <string name="close" msgid="5214897374055647996">"Затваряне"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-bn/strings.xml b/packages/PackageInstaller/res/values-bn/strings.xml
index 5a78f37..bab2d08 100644
--- a/packages/PackageInstaller/res/values-bn/strings.xml
+++ b/packages/PackageInstaller/res/values-bn/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"এই ব্যবহারকারী অজানা অ্যাপ ইনস্টল করতে পারেন না"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"এই ব্যবহারকারীর অ্যাপ ইনস্টল করার অনুমতি নেই"</string>
     <string name="ok" msgid="7871959885003339302">"ঠিক আছে"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"তবুও আপডেট করতে চাই"</string>
     <string name="manage_applications" msgid="5400164782453975580">"অ্যাপ পরিচালনা"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"জায়গা খালি নেই"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"আপডেট আনইনস্টল করুন"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> এই অ্যাপটির অংশ:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"আপনি কি এই অ্যাপটি আনইনস্টল করতে চান?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"আপনি কি "<b>"সব"</b>" ব্যবহারকারীর জন্য এই অ্যাপটিকে আনইনস্টল করতে চান? এই ডিভাইসের "<b>"সব"</b>" ব্যবহারকারীর ডেটা সহ এই অ্যাপ্লিকেশনটি সরিয়ে দেওয়া হবে।"</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"আপনি কি <xliff:g id="USERNAME">%1$s</xliff:g>-এর জন্য এই অ্যাপটি আনইনস্টল করতে চান?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"আপনার অফিস প্রোফাইল থেকে এই অ্যাপ আনইনস্টল করতে চান?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"অ্যাপ ডেটার মধ্যে <xliff:g id="SIZE">%1$s</xliff:g> রেখে দিন।"</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"আপনি এই অ্যাপ মুছে ফেলতে চান?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"আপনি এই অ্যাপ আনইনস্টল করতে চান? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ক্লোনও মুছে ফেলা হবে।"</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"আপনার ব্যক্তিগত স্পেস থেকে এই অ্যাপ আনইনস্টল করতে চান?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"আনইনস্টল করা হচ্ছে"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"আনইনস্টল করা যায়নি"</string>
     <string name="uninstalling" msgid="8709566347688966845">"আনইনস্টল করা হচ্ছে…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"ব্যবহারকারীদের পরিচালনা করুন"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> আনইনস্টল করা যায়নি।"</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"প্যাকেজটি পার্স করার সময় একটি সমস্যা হয়েছিল।"</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Wear-এ ইনস্টল/আনইনস্টল করা সমর্থিত নয়।"</string>
     <string name="message_staging" msgid="8032722385658438567">"অ্যাপ স্টেজ করা হচ্ছে…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"অজানা"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"আপনার নিরাপত্তার জন্য, এই সোর্স থেকে বর্তমানে আপনার ট্যাবে অজানা অ্যাপ ইনস্টল করা যাবে না। আপনি সেটিংস থেকে এটি পরিবর্তন করতে পারবেন।"</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"অজানা অ্যাপের দ্বারা আপনার ট্যাবলেট এবং ব্যক্তিগত ডেটা আক্রান্ত হওয়ার সম্ভাবনা বেশি থাকে। এই অ্যাপটি ইনস্টল করার মাধ্যমে আপনি সম্মত হচ্ছেন যে এটি ব্যবহারের ফলে আপনার ট্যাবলেটের বা ডেটার কোনও ক্ষতি হলে তার জন্য আপনিই দায়ী থাকবেন।"</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"অজানা অ্যাপের দ্বারা আপনার টিভি এবং ব্যক্তিগত ডেটা আক্রান্ত হওয়ার সম্ভাবনা বেশি থাকে। এই অ্যাপটি ইনস্টল করার মাধ্যমে আপনি সম্মত হচ্ছেন যে এটি ব্যবহারের ফলে আপনার টিভি বা ডেটার কোনও ক্ষতি হলে তার জন্য আপনিই দায়ী থাকবেন।"</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ক্লোন"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"চালিয়ে যান"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"সেটিংস"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Wear অ্যাপ ইনস্টল/আনইনস্টল করা হচ্ছে"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> থেকে <xliff:g id="APPNAME">%1$s</xliff:g> ফিরিয়ে আনবেন?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"এই অ্যাপটি ব্যাকগ্রাউন্ডে ডাউনলোড হওয়া শুরু হবে"</string>
     <string name="restore" msgid="8460854736328970444">"ফিরিয়ে আনুন"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"আপনি অফলাইন আছেন"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"আপনি ইন্টারনেটের সাথে কানেক্ট থাকাকালীন এই অ্যাপ অটোমেটিক ফিরিয়ে আনা হবে"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"কোনও সমস্যা হয়েছে"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"এই অ্যাপ ফিরিয়ে আনতে চেষ্টা করার সময় সমস্যা হয়েছে"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"পর্যাপ্ত স্টোরেজ নেই"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"এই অ্যাপ ফিরিয়ে আনতে, এই ডিভাইসের স্পেস খালি করতে পারেন। স্টোরেজ প্রয়োজন: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"ব্যবস্থা নিতে হবে"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"এই অ্যাপ ফিরিয়ে আনতে পরবর্তী ধাপগুলি ফলো করুন"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> বন্ধ করা হয়েছে"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"এই অ্যাপ ফিরিয়ে আনতে, সেটিংস থেকে <xliff:g id="INSTALLERNAME">%1$s</xliff:g> চালু করুন"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> আনইনস্টল করা হয়েছে"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"এই অ্যাপ ফিরিয়ে আনতে, আপনাকে <xliff:g id="INSTALLERNAME">%1$s</xliff:g> ইনস্টল করতে হবে"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"চালিয়ে যান"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"স্টোরেজ মুছুন"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"সেটিংস"</string>
+    <string name="close" msgid="5214897374055647996">"বন্ধ করুন"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-bs/strings.xml b/packages/PackageInstaller/res/values-bs/strings.xml
index aed2d22..defb388 100644
--- a/packages/PackageInstaller/res/values-bs/strings.xml
+++ b/packages/PackageInstaller/res/values-bs/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Ovaj korisnik ne može instalirati nepoznate aplikacije"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Ovom korisniku nije dozvoljeno instaliranje aplikacija"</string>
     <string name="ok" msgid="7871959885003339302">"Uredu"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Ipak ažuriraj"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Uprav. aplik."</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Nedostatak prostora"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Deinstaliraj ažuriranje"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> je dio sljedeće aplikacije:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Želite li deinstalirati ovu aplikaciju?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Želite li deinstalirati ovu aplikaciju za "<b>" sve "</b>" korisnike? Aplikacija i njeni podaci će biti uklonjeni iz "<b>" svih "</b>" korisničkih računa na uređaju."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Želite li deinstalirati ovu aplikaciju za korisnika <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Želite li deinstalirati ovu aplikaciju s radnog profila?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Zadržati <xliff:g id="SIZE">%1$s</xliff:g> podataka aplikacije."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Želite li izbrisati ovu aplikaciju?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Želite li deinstalirati ovu aplikaciju? Izbrisat će se i klon aplikacije <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Želite li deinstalirati ovu aplikaciju iz privatnog prostora?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Tekuća deinstaliranja"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Neuspjela deinstaliranja"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Deinstaliranje..."</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Upravljajte korisnicima"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> se ne može deinstalirati."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Došlo je do problema prilikom raščlanjivanja paketa."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Instaliranje/deinstaliranje nije podržano na Wearu."</string>
     <string name="message_staging" msgid="8032722385658438567">"Pripremanje aplikacije…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Nepoznato"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Radi vaše sigurnosti tabletu trenutno nije dozvoljeno da instalira nepoznate aplikacije iz ovog izvora. Ovo možete promijeniti u Postavkama."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Vaši podaci na tabletu i vaši lični podaci izloženiji su napadima nepoznatih aplikacija. Instaliranjem ove aplikacije, prihvatate odgovornost za bilo kakvu štetu na tabletu ili gubitak podataka do kojih može doći korištenjem aplikacije."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Vaši podaci na TV-u i vaši lični podaci izloženiji su napadima nepoznatih aplikacija. Instaliranjem ove aplikacije, prihvatate odgovornost za bilo kakvu štetu na TV-u ili gubitak podataka do kojih može doći korištenjem aplikacije."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Klon aplikacije <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Nastavi"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Postavke"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Instaliranje/deinstaliranje Wear aplik."</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Vratiti aplikaciju <xliff:g id="APPNAME">%1$s</xliff:g> s usluge <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Preuzimanje aplikacije će započeti u pozadini"</string>
     <string name="restore" msgid="8460854736328970444">"Vrati"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Offline ste"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Aplikacija će se automatski vratiti kada se povežete s internetom"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Nešto nije uredu"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Došlo je do problema prilikom pokušaja vraćanja aplikacije"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Nema dovoljno prostora za pohranu"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Da vratite aplikaciju, možete osloboditi prostor na uređaju. Potrebna pohrana: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Potrebna je radnja"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Pratite sljedeće korake da vratite ovu aplikaciju"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"Program za instaliranje <xliff:g id="INSTALLERNAME">%1$s</xliff:g> je onemogućen"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Da vratite aplikaciju, omogućite program za instaliranje <xliff:g id="INSTALLERNAME">%1$s</xliff:g> u Postavkama"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"Program za instaliranje <xliff:g id="INSTALLERNAME">%1$s</xliff:g> je deinstaliran"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Da vratite aplikaciju, trebat ćete instalirati program za instaliranje <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Nastavi"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Obriši pohranu"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Postavke"</string>
+    <string name="close" msgid="5214897374055647996">"Zatvori"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-ca/strings.xml b/packages/PackageInstaller/res/values-ca/strings.xml
index 85e5110..50e105c 100644
--- a/packages/PackageInstaller/res/values-ca/strings.xml
+++ b/packages/PackageInstaller/res/values-ca/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Aquest usuari no pot instal·lar aplicacions desconegudes"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Aquest usuari no té permís per instal·lar aplicacions"</string>
     <string name="ok" msgid="7871959885003339302">"D\'acord"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Actualitza de tota manera"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Gestiona apps"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Espai esgotat"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Desinstal·la l\'actualització"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> forma part de l\'aplicació següent:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Vols desinstal·lar aquesta aplicació?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Vols desinstal·lar aquesta aplicació per a "<b>"tots"</b>" els usuaris? L\'aplicació i les seves dades se suprimiran per a "<b>"tots"</b>" els usuaris del dispositiu."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Vols desinstal·lar aquesta aplicació per a l\'usuari <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Vols desinstal·lar aquesta aplicació del teu perfil de treball?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Conserva <xliff:g id="SIZE">%1$s</xliff:g> de dades de l\'aplicació."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Vols suprimir aquesta aplicació?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Vols desinstal·lar aquesta aplicació? El clon de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> també se suprimirà."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Vols desinstal·lar aquesta aplicació del teu espai privat?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Desinstal·lacions en curs"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Desinstal·lacions fallides"</string>
     <string name="uninstalling" msgid="8709566347688966845">"S\'està desinstal·lant…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Gestiona els usuaris"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"No s\'ha pogut desinstal·lar <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Hi ha hagut un problema en analitzar el paquet."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Les accions d\'instal·lar o de desinstal·lar no s\'admeten a Wear."</string>
     <string name="message_staging" msgid="8032722385658438567">"S\'està preparant la instal·lació de l\'aplicació…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Desconeguda"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Per la teva seguretat, actualment la tauleta no pot instal·lar aplicacions desconegudes d\'aquesta font. Pots canviar-ho a Configuració."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"La tauleta i les dades personals són més vulnerables als atacs d\'aplicacions desconegudes. En instal·lar aquesta aplicació, acceptes que ets responsable de qualsevol dany que es produeixi a la tauleta o de la pèrdua de dades que pugui resultar del seu ús."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"El televisor i les dades personals són més vulnerables als atacs d\'aplicacions desconegudes. En instal·lar aquesta aplicació, acceptes que ets responsable de qualsevol dany que es produeixi al televisor o de la pèrdua de dades que pugui resultar del seu ús."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Clon de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Continua"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Configuració"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Instal·lant o desinstal·lant apps de Wear"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Vols restaurar <xliff:g id="APPNAME">%1$s</xliff:g> des de <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Aquesta aplicació començarà a baixar-se en segon pla"</string>
     <string name="restore" msgid="8460854736328970444">"Restaura"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"No tens connexió"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"L\'aplicació es restaurarà automàticament quan tinguis connexió a Internet"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"S\'ha produït un error"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Hi ha hagut un problema en intentar restaurar aquesta aplicació"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"No hi ha prou emmagatzematge"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Per restaurar l\'aplicació, allibera espai en aquest dispositiu. Emmagatzematge necessari: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Acció necessària"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Segueix els passos que hi ha continuació per restaurar l\'aplicació"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> està desactivat"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Per restaurar aquesta aplicació, activa <xliff:g id="INSTALLERNAME">%1$s</xliff:g> a Configuració"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> no està instal·lat"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Per restaurar l\'aplicació, cal que instal·lis <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Continua"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Esborra emmagatzematge"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Configuració"</string>
+    <string name="close" msgid="5214897374055647996">"Tanca"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-cs/strings.xml b/packages/PackageInstaller/res/values-cs/strings.xml
index fc85bca..3b204be 100644
--- a/packages/PackageInstaller/res/values-cs/strings.xml
+++ b/packages/PackageInstaller/res/values-cs/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Tento uživatel nemůže instalovat neznámé aplikace"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Tento uživatel nesmí instalovat aplikace"</string>
     <string name="ok" msgid="7871959885003339302">"OK"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Přesto aktualizovat"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Správa aplikací"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Nedostatek místa"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Odinstalovat aktualizaci"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"Činnost <xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> je součástí následující aplikace:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Chcete tuto aplikaci odinstalovat?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Chcete tuto aplikaci odinstalovat "<b>"všem"</b>" uživatelům? Aplikace a její údaje budou odstraněny "<b>"všem"</b>" uživatelům tohoto zařízení."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Chcete tuto aplikaci pro uživatele <xliff:g id="USERNAME">%1$s</xliff:g> odinstalovat?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Chcete tuto aplikaci odinstalovat ze svého pracovního profilu?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Ponechat data aplikace o velikosti <xliff:g id="SIZE">%1$s</xliff:g>."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Chcete tuto aplikaci smazat?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Chcete tuto aplikaci odinstalovat? Smazán bude také klon <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Chcete tuto aplikaci odinstalovat ze soukromého prostoru?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Probíhající odinstalace"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Neúspěšné odinstalace"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Odinstalace…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Správa uživatelů"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"Aplikaci <xliff:g id="APP_NAME">%1$s</xliff:g> nelze odinstalovat."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Při analýze balíčku došlo k chybě."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Akce instalace/odinstalace nejsou v zařízení Wear podporovány."</string>
     <string name="message_staging" msgid="8032722385658438567">"Příprava instalace…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Neznámé"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Z bezpečnostních důvodů momentálně není dovoleno do tabletu instalovat neznámé aplikace z tohoto zdroje. Změnit to můžete v Nastavení."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Tablet a osobní údaje jsou zranitelnější vůči útoku ze strany neznámých aplikací. Instalací této aplikace přijímáte odpovědnost za případné škody na tabletu nebo ztrátu dat, která může být používáním aplikace způsobena."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Televize a osobní údaje jsou zranitelnější vůči útoku ze strany neznámých aplikací. Instalací této aplikace přijímáte odpovědnost za případné škody na televizi nebo ztrátu dat, která může být používáním aplikace způsobena."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Klon <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Pokračovat"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Nastavení"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Instalace/odinstalace aplikací pro Wear"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Obnovit aplikaci <xliff:g id="APPNAME">%1$s</xliff:g> z aplikace <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Aplikace se začne stahovat na pozadí"</string>
     <string name="restore" msgid="8460854736328970444">"Obnovit"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Nejste připojeni k internetu"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Tato aplikace se automaticky obnoví, až budete připojeni k internetu"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Něco se pokazilo"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Při pokusu o obnovení této aplikace došlo k problému"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Nedostatek úložného prostoru"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Pokud tuto aplikaci chcete obnovit, uvolněte na zařízení místo. Požadované úložiště: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Vyžadovaná akce"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Pokud tuto aplikaci chcete obnovit, postupujte podle následujících pokynů"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> je zakázán"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Pokud tuto aplikaci chcete obnovit, povolte v Nastavení <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> je odinstalován"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Pokud tuto aplikaci chcete obnovit, bude potřeba nainstalovat <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Pokračovat"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Vymazat úložiště"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Nastavení"</string>
+    <string name="close" msgid="5214897374055647996">"Zavřít"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-da/strings.xml b/packages/PackageInstaller/res/values-da/strings.xml
index aa6fe8f..d7819c7 100644
--- a/packages/PackageInstaller/res/values-da/strings.xml
+++ b/packages/PackageInstaller/res/values-da/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Denne bruger kan ikke installere ukendte apps"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Denne bruger har ikke tilladelse til at installere apps"</string>
     <string name="ok" msgid="7871959885003339302">"OK"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Opdater alligevel"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Administrer apps"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Der er ikke mere plads"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Afinstaller opdatering"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> er en del af følgende app:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Vil du afinstallere denne app?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Vil du afinstallere denne app for "<b>"alle"</b>" brugere? Appen og dens data fjernes fra "<b>"alle"</b>" brugere på denne enhed."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Vil du afinstallere denne app for brugeren <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Vil du afinstallere denne app fra din arbejdsprofil?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Behold <xliff:g id="SIZE">%1$s</xliff:g> appdata."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Vil du slette denne app?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Vil du afinstallere denne app? Klonen af <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> slettes også."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Vil du afinstallere denne app fra dit private område?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Igangværende afinstallationer"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Mislykkede afinstallationer"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Afinstallerer…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Administrer brugere"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> kunne ikke afinstalleres."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Der opstod et problem med parsing af pakken."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Det er ikke muligt at installere/afinstallere på Wear."</string>
     <string name="message_staging" msgid="8032722385658438567">"Forbereder appen…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Ukendt"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Af hensyn til din sikkerhed har din tablet i øjeblikket ikke tilladelse til at installere ukendte apps fra denne kilde. Du kan ændre dette i Indstillinger."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Din tablet og dine personlige data er mere sårbare over for angreb fra ukendte apps. Når du installerer denne app, accepterer du, at du er ansvarlig for skader på din tablet eller tab af data, der kan skyldes brug af appen."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Dit fjernsyn og dine personlige data er mere sårbare over for angreb fra ukendte apps. Når du installerer denne app, accepterer du, at du er ansvarlig for skader på dit fjernsyn eller tab af data, der kan skyldes brug af appen."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Klon af <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Fortsæt"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Indstillinger"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Installerer/afinstallerer Wear-apps"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Vil du gendanne <xliff:g id="APPNAME">%1$s</xliff:g> fra <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Download af denne app startes i baggrunden"</string>
     <string name="restore" msgid="8460854736328970444">"Gendan"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Du er offline"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Denne app gendannes automatisk, når du har forbindelse til internettet"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Noget gik galt"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Der opstod et problem under gendannelsen af denne app"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Ikke nok lagerplads"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Hvis du vil gendanne denne app, skal du frigøre plads på enheden. Påkrævet lagerplads: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Handling påkrævet"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Følg de næste trin for at gendanne denne app"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> er deaktiveret"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Aktivér <xliff:g id="INSTALLERNAME">%1$s</xliff:g> under Indstillinger for at gendanne denne app"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> er afinstalleret"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Du skal installere <xliff:g id="INSTALLERNAME">%1$s</xliff:g> for at gendanne denne app"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Fortsæt"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Ryd lagerplads"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Indstillinger"</string>
+    <string name="close" msgid="5214897374055647996">"Luk"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-de/strings.xml b/packages/PackageInstaller/res/values-de/strings.xml
index dc23696..666ef45 100644
--- a/packages/PackageInstaller/res/values-de/strings.xml
+++ b/packages/PackageInstaller/res/values-de/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Dieser Nutzer darf keine unbekannten Apps installieren"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Dieser Nutzer darf keine Apps installieren"</string>
     <string name="ok" msgid="7871959885003339302">"Ok"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Trotzdem aktualisieren"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Apps verwalten"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Kein freier Speicher vorhanden"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Update deinstallieren"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> gehört zu folgender App:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Möchtest du diese App deinstallieren?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Möchtest du diese App für "<b>"alle"</b>" Nutzer entfernen? Die App und alle zugehörigen Daten werden für "<b>"alle"</b>" Nutzer des Geräts entfernt."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Möchtest du diese App für den Nutzer <xliff:g id="USERNAME">%1$s</xliff:g> deinstallieren?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Möchtest du diese App aus deinem Arbeitsprofil deinstallieren?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"<xliff:g id="SIZE">%1$s</xliff:g> an App-Daten behalten."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Möchtest du diese App löschen?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Möchtest du diese App deinstallieren? Der <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-Klon wird ebenfalls gelöscht."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Möchtest du diese App in deinem privaten Bereich deinstallieren?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Laufende Deinstallationen"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Fehlgeschlagene Deinstallationen"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Wird deinstalliert..."</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Nutzer verwalten"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> konnte nicht deinstalliert werden."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Beim Parsen des Pakets ist ein Problem aufgetreten."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Installations-/Deinstallationsaktion auf Android Wear nicht unterstützt."</string>
     <string name="message_staging" msgid="8032722385658438567">"App wird vorbereitet…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Unbekannt"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Aus Sicherheitsgründen kannst du auf deinem Tablet zurzeit keine unbekannten Apps aus dieser Quelle installieren. Das kannst du in den Einstellungen ändern."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Unbekannte Apps können gefährlich für dein Tablet und deine personenbezogenen Daten sein. Wenn du diese App installierst, erklärst du dich damit einverstanden, dass du die Verantwortung für alle Schäden an deinem Tablet und jegliche Datenverluste trägst, die aus der Verwendung dieser App entstehen können."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Unbekannte Apps können gefährlich für deinen Fernseher und deine personenbezogenen Daten sein. Wenn du diese App installierst, erklärst du dich damit einverstanden, dass du die Verantwortung für alle Schäden an deinem Fernseher und jegliche Datenverluste trägst, die aus der Verwendung dieser App entstehen können."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-Klon"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Weiter"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Einstellungen"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Wear-Apps installieren/deinstallieren"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"<xliff:g id="APPNAME">%1$s</xliff:g> von <xliff:g id="INSTALLERNAME">%1$s</xliff:g> wiederherstellen?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Diese App beginnt im Hintergrund mit dem Herunterladen"</string>
     <string name="restore" msgid="8460854736328970444">"Wiederherstellen"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Du bist offline"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Die App wird automatisch wiederhergestellt, sobald du mit dem Internet verbunden bist"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Ein Fehler ist aufgetreten"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Beim Wiederherstellen der App ist ein Fehler aufgetreten"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Nicht genügend Speicherplatz"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Um die App wiederherzustellen, musst du erst Speicherplatz auf diesem Gerät freigeben. Erforderlicher Speicherplatz: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Aktion erforderlich"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Folge den nächsten Schritten, um die App wiederherzustellen"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> ist deaktiviert"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Um die App wiederherzustellen, aktiviere den <xliff:g id="INSTALLERNAME">%1$s</xliff:g> in den Einstellungen"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> ist deinstalliert"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Um die App wiederherzustellen, musst du den <xliff:g id="INSTALLERNAME">%1$s</xliff:g> installieren"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Weiter"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Speicherinhalt löschen"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Einstellungen"</string>
+    <string name="close" msgid="5214897374055647996">"Schließen"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-el/strings.xml b/packages/PackageInstaller/res/values-el/strings.xml
index ea4eeb6..94e50b1 100644
--- a/packages/PackageInstaller/res/values-el/strings.xml
+++ b/packages/PackageInstaller/res/values-el/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Δεν είναι δυνατή η εγκατάσταση άγνωστων εφαρμογών από αυτόν τον χρήστη"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Δεν επιτρέπεται η εγκατάσταση εφαρμογών σε αυτόν τον χρήστη"</string>
     <string name="ok" msgid="7871959885003339302">"ΟΚ"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Να ενημερωθεί ούτως ή άλλως"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Διαχ. εφαρμογών"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Δεν υπάρχει χώρος"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Απεγκατάσταση ενημέρωσης"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"Η δραστηριότητα <xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> αποτελεί τμήμα της ακόλουθης εφαρμογής:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Θέλετε να απεγκαταστήσετε αυτή την εφαρμογή;"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Θέλετε να απεγκαταστήσετε αυτή την εφαρμογή για "<b>"όλους"</b>" τους χρήστες; Η εφαρμογή και τα δεδομένα της θα καταργηθούν από "<b>"όλους"</b>" τους χρήστες στη συσκευή."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Θέλετε να απεγκαταστήσετε αυτή την εφαρμογή για τον χρήστη <xliff:g id="USERNAME">%1$s</xliff:g>;"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Θέλετε να καταργήσετε την εγκατάσταση αυτής της εφαρμογής από το προφίλ εργασίας σας;"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Διατήρηση <xliff:g id="SIZE">%1$s</xliff:g> δεδομένων εφαρμογών."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Θέλετε να διαγράψετε αυτή την εφαρμογή;"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Θέλετε να απεγκαταστήσετε αυτή την εφαρμογή; Θα διαγραφεί επίσης το διπλότυπο της εφαρμογής <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Θέλετε να απεγκαταστήσετε αυτή την εφαρμογή από τον ιδιωτικό χώρο;"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Απεγκαταστάσεις σε εξέλιξη"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Αποτυχημένες απεγκαταστάσεις"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Απεγκατάσταση…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Διαχείριση χρηστών"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"Δεν ήταν δυνατή η απεγκατάσταση της εφαρμογής <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Παρουσιάστηκε κάποιο πρόβλημα κατά την ανάλυση του πακέτου."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Οι ενέργειες εγκατάστασης/απεγκατάστασης δεν υποστηρίζονται στο Wear."</string>
     <string name="message_staging" msgid="8032722385658438567">"Σταδιακή διάθεση εφαρμογής…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Άγνωστη"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Για λόγους ασφαλείας, δεν επιτρέπεται προς το παρόν η εγκατάσταση άγνωστων εφαρμογών από αυτή την πηγή στο tablet σας. Μπορείτε να αλλάξετε την επιλογή από τις Ρυθμίσεις."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Το tablet σας και τα προσωπικά δεδομένα σας είναι πιο ευάλωτα σε επιθέσεις από άγνωστες εφαρμογές. Με την εγκατάσταση αυτής της εφαρμογής, συμφωνείτε ότι είστε υπεύθυνοι για τυχόν βλάβη που μπορεί να προκληθεί στο tablet ή απώλεια δεδομένων που μπορεί να προκύψει από τη χρήση τους."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Η τηλεόρασή σας και τα προσωπικά δεδομένα σας είναι πιο ευάλωτα σε επιθέσεις από άγνωστες εφαρμογές. Με την εγκατάσταση αυτής της εφαρμογής, συμφωνείτε ότι είστε υπεύθυνοι για τυχόν βλάβη που μπορεί να προκληθεί στην τηλεόρασή ή απώλεια δεδομένων που μπορεί να προκύψει από τη χρήση τους."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Διπλότυπο <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Συνέχεια"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Ρυθμίσεις"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Εγκατάσταση/απεγκατάσταση εφαρμογών Wear"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Επαναφορά <xliff:g id="APPNAME">%1$s</xliff:g> από <xliff:g id="INSTALLERNAME">%1$s</xliff:g>;"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Η λήψη της εφαρμογής θα ξεκινήσει στο παρασκήνιο"</string>
     <string name="restore" msgid="8460854736328970444">"Επαναφορά"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Είστε εκτός σύνδεσης"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Θα γίνει αυτόματη επαναφορά αυτής της εφαρμογής όταν είστε συνδεδεμένοι στο διαδίκτυο"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Κάτι πήγε στραβά"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Παρουσιάστηκε κάποιο πρόβλημα κατά την επαναφορά αυτής της εφαρμογής"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Δεν επαρκεί ο αποθηκευτικός χώρος"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Για να επαναφέρετε αυτή την εφαρμογή, μπορείτε να ελευθερώσετε χώρο στη συσκευή. Απαιτούμενος αποθηκευτικός χώρος: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Απαιτούμενη ενέργεια"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Ακολουθήστε τα επόμενα βήματα για να επαναφέρετε αυτή την εφαρμογή"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"Το <xliff:g id="INSTALLERNAME">%1$s</xliff:g> είναι απενεργοποιημένο"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Για να επαναφέρετε αυτή την εφαρμογή, ενεργοποιήστε το <xliff:g id="INSTALLERNAME">%1$s</xliff:g> στις ρυθμίσεις"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"Το <xliff:g id="INSTALLERNAME">%1$s</xliff:g> έχει απεγκατασταθεί"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Για να επαναφέρετε αυτή την εφαρμογή, πρέπει να εγκαταστήσετε το <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Συνέχεια"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Διαγραφή αποθηκευτικού χώρου"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Ρυθμίσεις"</string>
+    <string name="close" msgid="5214897374055647996">"Κλείσιμο"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-en-rAU/strings.xml b/packages/PackageInstaller/res/values-en-rAU/strings.xml
index 0187172..9be53ab 100644
--- a/packages/PackageInstaller/res/values-en-rAU/strings.xml
+++ b/packages/PackageInstaller/res/values-en-rAU/strings.xml
@@ -44,6 +44,7 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Unknown apps can\'t be installed by this user"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"This user is not allowed to install apps"</string>
     <string name="ok" msgid="7871959885003339302">"OK"</string>
+    <string name="archive" msgid="4447791830199354721">"Archive"</string>
     <string name="update_anyway" msgid="8792432341346261969">"Update anyway"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Manage apps"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Out of space"</string>
@@ -58,6 +59,11 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Uninstall update"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> is part of the following app:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Do you want to uninstall this app?"</string>
+    <string name="archive_application_text" msgid="8482325710714386348">"Your personal data will be saved"</string>
+    <string name="archive_application_text_all_users" msgid="3151229641681672580">"Archive this app for all users? Your personal data will be saved"</string>
+    <string name="archive_application_text_current_user_work_profile" msgid="1450487362134779752">"Archive this app on your work profile? Your personal data will be saved"</string>
+    <string name="archive_application_text_user" msgid="2586558895535581451">"Archive this app for <xliff:g id="USERNAME">%1$s</xliff:g>? Your personal data will be saved"</string>
+    <string name="archive_application_text_current_user_private_profile" msgid="1958423158655599132">"Do you want to archive this app from your private space? Your personal data will be saved"</string>
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Do you want to uninstall this app for "<b>"all"</b>" users? The application and its data will be removed from "<b>"all"</b>" users on the device."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Do you want to uninstall this app for the user <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Do you want to uninstall this app from your work profile?"</string>
@@ -66,6 +72,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Keep <xliff:g id="SIZE">%1$s</xliff:g> of app data."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Do you want to delete this app?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Do you want to uninstall this app? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> clone will also be deleted."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Do you want to uninstall this app from your private space?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Running uninstallations"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Failed uninstallations"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Uninstalling…"</string>
@@ -85,8 +92,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Manage users"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> couldn\'t be uninstalled."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"There was a problem while parsing the package."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Install/uninstall actions not supported on Wear."</string>
     <string name="message_staging" msgid="8032722385658438567">"Staging app…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Unknown"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"For your security, your tablet currently isn’t allowed to install unknown apps from this source. You can change this in Settings."</string>
@@ -97,6 +102,7 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Your tablet and personal data are more vulnerable to attack by unknown apps. By installing this app, you agree that you are responsible for any damage to your tablet or loss of data that may result from its use."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Your TV and personal data are more vulnerable to attack by unknown apps. By installing this app, you agree that you are responsible for any damage to your TV or loss of data that may result from its use."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> clone"</string>
+    <string name="archiving_app_label" msgid="1127085259724124725">"Archive <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>?"</string>
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Continue"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Settings"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Installing/uninstalling Wear apps"</string>
@@ -106,4 +112,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Restore <xliff:g id="APPNAME">%1$s</xliff:g> from <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"This app will start downloading in the background"</string>
     <string name="restore" msgid="8460854736328970444">"Restore"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"You\'re offline"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"This app will automatically restore when you\'re connected to the Internet"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Something went wrong"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"There was a problem trying to restore this app"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Not enough storage"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"To restore this app, you can free up space on this device. Storage required: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Action required"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Follow the next steps to restore this app"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> is disabled"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"To restore this app, enable <xliff:g id="INSTALLERNAME">%1$s</xliff:g> in Settings"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> is uninstalled"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"To restore this app, you\'ll need to install <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Continue"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Clear storage"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Settings"</string>
+    <string name="close" msgid="5214897374055647996">"Close"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-en-rCA/strings.xml b/packages/PackageInstaller/res/values-en-rCA/strings.xml
index 9b31f27..7a30d4d 100644
--- a/packages/PackageInstaller/res/values-en-rCA/strings.xml
+++ b/packages/PackageInstaller/res/values-en-rCA/strings.xml
@@ -44,6 +44,7 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Unknown apps can\'t be installed by this user"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"This user is not allowed to install apps"</string>
     <string name="ok" msgid="7871959885003339302">"OK"</string>
+    <string name="archive" msgid="4447791830199354721">"Archive"</string>
     <string name="update_anyway" msgid="8792432341346261969">"Update anyway"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Manage apps"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Out of space"</string>
@@ -58,6 +59,11 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Uninstall update"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> is part of the following app:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Do you want to uninstall this app?"</string>
+    <string name="archive_application_text" msgid="8482325710714386348">"Your personal data will be saved"</string>
+    <string name="archive_application_text_all_users" msgid="3151229641681672580">"Archive this app for all users? Your personal data will be saved"</string>
+    <string name="archive_application_text_current_user_work_profile" msgid="1450487362134779752">"Archive this app on your work profile? Your personal data will be saved"</string>
+    <string name="archive_application_text_user" msgid="2586558895535581451">"Archive this app for <xliff:g id="USERNAME">%1$s</xliff:g>? Your personal data will be saved"</string>
+    <string name="archive_application_text_current_user_private_profile" msgid="1958423158655599132">"Do you want to archive this app from your private space? Your personal data will be saved"</string>
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Do you want to uninstall this app for "<b>"all"</b>" users? The application and its data will be removed from "<b>"all"</b>" users on the device."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Do you want to uninstall this app for the user <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Do you want to uninstall this app from your work profile?"</string>
@@ -66,6 +72,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Keep <xliff:g id="SIZE">%1$s</xliff:g> of app data."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Do you want to delete this app?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Do you want to uninstall this app? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> clone will also be deleted."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Do you want to uninstall this app from your private space?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Running uninstalls"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Failed uninstalls"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Uninstalling…"</string>
@@ -85,8 +92,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Manage users"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> couldn\'t be uninstalled."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"There was a problem parsing the package."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Install/Uninstall actions not supported on Wear."</string>
     <string name="message_staging" msgid="8032722385658438567">"Staging app…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Unknown"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"For your security, your tablet currently isn’t allowed to install unknown apps from this source. You can change this in Settings."</string>
@@ -97,6 +102,7 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Your tablet and personal data are more vulnerable to attack by unknown apps. By installing this app, you agree that you are responsible for any damage to your tablet or loss of data that may result from its use."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Your TV and personal data are more vulnerable to attack by unknown apps. By installing this app, you agree that you are responsible for any damage to your TV or loss of data that may result from its use."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> Clone"</string>
+    <string name="archiving_app_label" msgid="1127085259724124725">"Archive <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>?"</string>
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Continue"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Settings"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Installing/uninstalling wear apps"</string>
@@ -106,4 +112,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Restore <xliff:g id="APPNAME">%1$s</xliff:g> from <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"This app will begin to download in the background"</string>
     <string name="restore" msgid="8460854736328970444">"Restore"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"You\'re offline"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"This app will automatically restore when you\'re connected to the internet"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Something went wrong"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"There was a problem trying to restore this app"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Not enough storage"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"To restore this app, you can free up space on this device. Storage required: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Action required"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Follow the next steps to restore this app"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> is disabled"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"To restore this app, enable <xliff:g id="INSTALLERNAME">%1$s</xliff:g> in Settings"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> is uninstalled"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"To restore this app, you\'ll need to install <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Continue"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Clear storage"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Settings"</string>
+    <string name="close" msgid="5214897374055647996">"Close"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-en-rGB/strings.xml b/packages/PackageInstaller/res/values-en-rGB/strings.xml
index 0187172..9be53ab 100644
--- a/packages/PackageInstaller/res/values-en-rGB/strings.xml
+++ b/packages/PackageInstaller/res/values-en-rGB/strings.xml
@@ -44,6 +44,7 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Unknown apps can\'t be installed by this user"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"This user is not allowed to install apps"</string>
     <string name="ok" msgid="7871959885003339302">"OK"</string>
+    <string name="archive" msgid="4447791830199354721">"Archive"</string>
     <string name="update_anyway" msgid="8792432341346261969">"Update anyway"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Manage apps"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Out of space"</string>
@@ -58,6 +59,11 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Uninstall update"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> is part of the following app:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Do you want to uninstall this app?"</string>
+    <string name="archive_application_text" msgid="8482325710714386348">"Your personal data will be saved"</string>
+    <string name="archive_application_text_all_users" msgid="3151229641681672580">"Archive this app for all users? Your personal data will be saved"</string>
+    <string name="archive_application_text_current_user_work_profile" msgid="1450487362134779752">"Archive this app on your work profile? Your personal data will be saved"</string>
+    <string name="archive_application_text_user" msgid="2586558895535581451">"Archive this app for <xliff:g id="USERNAME">%1$s</xliff:g>? Your personal data will be saved"</string>
+    <string name="archive_application_text_current_user_private_profile" msgid="1958423158655599132">"Do you want to archive this app from your private space? Your personal data will be saved"</string>
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Do you want to uninstall this app for "<b>"all"</b>" users? The application and its data will be removed from "<b>"all"</b>" users on the device."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Do you want to uninstall this app for the user <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Do you want to uninstall this app from your work profile?"</string>
@@ -66,6 +72,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Keep <xliff:g id="SIZE">%1$s</xliff:g> of app data."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Do you want to delete this app?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Do you want to uninstall this app? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> clone will also be deleted."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Do you want to uninstall this app from your private space?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Running uninstallations"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Failed uninstallations"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Uninstalling…"</string>
@@ -85,8 +92,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Manage users"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> couldn\'t be uninstalled."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"There was a problem while parsing the package."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Install/uninstall actions not supported on Wear."</string>
     <string name="message_staging" msgid="8032722385658438567">"Staging app…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Unknown"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"For your security, your tablet currently isn’t allowed to install unknown apps from this source. You can change this in Settings."</string>
@@ -97,6 +102,7 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Your tablet and personal data are more vulnerable to attack by unknown apps. By installing this app, you agree that you are responsible for any damage to your tablet or loss of data that may result from its use."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Your TV and personal data are more vulnerable to attack by unknown apps. By installing this app, you agree that you are responsible for any damage to your TV or loss of data that may result from its use."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> clone"</string>
+    <string name="archiving_app_label" msgid="1127085259724124725">"Archive <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>?"</string>
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Continue"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Settings"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Installing/uninstalling Wear apps"</string>
@@ -106,4 +112,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Restore <xliff:g id="APPNAME">%1$s</xliff:g> from <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"This app will start downloading in the background"</string>
     <string name="restore" msgid="8460854736328970444">"Restore"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"You\'re offline"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"This app will automatically restore when you\'re connected to the Internet"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Something went wrong"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"There was a problem trying to restore this app"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Not enough storage"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"To restore this app, you can free up space on this device. Storage required: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Action required"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Follow the next steps to restore this app"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> is disabled"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"To restore this app, enable <xliff:g id="INSTALLERNAME">%1$s</xliff:g> in Settings"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> is uninstalled"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"To restore this app, you\'ll need to install <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Continue"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Clear storage"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Settings"</string>
+    <string name="close" msgid="5214897374055647996">"Close"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-en-rIN/strings.xml b/packages/PackageInstaller/res/values-en-rIN/strings.xml
index 0187172..9be53ab 100644
--- a/packages/PackageInstaller/res/values-en-rIN/strings.xml
+++ b/packages/PackageInstaller/res/values-en-rIN/strings.xml
@@ -44,6 +44,7 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Unknown apps can\'t be installed by this user"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"This user is not allowed to install apps"</string>
     <string name="ok" msgid="7871959885003339302">"OK"</string>
+    <string name="archive" msgid="4447791830199354721">"Archive"</string>
     <string name="update_anyway" msgid="8792432341346261969">"Update anyway"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Manage apps"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Out of space"</string>
@@ -58,6 +59,11 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Uninstall update"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> is part of the following app:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Do you want to uninstall this app?"</string>
+    <string name="archive_application_text" msgid="8482325710714386348">"Your personal data will be saved"</string>
+    <string name="archive_application_text_all_users" msgid="3151229641681672580">"Archive this app for all users? Your personal data will be saved"</string>
+    <string name="archive_application_text_current_user_work_profile" msgid="1450487362134779752">"Archive this app on your work profile? Your personal data will be saved"</string>
+    <string name="archive_application_text_user" msgid="2586558895535581451">"Archive this app for <xliff:g id="USERNAME">%1$s</xliff:g>? Your personal data will be saved"</string>
+    <string name="archive_application_text_current_user_private_profile" msgid="1958423158655599132">"Do you want to archive this app from your private space? Your personal data will be saved"</string>
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Do you want to uninstall this app for "<b>"all"</b>" users? The application and its data will be removed from "<b>"all"</b>" users on the device."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Do you want to uninstall this app for the user <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Do you want to uninstall this app from your work profile?"</string>
@@ -66,6 +72,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Keep <xliff:g id="SIZE">%1$s</xliff:g> of app data."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Do you want to delete this app?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Do you want to uninstall this app? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> clone will also be deleted."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Do you want to uninstall this app from your private space?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Running uninstallations"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Failed uninstallations"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Uninstalling…"</string>
@@ -85,8 +92,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Manage users"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> couldn\'t be uninstalled."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"There was a problem while parsing the package."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Install/uninstall actions not supported on Wear."</string>
     <string name="message_staging" msgid="8032722385658438567">"Staging app…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Unknown"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"For your security, your tablet currently isn’t allowed to install unknown apps from this source. You can change this in Settings."</string>
@@ -97,6 +102,7 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Your tablet and personal data are more vulnerable to attack by unknown apps. By installing this app, you agree that you are responsible for any damage to your tablet or loss of data that may result from its use."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Your TV and personal data are more vulnerable to attack by unknown apps. By installing this app, you agree that you are responsible for any damage to your TV or loss of data that may result from its use."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> clone"</string>
+    <string name="archiving_app_label" msgid="1127085259724124725">"Archive <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>?"</string>
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Continue"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Settings"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Installing/uninstalling Wear apps"</string>
@@ -106,4 +112,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Restore <xliff:g id="APPNAME">%1$s</xliff:g> from <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"This app will start downloading in the background"</string>
     <string name="restore" msgid="8460854736328970444">"Restore"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"You\'re offline"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"This app will automatically restore when you\'re connected to the Internet"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Something went wrong"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"There was a problem trying to restore this app"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Not enough storage"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"To restore this app, you can free up space on this device. Storage required: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Action required"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Follow the next steps to restore this app"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> is disabled"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"To restore this app, enable <xliff:g id="INSTALLERNAME">%1$s</xliff:g> in Settings"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> is uninstalled"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"To restore this app, you\'ll need to install <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Continue"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Clear storage"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Settings"</string>
+    <string name="close" msgid="5214897374055647996">"Close"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-en-rXC/strings.xml b/packages/PackageInstaller/res/values-en-rXC/strings.xml
index 67ffce5..5753a35 100644
--- a/packages/PackageInstaller/res/values-en-rXC/strings.xml
+++ b/packages/PackageInstaller/res/values-en-rXC/strings.xml
@@ -44,6 +44,7 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‎‎‎‎‏‏‎‎‎‏‎‎‎‏‎‎‎‏‎‎‏‏‎‏‏‎‎‎‎‎‏‏‎‏‏‏‎‎‏‏‎‎‏‏‏‏‎‏‏‏‏‏‏‏‎‎‎‎Unknown apps can\'t be installed by this user‎‏‎‎‏‎"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‏‏‏‏‎‎‏‎‎‏‏‏‏‏‎‎‎‎‏‎‏‏‏‎‎‎‏‎‎‎‏‏‎‏‏‏‏‎‏‎‎‏‏‏‎‎‏‎‏‎‏‏‎‎‏‏‎‎This user is not allowed to install apps‎‏‎‎‏‎"</string>
     <string name="ok" msgid="7871959885003339302">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‏‏‏‏‏‎‏‏‎‏‎‎‎‏‏‏‎‎‏‏‏‎‏‏‎‏‎‏‏‏‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‎‎‏‏‎‎OK‎‏‎‎‏‎"</string>
+    <string name="archive" msgid="4447791830199354721">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‏‎‏‏‏‎‎‏‏‎‏‏‏‎‏‏‎‎‎‏‏‎‏‎‏‎‏‎‏‎‎‏‏‏‏‎‏‎‏‎‏‏‎‎‎‏‎‏‎‏‏‎‎‎‎‏‎Archive‎‏‎‎‏‎"</string>
     <string name="update_anyway" msgid="8792432341346261969">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‎‏‎‎‏‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‎‏‎‏‎‎‎‏‏‎‎‏‏‎‎‏‏‎‎‏‏‎‏‏‏‏‎‏‎‎‎‏‎Update anyway‎‏‎‎‏‎"</string>
     <string name="manage_applications" msgid="5400164782453975580">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‏‏‏‎‎‎‏‎‎‏‏‏‏‎‏‎‏‎‎‎‎‏‎‎‎‏‎‎‎‏‎‏‎‏‏‏‏‏‎‎‏‏‎‏‎‏‎‎‎‎‏‏‏‎‎‎Manage apps‎‏‎‎‏‎"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‎‏‏‏‏‏‎‎‎‎‏‏‏‏‎‎‎‏‎‏‏‎‏‏‎‎‏‏‏‎‎‎‎‎‎‏‎‎‎‎‏‎‎‎‎‎‎‎‏‏‏‏‎‎Out of space‎‏‎‎‏‎"</string>
@@ -58,6 +59,11 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‎‏‏‏‎‎‎‎‏‏‏‎‎‏‏‎‎‎‏‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‎‎‏‏‏‎‎‏‎‏‎‎‎‎‏‏‎‏‏‏‎Uninstall update‎‏‎‎‏‎"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‏‏‎‎‎‎‏‎‎‏‎‏‎‎‏‎‏‏‎‏‎‏‏‏‎‎‏‎‎‎‎‏‎‏‎‎‎‏‏‏‎‏‏‏‎‏‎‎‎‎‎‏‎‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is part of the following app:‎‏‎‎‏‎"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‏‏‏‏‏‎‎‎‎‎‎‏‏‎‏‏‎‏‎‏‎‏‏‎‏‏‎‎‎‏‏‎‎‏‏‎‎‏‎‏‎‎‎‎‏‏‎‎‏‏‏‎‏‏‎‎‎Do you want to uninstall this app?‎‏‎‎‏‎"</string>
+    <string name="archive_application_text" msgid="8482325710714386348">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‏‎‏‏‏‎‏‎‎‎‏‏‎‎‏‎‎‏‎‏‎‏‏‏‎‏‎‎‎‎‏‎‎‏‎‏‏‎‎‏‏‎‏‏‏‏‎‏‎‏‏‎‎‎Your personal data will be saved‎‏‎‎‏‎"</string>
+    <string name="archive_application_text_all_users" msgid="3151229641681672580">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‏‏‎‏‏‎‏‏‎‏‎‏‎‏‎‏‎‏‎‎‏‏‏‎‎‎‏‏‎‎‎‎‏‏‏‏‎‎‎‎‏‏‎‎‏‏‎‎‎‎‏‎‎‎Archive this app for all users? Your personal data will be saved‎‏‎‎‏‎"</string>
+    <string name="archive_application_text_current_user_work_profile" msgid="1450487362134779752">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‎‎‏‎‎‎‎‏‎‎‏‎‏‎‏‎‏‎‎‏‎‎‏‎‎‎‏‎‎‎‏‏‎‎‏‏‏‏‎‎‏‎‏‎‎‏‏‏‎‏‏‎‏‎‎‎‎Archive this app on your work profile? Your personal data will be saved‎‏‎‎‏‎"</string>
+    <string name="archive_application_text_user" msgid="2586558895535581451">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‏‏‏‏‎‎‏‎‏‎‏‎‎‏‏‎‏‏‎‎‏‏‏‎‎‎‏‏‏‏‏‏‏‎‎‎‎‎‏‏‎‎‏‏‎‏‎‎‏‎‎‎‎‏‎‏‏‎Archive this app for ‎‏‎‎‏‏‎<xliff:g id="USERNAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎? Your personal data will be saved‎‏‎‎‏‎"</string>
+    <string name="archive_application_text_current_user_private_profile" msgid="1958423158655599132">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‏‎‎‏‎‏‏‎‏‏‎‏‏‎‏‏‏‎‏‏‏‏‏‎‎‏‎‎‏‎‎‏‏‏‎‎‏‎‎‎‎‏‏‎‎‎‎‏‎‎‎‎‏‏‏‎‎‎Do you want to archive this app from your private space? Your personal data will be saved‎‏‎‎‏‎"</string>
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‏‏‎‏‎‏‏‏‎‎‎‎‎‏‏‏‏‏‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‏‎‎‎‏‎‏‏‏‏‎Do you want to uninstall this app for ‎‏‎‎‏‏‎"<b>"‎‏‎‎‏‏‏‎all‎‏‎‎‏‏‎"</b>"‎‏‎‎‏‏‏‎ users? The application and its data will be removed from ‎‏‎‎‏‏‎"<b>"‎‏‎‎‏‏‏‎all‎‏‎‎‏‏‎"</b>"‎‏‎‎‏‏‏‎ users on the device.‎‏‎‎‏‎"</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‎‏‏‏‎‏‎‎‏‏‎‎‎‎‎‏‎‎‏‏‏‏‏‏‎‏‎‏‎‎‎‎‎‏‎‏‎‎‏‏‎‏‎‏‏‎‏‎‏‎‎‎‎‏‏‏‎‎Do you want to uninstall this app for the user ‎‏‎‎‏‏‎<xliff:g id="USERNAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‎‏‏‎‏‎‏‎‎‎‎‎‎‎‎‏‎‏‎‏‏‏‏‏‎‏‎‎‏‏‎‏‎‎‏‏‏‎‎‏‎‏‎‏‏‏‏‏‎‎‎‏‎Do you want to uninstall this app from your work profile?‎‏‎‎‏‎"</string>
@@ -66,6 +72,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‏‎‏‏‎‏‎‏‏‏‎‎‏‏‎‎‏‎‎‎‏‎‎‏‏‏‎‏‎‏‎‏‎‏‎‎‏‏‏‎‏‎‎‏‎‎‏‎‏‏‏‏‏‎‎Keep ‎‏‎‎‏‏‎<xliff:g id="SIZE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ of app data.‎‏‎‎‏‎"</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‏‎‎‏‎‏‏‏‎‎‎‏‏‏‏‏‎‎‎‎‏‏‎‏‏‏‎‏‎‏‎‎‎‏‏‏‎‏‎‏‎‏‎‏‎‏‎‏‎‏‏‏‎‏‎‎‎Do you want to delete this app?‎‏‎‎‏‎"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‏‎‏‎‎‎‏‎‎‎‎‎‏‏‎‎‎‏‎‎‏‎‎‎‏‎‏‎‏‏‎‏‎‏‏‎‎‎Do you want to uninstall this app? ‎‏‎‎‏‏‎<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ clone will also be deleted.‎‏‎‎‏‎"</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‎‎‎‎‏‎‎‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‏‎‎‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‏‏‏‎‎‏‏‎‏‏‎‎‏‎‎Do you want to uninstall this app from your private space?‎‏‎‎‏‎"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‏‎‏‎‏‎‎‎‏‏‎‏‎‎‏‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‏‏‎‎‏‏‏‏‏‎‏‏‏‎‏‏‎‏‏‎‏‏‏‎‏‎Running uninstalls‎‏‎‎‏‎"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‏‏‎‎‎‏‎‏‎‏‎‏‎‎‏‏‎‎‎‏‏‏‎‏‎‏‏‎‏‎‎‏‎‏‎‏‏‎‎‏‏‏‏‎‏‏‏‎‎‎‎‎‏‏‎‎‎Failed uninstalls‎‏‎‎‏‎"</string>
     <string name="uninstalling" msgid="8709566347688966845">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‏‏‏‎‏‎‎‏‏‎‎‎‎‏‏‏‎‎‏‎‏‎‏‎‏‏‎‏‏‎‏‏‎‎‏‎‎‏‏‏‏‎‏‎‏‎‏‏‏‏‎‏‎Uninstalling…‎‏‎‎‏‎"</string>
@@ -85,8 +92,6 @@
     <string name="manage_users" msgid="1243995386982560813">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‎‏‎‎‎‎‏‏‏‎‎‎‏‏‏‏‎‎‏‏‎‏‏‎‏‎‏‎‎‏‏‏‎‏‎‏‎‎‎‏‏‏‏‏‎‏‎‎‎‎‏‎‏‏‎‏‎Manage users‎‏‎‎‏‎"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‎‎‎‏‏‎‏‎‏‎‏‎‏‏‎‎‏‏‏‏‎‎‏‎‎‏‏‏‏‎‏‎‎‎‎‏‎‎‎‎‎‏‎‎‏‏‎‏‏‎‏‎‎‏‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ couldn\'t be uninstalled.‎‏‎‎‏‎"</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‎‎‎‎‏‏‏‎‎‏‏‏‏‏‏‎‎‎‏‎‎‎‏‎‏‏‏‎‏‏‏‏‏‏‎‎‎‏‏‏‎‎‎‎‎‎‏‏‏‎‏‏‎‏‎‏‎There was a problem parsing the package.‎‏‎‎‏‎"</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‏‏‏‏‎‎‎‎‎‎‎‏‏‏‏‎‎‏‏‏‏‏‏‏‎‏‏‎‏‎‎‎‏‎‎‏‎‏‏‏‎‏‏‎‏‎‎‏‏‎‏‎Android Wear‎‏‎‎‏‎"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‏‏‎‎‎‏‏‏‎‏‎‎‏‏‎‎‎‎‎‏‎‏‎‏‎‏‏‎‏‎‎‏‎‏‎‎‎‏‎‏‎‎‏‏‎‏‎‎‎‏‏‎‎‏‎‏‎Install/Uninstall actions not supported on Wear.‎‏‎‎‏‎"</string>
     <string name="message_staging" msgid="8032722385658438567">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‏‏‎‎‏‏‏‏‏‎‏‏‎‎‏‏‏‎‎‏‏‎‏‎‏‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‏‎‎‏‏‏‎Staging app…‎‏‎‎‏‎"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‎‎‏‏‏‎‎‎‏‏‎‎‎‎‏‏‏‎‏‏‏‎‏‎‎‏‎‏‏‎‏‏‏‏‎‏‎‏‏‎‎Unknown‎‏‎‎‏‎"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‎‏‎‏‎‎‏‏‎‏‎‏‏‎‏‏‏‏‎‎‎‏‎‏‏‎‎‎‎‎‎‏‎‏‏‎‏‎‎‎‏‎‎‎‏‎‏‎‏‎‎‏‏‏‎For your security, your tablet currently isn’t allowed to install unknown apps from this source. You can change this in Settings.‎‏‎‎‏‎"</string>
@@ -97,6 +102,7 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‏‎‏‎‏‎‏‎‏‎‎‎‎‎‎‎‎‎‎‎‏‏‎‏‏‏‏‏‎‎‎‎‎‎‎‎‎‏‏‏‎‎‏‏‏‎‎‏‎‏‎‏‏‏‎‎‎Your tablet and personal data are more vulnerable to attack by unknown apps. By installing this app, you agree that you are responsible for any damage to your tablet or loss of data that may result from its use.‎‏‎‎‏‎"</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‎‏‏‎‏‎‏‎‏‎‏‏‏‎‎‏‎‎‏‏‏‎‎‏‎‏‎‎‎‏‏‎‎‏‏‏‎‎‏‎‎‏‏‎‏‎‎‎‏‏‏‎‏‏‎‎Your TV and personal data are more vulnerable to attack by unknown apps. By installing this app, you agree that you are responsible for any damage to your TV or loss of data that may result from its use.‎‏‎‎‏‎"</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‎‎‎‏‎‎‎‏‏‎‎‎‎‎‎‎‏‏‏‎‎‏‏‏‎‎‏‏‎‎‏‎‎‏‏‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‎‎‎‏‎‎‏‏‎<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ Clone‎‏‎‎‏‎"</string>
+    <string name="archiving_app_label" msgid="1127085259724124725">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‏‎‏‎‎‏‎‎‎‎‏‏‎‏‏‎‎‎‎‏‎‎‏‎‎‏‏‏‏‎‎‏‎‏‏‎‏‏‏‏‎‏‏‏‎‎‏‎‎‎‏‏‎‏‎‏‎Archive ‎‏‎‎‏‏‎<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
     <string name="anonymous_source_continue" msgid="4375745439457209366">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‏‏‏‎‎‏‏‏‎‎‎‏‎‏‎‏‎‎‏‎‏‏‎‎‏‎‎‎‏‎‎‏‏‎‎‎‎‏‏‏‏‎‏‏‎‎‎‎‎‏‎‏‏‎‎Continue‎‏‎‎‏‎"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‎‎‎‏‎‏‎‎‏‏‎‏‏‎‏‎‎‏‎‏‏‎‎‎‏‎‎‏‎‎‎‏‏‏‏‎‎‏‎‎‏‎‏‏‎‎‏‏‎‎‎‎‎‏‏‏‏‎Settings‎‏‎‎‏‎"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‏‎‎‏‏‎‏‏‎‎‎‏‏‎‎‏‎‎‎‎‎‎‎‏‎‏‎‏‎‎‏‎‏‎‎‏‎‏‏‏‏‏‎‎‎‎‏‎‎‏‎‎‎‏‎‏‎‎Installing/uninstalling wear apps‎‏‎‎‏‎"</string>
@@ -106,4 +112,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‎‎‎‏‎‏‏‏‏‎‏‏‏‏‏‏‏‎‎‏‏‎‎‎‏‏‎‎‏‏‎‏‏‏‎‎‏‎‏‎‏‎‎‎‎‎‎‎‏‏‎‏‎Restore ‎‏‎‎‏‏‎<xliff:g id="APPNAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ from ‎‏‎‎‏‏‎<xliff:g id="INSTALLERNAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‎‏‎‎‏‎‎‎‏‏‏‏‏‎‏‎‏‏‏‎‏‏‎‏‎‎‎‎‎‎‏‏‎‎‎‏‏‏‎‏‎‏‎‎‎‏‎‏‎‎‏‎‎‎This app will begin to download in the background‎‏‎‎‏‎"</string>
     <string name="restore" msgid="8460854736328970444">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‏‎‏‎‏‏‏‏‏‏‏‎‏‎‎‎‏‏‏‎‎‎‎‏‏‏‏‏‎‎‎‏‎‎‎‏‏‏‎‏‎‎‎‎‏‏‎‎‏‏‎‎‎Restore‎‏‎‎‏‎"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‎‏‎‎‎‎‎‏‎‎‎‎‎‎‎‏‏‏‎‎‎‏‏‏‎‎‎‎‎‏‏‎‎‏‏‏‎‏‏‏‎‎‏‎‏‎‎‎‎‎‏‏‎‏‎You\'re offline‎‏‎‎‏‎"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‏‏‎‎‎‏‏‎‎‎‏‏‏‏‏‎‏‎‏‎‎‎‎‎‏‏‏‎‏‎‎‏‏‎‎‎‎‎‎‏‎‎‏‏‎‏‎‏‎‎‏‎‏‎‎‏‏‎This app will automatically restore when you\'re connected to the internet‎‏‎‎‏‎"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‎‏‏‎‏‏‏‎‎‏‏‎‏‏‎‎‎‎‎‎‏‎‏‎‏‏‎‎‎‏‎‎‏‏‏‏‏‎‎‎‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎Something went wrong‎‏‎‎‏‎"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‎‎‎‏‎‎‎‏‎‏‎‎‏‏‏‏‎‏‎‏‏‏‎‎‏‏‎‎‎‎‎‏‏‏‎‎‏‏‏‎‎‏‏‎‎‏‏‏‎‏‎‏‏‏‎There was a problem trying to restore this app‎‏‎‎‏‎"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‎‎‎‎‎‏‎‎‏‎‏‏‎‏‎‏‏‏‏‏‎‎‏‏‎‎‎‎‎‎‎‎‏‎‏‎‏‏‎‏‎‎‎‏‎‏‎‏‏‎‏‎‏‏‎‎Not enough storage‎‏‎‎‏‎"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‏‏‎‎‏‎‎‎‎‏‏‎‏‎‎‏‏‎‎‎‎‎‏‏‏‎‏‎‏‏‎‏‎‏‎‎‏‏‎‎‎‏‏‎‎‏‏‏‎‏‏‎‎‎To restore this app, you can free up space on this device. Storage required: ‎‏‎‎‏‏‎<xliff:g id="BYTES">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‏‏‎‏‎‏‎‎‏‎‏‏‏‎‎‎‏‏‎‎‏‎‎‎‎‏‏‎‏‏‏‏‎‎‏‎‎‏‎‏‏‎Action required‎‏‎‎‏‎"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‎‏‎‎‏‏‏‎‏‎‎‎‏‎‏‎‎‎‎‏‏‏‏‎‎‎‎‏‏‏‎‎‎‏‎‎‏‎‎‏‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎Follow the next steps to restore this app‎‏‎‎‏‎"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‏‎‏‎‏‎‎‏‏‎‏‏‎‏‏‏‏‎‏‎‏‏‎‏‏‎‎‎‎‏‏‎‏‏‏‏‎‏‎‏‎‏‏‎‎‏‏‏‎‎‎‎‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="INSTALLERNAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is disabled‎‏‎‎‏‎"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‏‏‎‎‏‏‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‏‏‏‏‎‎‎‎‎‎‏‎‎‎‎‏‎‎‎‏‏‎‎‎‏‎‎‏‎‎‎‏‎To restore this app, enable ‎‏‎‎‏‏‎<xliff:g id="INSTALLERNAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ in Settings‎‏‎‎‏‎"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‎‎‎‎‎‏‎‎‏‏‎‏‎‏‎‎‎‎‏‏‎‎‏‏‏‏‏‎‎‎‎‏‏‏‎‏‎‏‎‎‏‎‏‎‏‎‎‏‎‏‎‏‏‎‎‏‎‎‏‎‎‏‏‎<xliff:g id="INSTALLERNAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is uninstalled‎‏‎‎‏‎"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‎‎‎‏‏‏‎‎‎‏‎‏‏‏‏‎‎‎‏‎‎‏‏‎‏‏‎‎‎‏‎‎‏‏‎‎‏‎‎‎‎‎‏‎‏‏‏‎‏‎‏‎‎‏‎‎‎To restore this app, you\'ll need to install ‎‏‎‎‏‏‎<xliff:g id="INSTALLERNAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‎‎‎‎‏‎‎‏‎‎‎‏‎‎‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‏‏‎‏‏‏‎‎‎‎‎‏‎Continue‎‏‎‎‏‎"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‏‎‎‎‎‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‎‏‏‏‎‎‏‎‏‏‏‎‏‎‏‎‏‎‎‎‏‏‎‏‎‏‎‎‎‎Clear storage‎‏‎‎‏‎"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‎‏‎‎‎‎‏‎‏‎‏‎‎‎‏‏‎‏‎‎‏‏‎‎‏‎‏‏‎‏‏‎‏‎‎‏‏‎‏‎‏‏‎‏‎‎‏‎‏‎‏‎‎‎‏‎Settings‎‏‎‎‏‎"</string>
+    <string name="close" msgid="5214897374055647996">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‏‎‏‏‏‏‏‎‎‎‎‏‎‎‏‏‎‎‎‏‎‎‎‎‎‏‏‎‎‎‎‏‎‏‏‎‏‎‎‎‏‎‎‏‎‏‎‏‏‏‏‏‏‎‎‎Close‎‏‎‎‏‎"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-es-rUS/strings.xml b/packages/PackageInstaller/res/values-es-rUS/strings.xml
index 2a8559a..b66976a 100644
--- a/packages/PackageInstaller/res/values-es-rUS/strings.xml
+++ b/packages/PackageInstaller/res/values-es-rUS/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Este usuario no puede instalar apps desconocidas"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Este usuario no puede instalar apps"</string>
     <string name="ok" msgid="7871959885003339302">"Aceptar"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Actualizar de todas formas"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Gestionar apps"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Sin espacio"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Desinstalar actualización"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> es parte de la siguiente app:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"¿Quieres desinstalar esta app?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"¿Quieres desinstalar esta app para "<b>"todos"</b>" los usuarios? Se quitarán la aplicación y sus datos de "<b>"todos"</b>" los usuarios del dispositivo."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"¿Quieres desinstalar esta app para el usuario <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"¿Deseas desinstalar esta app de tu perfil de trabajo?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Guardar <xliff:g id="SIZE">%1$s</xliff:g> en datos de apps"</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"¿Quieres borrar esta app?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"¿Quieres desinstalar esta app? También se borrará el clon de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"¿Quieres desinstalar esta app de tu espacio privado?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Desinstalaciones activas"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Desinstalaciones con errores"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Desinstalando…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Administrar usuarios"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"No se pudo desinstalar <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Se produjo un error durante el análisis del paquete."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Wear no admite las acciones de instalación y desinstalación"</string>
     <string name="message_staging" msgid="8032722385658438567">"Preparando app…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Desconocido"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Por tu seguridad, la tablet no tiene permitido actualmente instalar apps desconocidas de esta fuente. Puedes modificar esta opción en Configuración."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"La tablet y tus datos personales son más vulnerables a los ataques de apps desconocidas. Si instalas esta app, serás responsable de los daños que sufra la tablet y de la pérdida de datos que pueda ocasionar su uso."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"La TV y tus datos personales son más vulnerables a los ataques de apps desconocidas. Si instalas esta app, serás responsable de los daños que sufra la TV y de la pérdida de datos que pueda ocasionar su uso."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Clon de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Continuar"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Configuración"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Instalando/desinstalando apps para Wear"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"¿Quieres restablecer <xliff:g id="APPNAME">%1$s</xliff:g> desde <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Esta app comenzará la descarga en segundo plano"</string>
     <string name="restore" msgid="8460854736328970444">"Restablecer"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"No tienes conexión"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Se restablecerá automáticamente esta app cuando te conectes a Internet"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Se produjo un error"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Hubo un problema al intentar restablecer esta app"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"No hay suficiente espacio de almacenamiento"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Para restablecer la app, deberás liberar espacio en este dispositivo. Almacenamiento requerido: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Acción obligatoria"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Sigue los próximos pasos para restablecer esta app"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"Se inhabilitó <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Para restablecer esta app, habilita <xliff:g id="INSTALLERNAME">%1$s</xliff:g> en Configuración"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"No se instaló <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Para restablecer esta app, deberás instalar <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Continuar"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Liberar almacenamiento"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Configuración"</string>
+    <string name="close" msgid="5214897374055647996">"Cerrar"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-es/strings.xml b/packages/PackageInstaller/res/values-es/strings.xml
index 5e1022b..2a0d063 100644
--- a/packages/PackageInstaller/res/values-es/strings.xml
+++ b/packages/PackageInstaller/res/values-es/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Este usuario no puede instalar aplicaciones desconocidas"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Este usuario no tiene permiso para instalar aplicaciones"</string>
     <string name="ok" msgid="7871959885003339302">"Aceptar"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Actualizar igualmente"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Gestionar aplicaciones"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Sin espacio"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Desinstalar actualización"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> forma parte de esta aplicación:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"¿Quieres desinstalar esta aplicación?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"¿Quieres desinstalar esta aplicación para "<b>"todos"</b>" los usuarios? La aplicación y sus datos se borrarán de "<b>"todos"</b>" los usuarios del dispositivo."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"¿Quieres desinstalar esta aplicación para el usuario <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"¿Quieres desinstalar esta aplicación de tu perfil de trabajo?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Mantener <xliff:g id="SIZE">%1$s</xliff:g> de datos de aplicaciones."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"¿Quieres eliminar esta aplicación?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"¿Quieres desinstalar esta aplicación? El clon de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> también se eliminará."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"¿Quieres desinstalar esta aplicación de tu espacio privado?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Desinstalaciones en curso"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Desinstalaciones fallidas"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Desinstalando…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Gestionar usuarios"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"No se ha podido desinstalar <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"No se ha podido analizar el paquete."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Las acciones de instalar y desinstalar no pueden realizarse en Wear."</string>
     <string name="message_staging" msgid="8032722385658438567">"Preparando aplicación…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Desconocida"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Por tu seguridad, de momento tu tablet no puede instalar aplicaciones desconocidas de esta fuente. Puedes cambiarlo en Ajustes."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Tu tablet y tus datos personales son más vulnerables a los ataques de aplicaciones desconocidas. Al instalar esta aplicación, aceptas ser responsable de cualquier daño que sufra tu tablet o la pérdida de datos que se pueda derivar de su uso."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Tu TV y tus datos personales son más vulnerables a los ataques de aplicaciones desconocidas. Al instalar esta aplicación, aceptas ser responsable de cualquier daño que sufra tu TV o la pérdida de datos que se pueda derivar de su uso."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Clon de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Continuar"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Ajustes"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Instalando/desinstalando apps para Wear"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"¿Restaurar <xliff:g id="APPNAME">%1$s</xliff:g> de <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Esta aplicación comenzará a descargarse en segundo plano"</string>
     <string name="restore" msgid="8460854736328970444">"Restaurar"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"No tienes conexión a Internet"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Esta aplicación se restaurará automáticamente cuando tengas conexión a Internet"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Se ha producido un error"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"No se ha podido restaurar esta aplicación"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"No hay suficiente espacio"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Para restaurar esta aplicación, libera espacio del dispositivo. Almacenamiento necesario: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Acción necesaria"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Sigue los pasos que se indican a continuación para restaurar esta aplicación"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> está inhabilitada"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Para restaurar esta aplicación, habilita <xliff:g id="INSTALLERNAME">%1$s</xliff:g> en Ajustes"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> está desinstalada"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Para restaurar esta aplicación, tendrás que instalar <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Continuar"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Borrar almacenamiento"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Ajustes"</string>
+    <string name="close" msgid="5214897374055647996">"Cerrar"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-et/strings.xml b/packages/PackageInstaller/res/values-et/strings.xml
index 2bd2c04..5d5914e 100644
--- a/packages/PackageInstaller/res/values-et/strings.xml
+++ b/packages/PackageInstaller/res/values-et/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"See kasutaja ei saa installida tundmatuid rakendusi"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Kasutajal ei ole lubatud rakendusi installida"</string>
     <string name="ok" msgid="7871959885003339302">"OK"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Värskenda ikkagi"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Rakend. haldam."</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Pole ruumi"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Värskenduse desinstallimine"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> on osa järgmisest rakendusest:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Kas soovite selle rakenduse desinstallida?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Kas soovite selle rakenduse "<b>"kõikide"</b>" kasutajate kontodelt desinstallida? Rakendus ja selle andmed eemaldatakse "<b>"kõikide"</b>" seadme kasutajate kontodelt."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Kas soovite selle rakenduse kasutaja <xliff:g id="USERNAME">%1$s</xliff:g> kontolt desinstallida?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Kas soovite selle rakenduse oma tööprofiililt desinstallida?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Säilita rakenduse andmete hulk <xliff:g id="SIZE">%1$s</xliff:g>."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Kas soovite selle rakenduse kustutada?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Kas soovite selle rakenduse desinstallida? Rakenduse <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> kloon kustutatakse samuti."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Kas soovite selle rakenduse oma privaatsest ruumist desinstallida?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Käimasolevad desinstallimised"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Ebaõnnestunud desinstallimised"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Desinstallimine …"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Halda kasutajaid"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"Rakendust <xliff:g id="APP_NAME">%1$s</xliff:g> ei saanud desinstallida."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Probleem paketi sõelumisel."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Wear ei toeta installimist/desinstallimist."</string>
     <string name="message_staging" msgid="8032722385658438567">"Rakenduse koondamine …"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Teadmata"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Teie turvalisuse huvides ei ole tahvelarvutil praegu lubatud installida sellest allikast tundmatuid rakendusi. Saate seda seadetes muuta."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Teie tahvelarvuti ja isiklikud andmed on tundmatute rakenduste rünnakute suhtes haavatavamad. Selle rakenduse installimisel nõustute, et vastutate tahvelarvuti kahjude ja andmekao eest, mis võivad tuleneda selliste rakenduste kasutamisest."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Teie teler ja isiklikud andmed on tundmatute rakenduste rünnakute suhtes haavatavamad. Selle rakenduse installimisel nõustute, et vastutate teleri kahjude ja andmekao eest, mis võivad tuleneda selliste rakenduste kasutamisest."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Rakenduse <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> kloon"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Jätka"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Seaded"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Weari rak. installimine/desinstallimine"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Kas taastada rakendus <xliff:g id="APPNAME">%1$s</xliff:g> rakenduse <xliff:g id="INSTALLERNAME">%1$s</xliff:g> kaudu?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Selle rakenduse allalaadimine algab taustal"</string>
     <string name="restore" msgid="8460854736328970444">"Taasta"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Võrguühendus puudub"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"See rakendus taastatakse automaatselt, kui olete Internetiga ühendatud"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Midagi läks valesti"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Selle rakenduse taastamisel ilmnes probleem"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Pole piisavalt salvestusruumi"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Selle rakenduse taastamiseks saate selles seadmes ruumi vabastada. Vajalik salvestusruum: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Toiming on vajalik"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Selle rakenduse taastamiseks järgige järgmisi samme"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> on keelatud"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Selle rakenduse taastamiseks lubage seadetes <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> on desinstallitud"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Selle rakenduse taastamiseks peate installima: <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Jätka"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Tühjenda salvestusruum"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Seaded"</string>
+    <string name="close" msgid="5214897374055647996">"Sule"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-eu/strings.xml b/packages/PackageInstaller/res/values-eu/strings.xml
index 574d4ab..af25e52 100644
--- a/packages/PackageInstaller/res/values-eu/strings.xml
+++ b/packages/PackageInstaller/res/values-eu/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Erabiltzaile honek ezin ditu instalatu aplikazio ezezagunak"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Erabiltzaile honek ez du baimenik aplikazioak instalatzeko"</string>
     <string name="ok" msgid="7871959885003339302">"Ados"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Eguneratu halere"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Kudeatu aplikazioak"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Ez dago behar adina toki"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Desinstalatu eguneratzea"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> aplikazio honen zati da:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Aplikazioa desinstalatu nahi duzu?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Erabiltzaile "<b>"guztiei"</b>" desinstalatu nahi diezu aplikazioa? Aplikazioa eta haren datu guztiak ezabatuko zaizkie gailuko erabiltzaile "<b>"guztiei"</b>"."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"<xliff:g id="USERNAME">%1$s</xliff:g> erabiltzaileari desinstalatu nahi diozu aplikazioa?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Aplikazioa laneko profiletik desinstalatu nahi duzu?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Mantendu aplikazioetako datuen <xliff:g id="SIZE">%1$s</xliff:g>."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Aplikazioa ezabatu nahi duzu?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Aplikazioa desinstalatu nahi duzu? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> aplikazioaren klona ere ezabatuko da."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Aplikazioa eremu pribatutik desinstalatu nahi duzu?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Abian diren desinstalatze-eragiketak"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Desinstalatu ezin izan direnak"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Desinstalatzen…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Kudeatu erabiltzaileak"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"Ezin izan da desinstalatu <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Arazo bat izan da paketea analizatzean."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Ezin dira gauzatu instalatzeko eta desinstalatzeko ekintzak Wear gailuetan."</string>
     <string name="message_staging" msgid="8032722385658438567">"Aplikazioa prestatzen…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Ezezaguna"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Segurtasuna bermatzeko, ezin dira instalatu iturburu honetako aplikazio ezezagunak tableta honetan. Hori aldatzeko, joan Ezarpenak atalera."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Baliteke tabletak eta datu pertsonalek aplikazio ezezagunen erasoak jasatea. Aplikazio hau instalatzen baduzu, onartu egingo duzu hura erabiltzeagatik tabletari agian gertatuko zaizkion kalteen edo datu-galeren erantzulea zeu izango zarela."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Baliteke telebistak eta datu pertsonalek aplikazio ezezagunen erasoak jasatea. Aplikazio hau instalatzen baduzu, onartu egingo duzu hura erabiltzeagatik telebistari agian gertatuko zaizkion kalteen edo datu-galeren erantzulea zeu izango zarela."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> aplikazioaren klona"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Egin aurrera"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Ezarpenak"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Wear aplikazioak instalatzea/desinstalatzea"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> aplikaziotik leheneratu nahi duzu <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Atzeko planoan deskargatuko da aplikazioa"</string>
     <string name="restore" msgid="8460854736328970444">"Leheneratu"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Ez zaude konektatuta Internetera"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Aplikazioa automatikoki leheneratuko da Internetera konektatzen zarenean"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Arazoren bat izan da"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Arazo bat izan da aplikazioa leheneratzean"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Ez dago behar adina toki"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Aplikazioa leheneratzeko, egin tokia gailuan. Behar den tokia: <xliff:g id="BYTES">%1$s</xliff:g>."</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Zerbait egin behar duzu"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Aplikazioa leheneratzeko, egin hurrengo urratsak"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> desgaituta dago"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Aplikazioa leheneratzeko, gaitu <xliff:g id="INSTALLERNAME">%1$s</xliff:g> ezarpenetan"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> ez dago instalatuta"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Aplikazioa leheneratzeko, <xliff:g id="INSTALLERNAME">%1$s</xliff:g> instalatu beharko duzu"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Egin aurrera"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Egin tokia"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Ezarpenak"</string>
+    <string name="close" msgid="5214897374055647996">"Itxi"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-fa/strings.xml b/packages/PackageInstaller/res/values-fa/strings.xml
index 1869cb6..a7dc36a 100644
--- a/packages/PackageInstaller/res/values-fa/strings.xml
+++ b/packages/PackageInstaller/res/values-fa/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"این کاربر نمی‌تواند برنامه‌های ناشناس نصب کند"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"این کاربر مجاز به نصب برنامه‌ نیست"</string>
     <string name="ok" msgid="7871959885003339302">"بسیار خوب"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"درهرصورت به‌روز شود"</string>
     <string name="manage_applications" msgid="5400164782453975580">"مدیریت برنامه‌ها"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"فضا کافی نیست"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"حذف نصب به‌روزرسانی"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> قسمتی از برنامه زیر است:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"می‌خواهید این برنامه را حذف نصب کنید؟"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"آیا می‌خواهید این برنامه را برای "<b>"همه"</b>" کاربران حذف کنید؟ این برنامه و داده‌های آن برای "<b>"همه"</b>" کاربران این دستگاه حذف خواهد شد."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"آیا می‌خواهید این برنامه را برای این کاربر <xliff:g id="USERNAME">%1$s</xliff:g> حذف نصب کنید؟"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"می‌خواهید این برنامه را از نمایه کاری‌تان حذف نصب کنید؟"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"<xliff:g id="SIZE">%1$s</xliff:g> از داده‌های برنامه را نگه‌دارید."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"می‌خواهید این برنامه را حذف کنید؟"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"می‌خواهید این برنامه را حذف نصب کنید؟ همسانه <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> هم حذف خواهد شد."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"می‌خواهید این برنامه از فضای خصوصی حذف نصب شود؟"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"حذف‌نصب‌های درحال انجام"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"حذف‌نصب‌های ناموفق"</string>
     <string name="uninstalling" msgid="8709566347688966845">"درحال حذف نصب..."</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"مدیریت کاربران"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> حذف نصب نشد."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"مشکلی در تجزیه این بسته وجود داشت."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"‏کنش‌های نصب/حذف نصب در Wear پشتیبانی نمی‌شود."</string>
     <string name="message_staging" msgid="8032722385658438567">"مرحله‌بندی برنامه…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"نامشخص"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"برای امنیت شما، درحال‌حاضر رایانه لوحی‌تان اجازه ندارد برنامه‌های ناشناس را از این منبع نصب کنید. می‌توانید آن را در «تنظیمات» تغییر دهید."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"رایانه لوحی و داده‌های شخصی‌تان دربرابر حمله برنامه‌های ناشناس آسیب‌پذیرتر هستند. با نصب این برنامه، موافقت می‌کنید که مسئول هرگونه آسیب به رایانه لوحی یا از دست رفتن داده‌ای هستید که ممکن است درنتیجه استفاده از آن به وجود آید."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"تلویزیون و داده‌های شخصی‌تان دربرابر حمله برنامه‌های ناشناس آسیب‌پذیرتر هستند. با نصب این برنامه، موافقت می‌کنید که مسئول هرگونه آسیب به تلویزیون یا از دست رفتن داده‌ای هستید که ممکن است درنتیجه استفاده از آن به وجود آید."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"همسانه <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"ادامه"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"تنظیمات"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"نصب/حذف نصب برنامه‌های پوشیدنی"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"<xliff:g id="APPNAME">%1$s</xliff:g> از <xliff:g id="INSTALLERNAME">%1$s</xliff:g> بازیابی شود؟"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"این برنامه در پس‌زمینه شروع به بارگیری می‌کند"</string>
     <string name="restore" msgid="8460854736328970444">"بازیابی"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"آفلاین هستید"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"وقتی به اینترنت متصل شوید، این برنامه به‌طور خودکار بازیابی خواهد شد"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"مشکلی پیش آمد"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"هنگام بازیابی این برنامه مشکلی پیش آمد"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"فضای ذخیره‌سازی کافی نیست"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"برای بازیابی این برنامه، می‌توانید فضای این دستگاه را آزاد کنید. فضای ذخیره‌سازی لازم: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"اقدام لازم است"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"برای بازیابی این برنامه، مراحل بعدی را دنبال کنید"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> غیرفعال است"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"برای بازیابی این برنامه، <xliff:g id="INSTALLERNAME">%1$s</xliff:g> را در «تنظیمات» فعال کنید"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> حذف نصب شده است"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"برای بازیابی این برنامه، باید <xliff:g id="INSTALLERNAME">%1$s</xliff:g> را نصب کنید"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"ادامه دادن"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"پاک کردن فضای ذخیره‌سازی"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"تنظیمات"</string>
+    <string name="close" msgid="5214897374055647996">"بستن"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-fi/strings.xml b/packages/PackageInstaller/res/values-fi/strings.xml
index 8f960ea..3ef9807 100644
--- a/packages/PackageInstaller/res/values-fi/strings.xml
+++ b/packages/PackageInstaller/res/values-fi/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Tämä käyttäjä ei voi asentaa tuntemattomia sovelluksia."</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Tämä käyttäjä ei voi asentaa sovelluksia."</string>
     <string name="ok" msgid="7871959885003339302">"OK"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Päivitä silti"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Sovellusvalinnat"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Tallennustila ei riitä"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Poista päivitys"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> on osa seuraavaa sovellusta:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Haluatko poistaa tämän sovelluksen?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Haluatko poistaa tämän sovelluksen "<b>"kaikilta"</b>" käyttäjiltä? Sovellus ja sen data poistetaan "<b>"kaikilta"</b>" laitteen käyttäjiltä."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Haluatko poistaa tämän sovelluksen käyttäjältä <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Haluatko poistaa sovelluksen työprofiilistasi?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Säilytä <xliff:g id="SIZE">%1$s</xliff:g> sovellusdataa"</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Haluatko poistaa tämän sovelluksen?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Haluatko poistaa tämän sovelluksen? Myös klooni (<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>) poistetaan."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Haluatko poistaa tämän sovelluksen yksityisestä tilasta?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Käynnissä olevat poistot"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Epäonnistuneet poistot"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Poistetaan…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Käyttäjävalinnat"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"Poisto (<xliff:g id="APP_NAME">%1$s</xliff:g>) epäonnistui."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Ongelma paketin jäsentämisessä"</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Wear ei tue asennus- ja poistotoimintoja."</string>
     <string name="message_staging" msgid="8032722385658438567">"Valmistellaan sovellusta…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Tuntematon"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Turvallisuussyistä tablettisi ei tällä hetkellä voi asentaa tuntemattomia sovelluksia tästä lähteestä. Voit muuttaa tätä asetuksissa."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Tuntemattomat sovellukset voivat helpommin kaapata tablettisi ja henkilökohtaiset tietosi. Lataamalla sovelluksia tästä lähteestä hyväksyt, että olet itse vastuussa tabletillesi aiheutuvista vahingoista tai tietojen menetyksestä, jotka voivat johtua sovellusten käytöstä."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Tuntemattomat sovellukset voivat helpommin kaapata televisiosi ja henkilökohtaiset tietosi. Lataamalla sovelluksen hyväksyt, että olet itse vastuussa mahdollisista televisiolle aiheutuvista vahingoista tai tietojen menetyksestä, jotka voivat johtua sovellusten käytöstä."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Klooni: <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Jatka"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Asetukset"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Wear-sovellusten asennus/poistaminen"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Palautetaanko <xliff:g id="APPNAME">%1$s</xliff:g> sovelluksella <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Sovelluksen lataus aloitetaan taustalla"</string>
     <string name="restore" msgid="8460854736328970444">"Palauta"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Olet offline-tilassa"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Sovellus palautuu automaattiseti, kun olet yhteydessä internetiin"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Jotain meni pieleen"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Sovelluksen palauttamisessa oli ongelma"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Tallennustila ei riitä"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Voit palauttaa sovelluksen vapauttamalla tilaa laitteella. Vaadittu tallennustila: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Toimi nyt"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Seuraa vaiheita sovelluksen palauttamiseen"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> on poistettu käytöstä"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Ota <xliff:g id="INSTALLERNAME">%1$s</xliff:g> käyttöön asetuksissa, jotta voit palauttaa sovelluksen"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"Asennus on poistettu (<xliff:g id="INSTALLERNAME">%1$s</xliff:g>)"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Asenna <xliff:g id="INSTALLERNAME">%1$s</xliff:g>, jotta voit palauttaa sovelluksen"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Jatka"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Tyhjennä tallennustila"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Asetukset"</string>
+    <string name="close" msgid="5214897374055647996">"Sulje"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-fr-rCA/strings.xml b/packages/PackageInstaller/res/values-fr-rCA/strings.xml
index 647a7b5..0bd5026 100644
--- a/packages/PackageInstaller/res/values-fr-rCA/strings.xml
+++ b/packages/PackageInstaller/res/values-fr-rCA/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Cet utilisateur ne peut pas installer d\'applications inconnues"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Cet utilisateur n\'est pas autorisé à installer des applications"</string>
     <string name="ok" msgid="7871959885003339302">"OK"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Mettre à jour malgré tout"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Gérer les applis"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Espace insuffisant"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Désinstaller mise à jour"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> fait partie de l\'application suivante :"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Voulez-vous désinstaller cette application?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Voulez-vous désinstaller cette application pour "<b>"tous"</b>" les utilisateurs? L\'application et ses données seront supprimées pour "<b>"tous"</b>" les utilisateurs de l\'appareil."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Voulez-vous désinstaller cette application pour l\'utilisateur <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Voulez-vous désinstaller cette application de votre profil professionnel?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Garder <xliff:g id="SIZE">%1$s</xliff:g> de données d\'application."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Voulez-vous supprimer cette application?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Voulez-vous désinstaller cette application? Le clone de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> sera aussi supprimé."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Voulez-vous désinstaller cette application de votre Espace privé?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Désinstallations en cours…"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Désinstallations échouées"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Désinstallation en cours…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Gérer les utilisateurs"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"Impossible de désinstaller <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Un problème est survenu lors de l\'analyse du paquet."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Les actions d\'installation et de désinstallation ne sont pas prises en charge par Android Wear."</string>
     <string name="message_staging" msgid="8032722385658438567">"Pré-production de l\'application en cours…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Inconnue"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"À des fins de sécurité, l\'installation d\'applications inconnues provenant de cette source n\'est pas autorisée sur cette tablette. Vous pouvez modifier cette option dans les paramètres."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Votre tablette et vos données personnelles sont plus vulnérables aux attaques provenant d\'applications inconnues. En installant cette application, vous acceptez d\'être le seul responsable de tout dommage causé à votre tablette ou de toute perte de données pouvant découler de l\'utilisation de telles applications."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Votre téléviseur et vos données personnelles sont plus vulnérables aux attaques d\'applications inconnues. En installant cette application, vous acceptez d\'être le seul responsable de tout dommage causé à votre téléviseur ou de toute perte de données pouvant découler de son utilisation."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Clone de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Continuer"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Paramètres"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Installer/désinstaller applis Google Wear"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Restaurer <xliff:g id="APPNAME">%1$s</xliff:g> à partir de <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Le téléchargement de cette application commencera en arrière-plan"</string>
     <string name="restore" msgid="8460854736328970444">"Restaurer"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Vous êtes hors ligne"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Cette application sera automatiquement restaurée lorsque vous serez connecté à Internet"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Un problème est survenu"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Un problème est survenu lors de la restauration de cette application"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Espace de stockage insuffisant"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Pour restaurer cette application, vous devez libérer de l\'espace de stockage sur cet appareil. Espace de stockage requis : <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Action requise"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Suivez les étapes suivantes pour restaurer cette application"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> est désactivé"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Pour restaurer cette application, activez <xliff:g id="INSTALLERNAME">%1$s</xliff:g> dans les paramètres"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> est désinstallé"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Pour restaurer cette application, vous devrez installer <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Continuer"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Effacer le stockage"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Paramètres"</string>
+    <string name="close" msgid="5214897374055647996">"Fermer"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-fr/strings.xml b/packages/PackageInstaller/res/values-fr/strings.xml
index 3cf043b..1c64613 100644
--- a/packages/PackageInstaller/res/values-fr/strings.xml
+++ b/packages/PackageInstaller/res/values-fr/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Cet utilisateur ne peut pas installer d\'applications inconnues"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Cet utilisateur n\'est pas autorisé à installer des applications"</string>
     <string name="ok" msgid="7871959885003339302">"OK"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Mettre à jour quand même"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Gérer applis"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Mémoire insuffisante"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Désinstaller la mise à jour"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> fait partie de l\'application suivante :"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Voulez-vous désinstaller cette application ?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Voulez-vous désinstaller cette application pour "<b>"tous"</b>" les utilisateurs ? L\'application et ses données seront supprimées pour "<b>"tous"</b>" les utilisateurs de l\'appareil."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Voulez-vous désinstaller cette application pour l\'utilisateur <xliff:g id="USERNAME">%1$s</xliff:g> ?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Voulez-vous désinstaller cette appli de votre profil professionnel ?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Conserver <xliff:g id="SIZE">%1$s</xliff:g> de données d\'application."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Voulez-vous supprimer cette appli ?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Voulez-vous désinstaller cette appli ? Le clone de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> sera supprimé aussi."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Souhaitez-vous désinstaller cette application de votre espace privé ?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Désinstallations en cours"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Échec des désinstallations"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Désinstallation…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Gérer les utilisateurs"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"Impossible de désinstaller l\'application <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Un problème est survenu lors de l\'analyse du package."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Opérations d\'installation et de désinstallation impossibles sur Android Wear."</string>
     <string name="message_staging" msgid="8032722385658438567">"Préparation de l\'installation de l\'appli…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Inconnu"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Pour votre sécurité, l\'installation d\'applis inconnues provenant de cette source n\'est pas autorisée sur cette tablette actuellement. Vous pouvez modifier cette option dans les paramètres."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Votre tablette et vos données à caractère personnel sont plus vulnérables aux attaques d\'applications inconnues. En installant cette application, vous acceptez d\'être le seul responsable de tout dommage causé à votre tablette ou de toute perte de données pouvant découler de son utilisation."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Votre téléviseur et vos données à caractère personnel sont plus vulnérables aux attaques d\'applications inconnues. En installant cette application, vous acceptez d\'être le seul responsable de tout dommage causé à votre téléviseur ou de toute perte de données pouvant découler de son utilisation."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Clone de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Continuer"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Paramètres"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Installer/Désinstaller les applis Wear"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Restaurer <xliff:g id="APPNAME">%1$s</xliff:g> depuis <xliff:g id="INSTALLERNAME">%1$s</xliff:g> ?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Cette application commencera à se télécharger en arrière-plan"</string>
     <string name="restore" msgid="8460854736328970444">"Restaurer"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Vous n\'êtes pas connecté"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"L\'application sera automatiquement restaurée lorsque vous serez connecté à Internet"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Un problème est survenu"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Un problème est survenu lors de la restauration de cette application"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Espace de stockage insuffisant"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Pour restaurer cette application, vous pouvez libérer de l\'espace sur cet appareil. Espace de stockage requis : <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Action requise"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Suivre la procédure ci-dessous pour restaurer cette application"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> est désactivé"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Pour restaurer cette application, autorisez <xliff:g id="INSTALLERNAME">%1$s</xliff:g> dans les Paramètres"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> n\'est pas installé"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Pour restaurer cette application, vous devrez installer <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Continuer"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Vider l\'espace de stockage"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Paramètres"</string>
+    <string name="close" msgid="5214897374055647996">"Fermer"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-gl/strings.xml b/packages/PackageInstaller/res/values-gl/strings.xml
index eeb1f95..38e79ba 100644
--- a/packages/PackageInstaller/res/values-gl/strings.xml
+++ b/packages/PackageInstaller/res/values-gl/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Este usuario non pode instalar aplicacións descoñecidas"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Este usuario non ten permiso para instalar aplicacións"</string>
     <string name="ok" msgid="7871959885003339302">"Aceptar"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Actualizar de todas formas"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Xestionar apps"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Esgotouse o espazo"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Desinstalar actualización"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> forma parte da seguinte aplicación:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Queres desinstalar esta aplicación?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Queres desinstalar esta aplicación para "<b>"todos"</b>" os usuarios? A aplicación e os seus datos quitaranse de "<b>"todos"</b>" os usuarios do dispositivo."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Queres desinstalar esta aplicación para o usuario que se chama <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Queres desinstalar esta aplicación do perfil de traballo?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Conservar os datos da aplicación, que ocupan <xliff:g id="SIZE">%1$s</xliff:g>."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Queres eliminar esta aplicación?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Queres desinstalar esta aplicación? Tamén se eliminará o clon de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Queres desinstalar esta aplicación do teu espazo privado?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Desinstalacións en curso"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Erros nas desinstalacións"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Desinstalando…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Administrar usuarios"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"Non se puido desinstalar a aplicación <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Produciuse un problema ao analizar o paquete."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"As accións de instalar e desinstalar non son compatibles con Wear."</string>
     <string name="message_staging" msgid="8032722385658438567">"Preparando aplicación…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Nome descoñecido"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Por cuestións de seguranza, na tableta non se poden instalar actualmente aplicacións descoñecidas procedentes desta fonte. Podes cambiar esta opción en Configuración."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"A tableta e os datos persoais son máis vulnerables aos ataques de aplicacións descoñecidas. Ao instalar esta aplicación, aceptas que es responsable dos danos ocasionados na tableta ou da perda dos datos que se poidan derivar do seu uso."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"A televisión e os datos persoais son máis vulnerables aos ataques de aplicacións descoñecidas. Ao instalar esta aplicación, aceptas que es responsable dos danos ocasionados na televisión ou da perda dos datos que se poidan derivar do seu uso."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Clon de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Continuar"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Configuración"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Instalando/desinstalando apps para Wear"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Queres restaurar <xliff:g id="APPNAME">%1$s</xliff:g> desde <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Esta aplicación comezará a descargarse en segundo plano"</string>
     <string name="restore" msgid="8460854736328970444">"Restaurar"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Estás sen conexión"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Esta aplicación restaurarase automaticamente cando te conectes a Internet"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Produciuse un erro"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Produciuse un problema ao restaurar esta aplicación"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Non hai almacenamento suficiente"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Para restaurar esta aplicación, podes liberar espazo neste dispositivo. Espazo de almacenamento necesario: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Acción necesaria"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Completa os pasos seguintes para restaurar esta aplicación"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"Desactivouse <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Para restaurar esta aplicación, activa <xliff:g id="INSTALLERNAME">%1$s</xliff:g> en Configuración"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"Desinstalouse <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Para restaurar esta aplicación, tes que instalar <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Continuar"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Liberar almacenamento"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Configuración"</string>
+    <string name="close" msgid="5214897374055647996">"Pechar"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-gu/strings.xml b/packages/PackageInstaller/res/values-gu/strings.xml
index e1f1887..3362a16 100644
--- a/packages/PackageInstaller/res/values-gu/strings.xml
+++ b/packages/PackageInstaller/res/values-gu/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"આ વપરાશકર્તા અજાણી ઍપ્લિકેશનોને ઇન્સ્ટૉલ કરી શકતા નથી"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"આ વપરાશકર્તાને ઍપ્લિકેશનો ઇન્સ્ટૉલ કરવાની મંજૂરી નથી"</string>
     <string name="ok" msgid="7871959885003339302">"ઓકે"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"તો પણ અપડેટ કરો"</string>
     <string name="manage_applications" msgid="5400164782453975580">"ઍપને મેનેજ કરો"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"સ્પેસ નથી"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"અપડેટ અનઇન્સ્ટૉલ કરો"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g>, નીચેની ઍપ્લિકેશનનો ભાગ છે:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"શું તમે આ ઍપને અનઇન્સ્ટૉલ કરવા માંગો છો?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"શું તમે "<b>"બધા"</b>" વપરાશકર્તાઓ માટે આ ઍપ્લિકેશનને અનઇન્સ્ટૉલ કરવા માગો છો? ડિવાઇસ પરના "<b>"બધા"</b>" વપરાશકર્તાઓની ઍપ્લિકેશન અને તેનો ડેટા કાઢી નાખવામાં આવશે."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"શું તમે <xliff:g id="USERNAME">%1$s</xliff:g> વપરાશકર્તા માટે આ ઍપ્લિકેશનને અનઇન્સ્ટૉલ કરવા માગો છો?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"શું તમે તમારી ઑફિસની પ્રોફાઇલમાંથી આ ઍપને અનઇન્સ્ટૉલ કરવા માગો છો?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"<xliff:g id="SIZE">%1$s</xliff:g>નો ઍપ ડેટા રાખો."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"શું તમે આ ઍપ ડિલીટ કરવા માગો છો?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"શું તમે આ ઍપને અનઇન્સ્ટૉલ કરવા માગો છો? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>ની ક્લોન પણ ડિલીટ કરવામાં આવશે."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"શું તમે તમારી ખાનગી સ્પેસમાંથી આ ઍપ અનઇન્સ્ટૉલ કરવા માગો છો?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"ચાલી રહેલા અનઇન્સ્ટૉલ"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"નિષ્ફળ થયેલા અનઇન્સ્ટૉલ"</string>
     <string name="uninstalling" msgid="8709566347688966845">"અનઇન્સ્ટૉલ કરી રહ્યાં છીએ…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"વપરાશકર્તાઓને મેનેજ કરો"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> અનઇન્સ્ટૉલ કરી શકાઈ નથી."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"પૅકેજનું વિશ્લેષણ કરવામાં સમસ્યા આવી હતી."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Wear પર ઇન્સ્ટૉલ/અનઇન્સ્ટૉલ ક્રિયાઓ સમર્થિત નથી."</string>
     <string name="message_staging" msgid="8032722385658438567">"ઍપ્લિકેશનની પ્રક્રિયા ચાલુ છે…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"અજાણ"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"તમારી સુરક્ષા માટે, હાલમાં તમારા ટૅબ્લેટને આ સૉર્સ પરથી અજાણી ઍપ ઇન્સ્ટૉલ કરવાની મંજૂરી નથી. તમે આને સેટિંગમાં બદલી શકો છો."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"તમારું ટૅબ્લેટ અને વ્યક્તિગત ડેટા અજાણી ઍપ્લિકેશનો દ્વારા હુમલા માટે વધુ સંવેદનશીલ છે. આ ઍપ્લિકેશન ઇન્સ્ટૉલ કરીને તમે સંમત થાઓ છો કે આનો ઉપયોગ કરવાથી તમારા ટૅબ્લેટને થતી કોઈપણ હાનિ અથવા ડેટાના નુકસાન માટે તમે જવાબદાર છો."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"તમારું ટીવી અને વ્યક્તિગત ડેટા અજાણી ઍપ્લિકેશનો દ્વારા હુમલા માટે વધુ સંવેદનશીલ છે. આ ઍપ્લિકેશન ઇન્સ્ટૉલ કરીને તમે સંમત થાઓ છો કે આનો ઉપયોગ કરવાથી તમારા ટીવીને થતી કોઈપણ હાનિ અથવા ડેટાના નુકસાન માટે તમે જવાબદાર છો."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>ની ક્લોન"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"આગળ વધો"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"સેટિંગ"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"એમ્બેડ ઍપ્લિકેશનો ઇન્સ્ટૉલ/અનઇન્સ્ટૉલ"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g>માંથી <xliff:g id="APPNAME">%1$s</xliff:g> રિસ્ટોર કરીએ?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"બૅકગ્રાઉન્ડમાં આ ઍપ ડાઉનલોડ થવાનું શરૂ થશે"</string>
     <string name="restore" msgid="8460854736328970444">"રિસ્ટોર કરો"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"તમે ઑફલાઇન છો"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"જ્યારે તમે ઇન્ટરનેટ સાથે કનેક્ટેડ થશો, ત્યારે આ ઍપ ઑટોમૅટિક રીતે રિસ્ટોર થશે"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"કંઈક ખોટું થયું"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"આ ઍપને રિસ્ટોર કરવામાં કોઈ સમસ્યા આવી હતી"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"પર્યાપ્ત સ્ટોરેજ નથી"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"આ ઍપને રિસ્ટોર કરવા માટે, તમે આ ડિવાઇસ પર સ્પેસ ખાલી કરી શકો છો. આવશ્યક સ્ટોરેજ: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"પગલું આવશ્યક છે"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"આ ઍપને રિસ્ટોર કરવા માટે આગળના પગલાં અનુસરો"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> બંધ છે"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"આ ઍપને રિસ્ટોર કરવા માટે, સેટિંગમાં <xliff:g id="INSTALLERNAME">%1$s</xliff:g> ચાલુ કરો"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> અનઇન્સ્ટૉલ કર્યું છે"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"આ ઍપને રિસ્ટોર કરવા માટે, તમારે <xliff:g id="INSTALLERNAME">%1$s</xliff:g> ઇન્સ્ટૉલ કરવું જરૂરી છે"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"આગળ વધો"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"સ્ટોરેજ સાફ કરો"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"સેટિંગ"</string>
+    <string name="close" msgid="5214897374055647996">"બંધ કરો"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-hi/strings.xml b/packages/PackageInstaller/res/values-hi/strings.xml
index 642bbd9..e774291 100644
--- a/packages/PackageInstaller/res/values-hi/strings.xml
+++ b/packages/PackageInstaller/res/values-hi/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"यह उपयोगकर्ता अनजान ऐप्लिकेशन इंस्टॉल नहीं कर सकता"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"इस उपयोगकर्ता को ऐप्लिकेशन इंस्टॉल करने की अनुमति नहीं है"</string>
     <string name="ok" msgid="7871959885003339302">"ठीक है"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"फिर भी अपडेट करें"</string>
     <string name="manage_applications" msgid="5400164782453975580">"ऐप्लिकेशन प्रबंधित करें"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"जगह नहीं है"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"अपडेट अनइंस्‍टॉल करें"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> इस ऐप्लिकेशन का भाग है:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"क्‍या आपको इस ऐप्लिकेशन को अनइंस्‍टॉल करना है?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"क्या आप इस ऐप्लिकेशन को "<b>"सभी"</b>" उपयोगकर्ताओं के लिए अनइंस्टॉल करना चाहते हैं? ऐप्लिकेशन और उसके डेटा को डिवाइस पर "<b>"सभी"</b>" उपयोगकर्ताओं से हटा दिया जाएगा."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"क्या आप उपयोगकर्ता <xliff:g id="USERNAME">%1$s</xliff:g> के लिए इस ऐप्लिकेशन को अनइंस्टॉल करना चाहते हैं?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"क्या अपनी वर्क प्रोफ़ाइल से इस ऐप्लिकेशन को अनइंस्टॉल करना है?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"<xliff:g id="SIZE">%1$s</xliff:g> ऐप्लिकेशन डेटा रखें."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"क्या आपको यह ऐप्लिकेशन मिटाना है?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"क्या आपको यह ऐप्लिकेशन अनइंस्टॉल करना है? इससे <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> का क्लोन भी मिट जाएगा."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"क्या आपको अपने प्राइवेट स्पेस से यह ऐप्लिकेशन अनइंस्टॉल करना है?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"वे अनइंस्टॉल जो चल रहे हैं"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"वे अनइंस्टॉल जो सफल नहीं रहे"</string>
     <string name="uninstalling" msgid="8709566347688966845">"अनइंस्‍टॉल हो रहा है…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"उपयोगकर्ताओं को मैनेज करें"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> को अनइंस्‍टॉल नहीं किया जा सका."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"पैकेज को पार्स करने में कोई समस्‍या थी."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Wear पर ऐप्लिकेशन इंस्टॉल या अनइंस्टॉल नहीं किए जा सकते."</string>
     <string name="message_staging" msgid="8032722385658438567">"ऐप्लिकेशन तैयार किया जा रहा है…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"अनजान"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"आपकी सुरक्षा के लिए, आपके टैबलेट को फ़िलहाल इस स्रोत से अनजान ऐप्लिकेशन इंस्टॉल करने की अनुमति नहीं है. आप \'सेटिंग\' में जाकर इसे बदल सकते हैं."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"आपका टैबलेट और निजी डेटा अनजान ऐप्लिकेशन के हमले को लेकर ज़्यादा संवेदनशील हैं. इस ऐप्लिकेशन को इंस्टॉल करके, आप सहमति देते हैं कि इसके इस्तेमाल के चलते आपके टैबलेट को होने वाले किसी भी नुकसान या डेटा के मिट जाने पर, आप ज़िम्मेदार होंगे."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"आपका टीवी और निजी डेटा अनजान ऐप्लिकेशन के हमले को लेकर ज़्यादा संवेदनशील हैं. इस ऐप्लिकेशन को इंस्टॉल करके, आप सहमति देते हैं कि इसके इस्तेमाल के चलते आपके टीवी को होने वाले किसी भी नुकसान या डेटा के मिट जाने पर, आप ज़िम्मेदार होंगे."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> का क्लोन"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"जारी रखें"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"सेटिंग"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Wear ऐप्लिकेशन इंस्टॉल/अनइंस्टॉल हो रहे हैं"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"<xliff:g id="APPNAME">%1$s</xliff:g> को <xliff:g id="INSTALLERNAME">%1$s</xliff:g> से वापस लाएं?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"यह ऐप्लिकेशन, बैकग्राउंड में डाउनलोड होना शुरू हो जाएगा"</string>
     <string name="restore" msgid="8460854736328970444">"वापस लाएं"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"आप ऑफ़लाइन हैं"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"इंटरनेट कनेक्शन होने पर, यह ऐप्लिकेशन अपने-आप वापस आ जाएगा"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"कोई गड़बड़ी हुई"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"इस ऐप्लिकेशन को वापस लाने में समस्या हुई"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"डिवाइस का स्टोरेज ज़रूरत से कम है"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"इस ऐप्लिकेशन को वापस लाने के लिए, इस डिवाइस में स्टोरेज खाली करें. इतने स्टोरेज की ज़रूरत है: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"कार्रवाई ज़रूरी है"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"इस ऐप्लिकेशन को वापस लाने के लिए, दिया गया तरीका अपनाएं"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> बंद है"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"इस ऐप्लिकेशन को वापस लाने के लिए, Settings में जाकर <xliff:g id="INSTALLERNAME">%1$s</xliff:g> को चालू करें"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> अनइंस्टॉल है"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"इस ऐप्लिकेशन को वापस लाने के लिए, आपको <xliff:g id="INSTALLERNAME">%1$s</xliff:g> इंस्टॉल करना होगा"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"जारी रखें"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"स्टोरेज खाली करें"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Settings"</string>
+    <string name="close" msgid="5214897374055647996">"बंद करें"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-hr/strings.xml b/packages/PackageInstaller/res/values-hr/strings.xml
index 69ce3f1..5df276e 100644
--- a/packages/PackageInstaller/res/values-hr/strings.xml
+++ b/packages/PackageInstaller/res/values-hr/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Ovaj korisnik ne može instalirati nepoznate aplikacije"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Ovaj korisnik nema dopuštenje za instaliranje aplikacija"</string>
     <string name="ok" msgid="7871959885003339302">"U redu"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Ipak ažuriraj"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Upravljanje apl."</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Nema dovoljno mjesta"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Deinstalacija ažuriranja"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"Aktivnost <xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> dio je sljedeće aplikacije:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Želite li deinstalirati ovu aplikaciju?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Želite li deinstalirati tu aplikaciju za "<b>"sve"</b>" korisnike? Aplikacija i njezini podaci bit će uklonjeni sa "<b>"svih"</b>" korisnika na uređaju."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Želite li deinstalirati tu aplikaciju za korisnika <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Želite li deinstalirati tu aplikaciju s poslovnog profila?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Zadrži <xliff:g id="SIZE">%1$s</xliff:g> podataka aplikacije."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Želite li izbrisati ovu aplikaciju?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Želite li deinstalirati ovu aplikaciju? Klon za <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> također će se izbrisati."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Želite li deinstalirati ovu aplikaciju iz svojeg privatnog prostora?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Deinstaliranja u tijeku"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Neuspjela deinstaliranja"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Deinstaliranje…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Upravljaj korisnicima"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"Aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g> nije moguće instalirati."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Došlo je do problema pri analiziranju paketa."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Radnje instaliranja i deinstaliranja nisu podržane na Wearu."</string>
     <string name="message_staging" msgid="8032722385658438567">"Postavljanje aplikacije…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Nepoznato"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Iz sigurnosnih razloga tablet trenutačno nema dopuštenje za instaliranje nepoznatih aplikacija iz ovog izvora. To možete promijeniti u Postavkama."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Vaš tablet i osobni podaci podložniji su napadima nepoznatih aplikacija. Instaliranjem te aplikacije prihvaćate odgovornost za oštećenje tableta ili gubitak podataka do kojih može doći uslijed njezine upotrebe."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Vaš TV i osobni podaci podložniji su napadima nepoznatih aplikacija. Instaliranjem te aplikacije prihvaćate odgovornost za oštećenje televizora ili gubitak podataka do kojih može doći uslijed njezine upotrebe."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Klon <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Nastavi"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Postavke"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Instaliranje/deinstaliranje Wear apl."</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Želite li vratiti aplikaciju <xliff:g id="APPNAME">%1$s</xliff:g> putem aplikacije <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Ova aplikacija počet će se preuzimati u pozadini"</string>
     <string name="restore" msgid="8460854736328970444">"Vrati"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Niste povezani s internetom"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Aplikacija će se automatski vratiti kad se povežete s internetom"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Nešto nije u redu"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Došlo je do problema s vraćanjem aplikacije"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Nema dovoljno prostora za pohranu"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Da biste vratili aplikaciju, možete osloboditi prostor za pohranu na ovom uređaju. Potreban prostor za pohranu: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Potrebna je radnja"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Da biste vratili aplikaciju, slijedite upute u nastavku"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> – onemogućeno"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Da biste vratili aplikaciju, u postavkama omogućite sljedeće: <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> – deinstalirano"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Da biste vratili aplikaciju, instalirajte sljedeće: <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Nastavi"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Izbriši pohranu"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Postavke"</string>
+    <string name="close" msgid="5214897374055647996">"Zatvori"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-hu/strings.xml b/packages/PackageInstaller/res/values-hu/strings.xml
index ea8cfc7..6de5bac 100644
--- a/packages/PackageInstaller/res/values-hu/strings.xml
+++ b/packages/PackageInstaller/res/values-hu/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Ez a felhasználó nem telepíthet ismeretlen alkalmazásokat"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Ez a felhasználó nem telepíthet alkalmazásokat"</string>
     <string name="ok" msgid="7871959885003339302">"OK"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Frissítés"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Alkalmazáskezelés"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Nincs elég hely"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Frissítés eltávolítása"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"A(z) <xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> a következő alkalmazás része:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Eltávolítja ezt az alkalmazást?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Szeretné eltávolítani ezt az alkalmazást "<b>"minden"</b>" felhasználónál? Az alkalmazást és adatait az eszköz "<b>"minden"</b>" felhasználójánál töröljük."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Eltávolítja ezt az alkalmazást <xliff:g id="USERNAME">%1$s</xliff:g> felhasználó esetében?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Biztosan eltávolítja ezt az alkalmazást a munkaprofiljából?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"<xliff:g id="SIZE">%1$s</xliff:g> alkalmazásadat megtartása."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Szeretné törölni ezt az alkalmazást?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Eltávolítja ezt az alkalmazást? A klónozott <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> is törlésre kerül."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Eltávolítja ezt az alkalmazást a privát területről?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Futó eltávolítások"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Sikertelen telepítések"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Eltávolítás…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Felhasználók kezelése"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"Nem sikerült a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> eltávolítása"</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Gond volt a csomag elemzésekor."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"A Wear nem támogatja a telepítés/eltávolítás műveletet."</string>
     <string name="message_staging" msgid="8032722385658438567">"Alkalmazás fokozatos közzététele…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Ismeretlen"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Az Ön biztonsága érdekében táblagépe jelenleg nem telepíthet ebből a forrásból származó ismeretlen alkalmazásokat. Ezt módosíthatja a Beállítások között."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Táblagépe és személyes adatai fokozott kockázatnak vannak kitéve az ismeretlen alkalmazások támadásaival szemben. Az alkalmazás telepítésével elfogadja, hogy Ön a felelős az alkalmazás használatából eredő esetleges adatvesztésért és a táblagépet ért károkért."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Tévéje és személyes adatai fokozott kockázatnak vannak kitéve az ismeretlen alkalmazások támadásaival szemben. Az alkalmazás telepítésével elfogadja, hogy Ön a felelős az alkalmazás használatából eredő esetleges adatvesztésért és a tévét ért károkért."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Klónozott <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Tovább"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Beállítások"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Wear-alkalmazások telepítése/törlése"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Visszaállítja a(z) <xliff:g id="APPNAME">%1$s</xliff:g> appot innen: <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"A háttérben megkezdődik az app letöltése"</string>
     <string name="restore" msgid="8460854736328970444">"Visszaállítás"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Az eszköz offline állapotban van"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Automatikusan megtörténik az alkalmazás visszaállítása, amikor Ön csatlakozik az internethez."</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Hiba történt"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Hiba történt az alkalmazás visszaállítása során."</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Nincs elegendő tárhely"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Az alkalmazás visszaállításához szabadítson fel tárhelyet ezen az eszközön. Szükséges tárhely: <xliff:g id="BYTES">%1$s</xliff:g>."</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Fontos teendő"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Az alkalmazás visszaállításához kövesse a következő lépéseket."</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"A(z) <xliff:g id="INSTALLERNAME">%1$s</xliff:g> le van tiltva"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Az alkalmazás visszaállításához engedélyezze a következőt a Beállításokban: <xliff:g id="INSTALLERNAME">%1$s</xliff:g>."</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"A(z) <xliff:g id="INSTALLERNAME">%1$s</xliff:g> nincs telepítve"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Az alkalmazás app visszaállításához telepítse a következőt: <xliff:g id="INSTALLERNAME">%1$s</xliff:g>."</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Tovább"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Tárhely ürítése"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Beállítások"</string>
+    <string name="close" msgid="5214897374055647996">"Bezárás"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-hy/strings.xml b/packages/PackageInstaller/res/values-hy/strings.xml
index a447371..4bb3915 100644
--- a/packages/PackageInstaller/res/values-hy/strings.xml
+++ b/packages/PackageInstaller/res/values-hy/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Այս օգտատերը չի կարող անհայտ հավելվածներ տեղադրել"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Այս օգտատիրոջը չի թույլատրվում տեղադրել հավելվածներ"</string>
     <string name="ok" msgid="7871959885003339302">"Եղավ"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Թարմացնել"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Կառավարել հավելվածները"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Բավարար տարածք չկա"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Ապատեղադրել թարմացումը"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> գործողությունը հետևյալ հավելվածի մասն է`"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Ուզո՞ւմ եք ապատեղադրել այս հավելվածը։"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Ապատեղադրե՞լ այս հավելվածը "<b>"բոլոր"</b>" օգտատերերի համար: Հավելվածը և դրա տվյալները կհեռացվեն սարքի "<b>"բոլոր"</b>" օգտատերերից:"</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Ապատեղադրե՞լ այս հավելվածը <xliff:g id="USERNAME">%1$s</xliff:g> օգտատիրոջ համար:"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Հեռացնե՞լ այս հավելվածը ձեր աշխատանքային պրոֆիլից"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Չհեռացնել հավելվածների տվյալները (<xliff:g id="SIZE">%1$s</xliff:g>):"</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Ջնջե՞լ այս հավելվածը"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Ապատեղադրե՞լ այս հավելվածը։ <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-ի կլոնը նույնպես կջնջվի։"</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Ապատեղադրե՞լ այս հավելվածը ձեր անձնական տարածքից"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Ընթացիկ ապատեղադրումներ"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Ձախողված ապատեղադրումներ"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Ապատեղադրվում է…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Կառավարել օգտատերերին"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"Չհաջողվեց ապատեղադրել <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը:"</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Փաթեթը վերլուծելիս խնդիր առաջացավ:"</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Տեղադրման/ապատեղադրման գործողությունները Android Wear-ում չեն աջակցվում:"</string>
     <string name="message_staging" msgid="8032722385658438567">"Սպասեք…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Անհայտ"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Անվտանգության նկատառումներից ելնելով՝ ձեր պլանշետում ներկայումս չի թույլատրվում անհայտ հավելվածներ տեղադրել այս աղբյուրից: Սա կարող եք փոխել կարգավորումներում։"</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Ձեր պլանշետը և անձնական տվյալներն առավել խոցելի են անհայտ հավելվածների գրոհների նկատմամբ: Տեղադրելով այս հավելվածը՝ դուք ընդունում եք, որ պատասխանատվություն եք կրում հավելվածի օգտագործման հետևանքով ձեր պլանշետին հասցված ցանկացած վնասի կամ տվյալների կորստի համար:"</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Ձեր հեռուստացույցը և անձնական տվյալներն առավել խոցելի են անհայտ հավելվածների գրոհների նկատմամբ: Տեղադրելով այս հավելվածը՝ դուք ընդունում եք, որ պատասխանատվություն եք կրում հավելվածի օգտագործման հետևանքով ձեր հեռուստացույցին հասցված ցանկացած վնասի կամ տվյալների կորստի համար:"</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"«<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>» հավելվածի կլոն"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Շարունակել"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Կարգավորումներ"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Wear հավելվածների տեղադրում/ապատեղադրում"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Վերականգնե՞լ <xliff:g id="APPNAME">%1$s</xliff:g> հավելվածը <xliff:g id="INSTALLERNAME">%1$s</xliff:g>-ից"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Այս հավելվածը կներբեռնվի ֆոնային ռեժիմում"</string>
     <string name="restore" msgid="8460854736328970444">"Վերականգնել"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Կապ չկա"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Այս հավելվածն ավտոմատ կվերականգնվի, երբ միանաք ինտերնետին"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Սխալ առաջացավ"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Չհաջողվեց վերականգնել այս հավելվածը"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Բավարար տարածք չկա"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Հավելվածը վերականգնելու համար տարածք ազատեք սարքում։ Պահանջվում է <xliff:g id="BYTES">%1$s</xliff:g>։"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Պահանջվում է գործողություն"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Այս հավելվածը վերականգնելու համար կատարեք հաջորդ քայլերը"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> հավելվածն անջատված է"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Այս հավելվածը վերականգնելու համար միացրեք <xliff:g id="INSTALLERNAME">%1$s</xliff:g> հավելվածը Կարգավորումներում"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> հավելվածն ապատեղադրված է"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Այս հավելվածը վերականգնելու համար տեղադրեք <xliff:g id="INSTALLERNAME">%1$s</xliff:g> հավելվածը"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Շարունակել"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Մաքրել պահոցը"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Կարգավորումներ"</string>
+    <string name="close" msgid="5214897374055647996">"Փակել"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-in/strings.xml b/packages/PackageInstaller/res/values-in/strings.xml
index 9e24424..58db084 100644
--- a/packages/PackageInstaller/res/values-in/strings.xml
+++ b/packages/PackageInstaller/res/values-in/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Aplikasi yang tidak dikenal tidak dapat diinstal oleh pengguna ini"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Pengguna ini tidak diizinkan menginstal aplikasi"</string>
     <string name="ok" msgid="7871959885003339302">"Oke"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Tetap update"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Kelola aplikasi"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Kehabisan ruang penyimpanan"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Uninstal update"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> adalah bagian dari aplikasi berikut:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Apakah Anda ingin meng-uninstal aplikasi ini?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Apakah Anda ingin meng-uninstal aplikasi ini untuk "<b>"semua"</b>" pengguna? Aplikasi dan datanya akan dihapus dari "<b>"semua"</b>" pengguna pada perangkat."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Apakah Anda ingin meng-uninstal aplikasi ini untuk pengguna <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Ingin meng-uninstal aplikasi ini dari profil kerja Anda?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Pertahankan data aplikasi sebesar <xliff:g id="SIZE">%1$s</xliff:g>."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Ingin menghapus aplikasi ini?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Ingin meng-uninstal aplikasi ini? Clone <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> juga akan dihapus."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Ingin meng-uninstal aplikasi ini dari ruang pribadi?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Menjalankan proses uninstal"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Proses uninstal yang gagal"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Meng-uninstal..."</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Kelola pengguna"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak dapat di-uninstal."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Ada masalah saat mengurai paket."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Tindakan Instal/Uninstal tidak didukung di Wear."</string>
     <string name="message_staging" msgid="8032722385658438567">"Menyiapkan aplikasi..."</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Tidak dikenal"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Demi keamanan, tablet Anda saat ini tidak diizinkan menginstal aplikasi yang tidak dikenal dari sumber ini. Anda dapat mengubahnya di Setelan."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Tablet dan data pribadi Anda lebih rentan terhadap serangan oleh aplikasi yang tidak dikenal. Dengan menginstal aplikasi ini, Anda setuju bahwa Anda bertanggung jawab atas kerusakan tablet atau kehilangan data yang mungkin diakibatkan oleh penggunaannya."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"TV dan data pribadi Anda lebih rentan terhadap serangan oleh aplikasi yang tidak dikenal. Dengan menginstal aplikasi ini, Anda setuju bahwa Anda bertanggung jawab atas kerusakan TV atau kehilangan data yang mungkin diakibatkan oleh penggunaannya."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Clone <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Lanjutkan"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Setelan"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Melakukan instal/uninstal aplikasi Wear"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Pulihkan <xliff:g id="APPNAME">%1$s</xliff:g> dari <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Aplikasi ini akan mulai didownload di latar belakang"</string>
     <string name="restore" msgid="8460854736328970444">"Pulihkan"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Anda offline"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Aplikasi ini akan otomatis dipulihkan saat Anda terhubung ke internet"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Terjadi error"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Terjadi error saat mencoba memulihkan aplikasi ini"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Penyimpanan tidak cukup"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Untuk memulihkan aplikasi ini, Anda perlu mengosongkan ruang penyimpanan di perangkat ini. Penyimpanan yang diperlukan: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Tindakan diperlukan"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Ikuti langkah berikutnya untuk memulihkan aplikasi ini"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> dinonaktifkan"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Untuk memulihkan aplikasi ini, aktifkan <xliff:g id="INSTALLERNAME">%1$s</xliff:g> di Setelan"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> diuninstal"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Untuk memulihkan aplikasi ini, Anda harus menginstal <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Lanjutkan"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Hapus penyimpanan"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Setelan"</string>
+    <string name="close" msgid="5214897374055647996">"Tutup"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-is/strings.xml b/packages/PackageInstaller/res/values-is/strings.xml
index c24f284..44fc208 100644
--- a/packages/PackageInstaller/res/values-is/strings.xml
+++ b/packages/PackageInstaller/res/values-is/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Þessi notandi getur ekki sett upp óþekkt forrit"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Þessi notandi hefur ekki leyfi til að setja upp forrit"</string>
     <string name="ok" msgid="7871959885003339302">"Í lagi"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Uppfæra samt"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Stj. forritum"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Ekkert pláss eftir"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Fjarlægja uppfærslu"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> er hluti af þessu forriti:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Viltu fjarlægja þetta forrit?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Viltu fjarlægja þetta forrit hjá "<b>"öllum"</b>" notendum? Forritið og gögn þess verða fjarlægð hjá "<b>"öllum"</b>" notendum tækisins."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Viltu fjarlægja þetta forrit fyrir notandann <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Viltu fjarlægja þetta forrit af vinnuprófílnum þínum?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Halda <xliff:g id="SIZE">%1$s</xliff:g> af forritagögnum."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Viltu eyða þessu forriti?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Viltu fjarlægja þetta forrit? Afriti af <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> verður einnig eytt."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Viltu fjarlægja þetta forrit úr einkarýminu?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Fjarlægingar í gangi"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Fjarlægingar sem mistókust"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Fjarlægir…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Stjórna notendum"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"Ekki tókst að fjarlægja <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Vandamál kom upp við að vinna úr pakkanum."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Aðgerðir til að setja upp / fjarlægja eru ekki studdar í Wear."</string>
     <string name="message_staging" msgid="8032722385658438567">"Setur upp forrit…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Óþekkt"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Af öryggisástæðum er ekki heimilt að setja upp óþekkt forrit frá þessum uppruna í spjaldtölvunni þinni. Þú getur breytt þessu í stillingum."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Spjaldtölvan þín og persónuleg gögn eru berskjaldaðri fyrir árásum forrita af óþekktum uppruna. Með uppsetningu þessa forrits samþykkirðu að bera fulla ábyrgð á hverju því tjóni sem verða kann á spjaldtölvunni eða gagnatapi sem leiða kann af notkun þess."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Sjónvarpið þitt og persónuleg gögn eru berskjaldaðri fyrir árásum forrita af óþekktum uppruna. Með uppsetningu þessa forrits samþykkirðu að bera fulla ábyrgð á hverju því tjóni sem verða kann á sjónvarpinu eða gagnatapi sem leiða kann af notkun þess."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Afrit af <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Áfram"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Stillingar"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Uppsetning/fjarlæging Wear forrita"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Endurheimta <xliff:g id="APPNAME">%1$s</xliff:g> úr <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Forritið verður sótt í bakgrunni"</string>
     <string name="restore" msgid="8460854736328970444">"Endurheimta"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Þú ert ekki á netinu"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Þetta forrit verður endurheimt sjálfkrafa þegar þú tengist netinu"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Eitthvað fór úrskeiðis"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Vandamál kom upp við að endurheimta þetta forrit"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Ekki nógu mikið geymslurými"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Til að endurheimta þetta forrit geturðu losað um pláss í þessu tæki. Geymslurýmið sem þarf: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Aðgerðar krafist"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Fylgdu næstu skrefum til að endurheimta þetta forrit"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"Slökkt er á <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Kveiktu á <xliff:g id="INSTALLERNAME">%1$s</xliff:g> í stillingunum til að endurheimta þetta forrit"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"Búið er að fjarlægja <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Þú þarft að setja upp <xliff:g id="INSTALLERNAME">%1$s</xliff:g> til að endurheimta þetta forrit"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Halda áfram"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Hreinsa geymslu"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Stillingar"</string>
+    <string name="close" msgid="5214897374055647996">"Loka"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-it/strings.xml b/packages/PackageInstaller/res/values-it/strings.xml
index 604d88a..136a537 100644
--- a/packages/PackageInstaller/res/values-it/strings.xml
+++ b/packages/PackageInstaller/res/values-it/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Questo utente non può installare app sconosciute"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"L\'utente non è autorizzato a installare app"</string>
     <string name="ok" msgid="7871959885003339302">"OK"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Aggiorna comunque"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Gestisci app"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Spazio esaurito"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Disinstalla aggiornamento"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> fa parte della seguente applicazione:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Vuoi disinstallare questa app?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Vuoi disinstallare questa applicazione per "<b>"tutti"</b>" gli utenti? L\'applicazione e i relativi dati verranno rimossi da "<b>"tutti"</b>" gli utenti configurati sul dispositivo."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Disinstallare l\'app per l\'utente <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Vuoi disinstallare questa app dal tuo profilo di lavoro?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Mantieni <xliff:g id="SIZE">%1$s</xliff:g> di dati delle app."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Vuoi eliminare questa app?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Vuoi disinstallare questa app? Verrà eliminato anche il clone di <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Vuoi disinstallare questa app dal tuo spazio privato?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Disinstallazioni in esecuzione"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Disinstallazioni non riuscite"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Disinstallazione…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Gestisci utenti"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"Impossibile disinstallare <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Errore durante l\'analisi del pacchetto."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Le azioni di installazione/disinstallazione non sono supportate su Wear."</string>
     <string name="message_staging" msgid="8032722385658438567">"App in preparazione…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Sconosciuto"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Per motivi di sicurezza, il tuo tablet non è attualmente autorizzato a installare app sconosciute da questa origine. Puoi modificare questa opzione nelle Impostazioni."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"I dati del tablet e i dati personali sono più vulnerabili agli attacchi di app sconosciute. Se installi questa app, accetti di essere responsabile degli eventuali danni al tablet o dell\'eventuale perdita di dati derivanti dall\'uso dell\'app."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"I dati della TV e i dati personali sono più vulnerabili agli attacchi di app sconosciute. Se installi questa app, accetti di essere responsabile degli eventuali danni alla TV o dell\'eventuale perdita di dati derivanti dall\'uso dell\'app."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Clone di <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Continua"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Impostazioni"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Installazione/disinstallazione app Wear"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Ripristinare <xliff:g id="APPNAME">%1$s</xliff:g> da <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Il download di quest\'app inizierà in background"</string>
     <string name="restore" msgid="8460854736328970444">"Ripristina"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Sei offline"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Quest\'app verrà ripristinata automaticamente quando il dispositivo è connesso a internet"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Si è verificato un problema"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Si è verificato un problema durante il ripristino di questa app"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Spazio di archiviazione insufficiente"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Per ripristinare quest\'app, puoi liberare spazio sul dispositivo. Spazio di archiviazione necessario: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Azione richiesta"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Segui i passaggi successivi per ripristinare quest\'app"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> non è attivo"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Per ripristinare quest\'app, abilita <xliff:g id="INSTALLERNAME">%1$s</xliff:g> in Impostazioni"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> è stato disinstallato"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Per ripristinare quest\'app, dovrai installare <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Continua"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Libera spazio di archiviazione"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Impostazioni"</string>
+    <string name="close" msgid="5214897374055647996">"Chiudi"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-iw/strings.xml b/packages/PackageInstaller/res/values-iw/strings.xml
index 0e37b2e..2c6f127 100644
--- a/packages/PackageInstaller/res/values-iw/strings.xml
+++ b/packages/PackageInstaller/res/values-iw/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"למשתמש הזה אין הרשאה להתקין אפליקציות שאינן מוכרות"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"למשתמש הזה אין הרשאה להתקין אפליקציות"</string>
     <string name="ok" msgid="7871959885003339302">"אישור"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"אני רוצה לעדכן בכל זאת"</string>
     <string name="manage_applications" msgid="5400164782453975580">"ניהול אפליקציות"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"אין מספיק מקום"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"הסרת התקנה של עדכון"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"הפעילות <xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> היא חלק מהאפליקציה הבאה:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"להסיר את ההתקנה של האפליקציה הזו?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"להסיר את האפליקציה הזו עבור "<b>"כל"</b>" המשתמשים? האפליקציה והנתונים שלה יוסרו עבור "<b>"כל"</b>" המשתמשים במכשיר."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"להסיר את ההתקנה של האפליקציה הזו עבור <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"רוצה להסיר את האפליקציה הזו מפרופיל העבודה?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"שמירת <xliff:g id="SIZE">%1$s</xliff:g> מנתוני האפליקציה."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"למחוק את האפליקציה הזו?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"להסיר את ההתקנה של האפליקציה הזו? השכפול של <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> גם יימחק."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"להסיר את ההתקנה של האפליקציה הזו מהמרחב הפרטי?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"התקנות בתהליכי הסרה"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"הסרות התקנה שנכשלו"</string>
     <string name="uninstalling" msgid="8709566347688966845">"בתהליך הסרת התקנה..."</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"ניהול משתמשים"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"לא ניתן להסיר את ההתקנה של <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"אירעה בעיה בניתוח החבילה."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"‏פעולות התקנה/הסרת התקנה אינן נתמכות ב-Wear."</string>
     <string name="message_staging" msgid="8032722385658438567">"בתהליך הכנת האפליקציה להתקנה…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"לא ידוע"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"לצורכי אבטחה, הטאבלט שלך חסום להתקנת אפליקציות לא מוכרות מהמקור הזה. אפשר לשנות זאת ב\'הגדרות\'."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"נתוני הטאבלט והנתונים האישיים שלך חשופים יותר בפני התקפות על ידי אפליקציות ממקורות לא ידועים. התקנת האפליקציה הזו מהווה את הסכמתך לכך שהאחריות הבלעדית היא שלך במקרה של אובדן נתונים או גרימת נזק לטאבלט בעקבות השימוש באפליקציה."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"נתוני הטלוויזיה והנתונים האישיים שלך חשופים יותר בפני התקפות על ידי אפליקציות ממקורות לא ידועים. התקנת האפליקציה הזו מהווה את הסכמתך לכך שהאחריות הבלעדית היא שלך במקרה של אובדן נתונים או גרימת נזק לטלוויזיה שלך בעקבות השימוש באפליקציה."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"שכפול של <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"המשך"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"הגדרות"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"‏תהליך התקנה/הסרת התקנה של אפליקציות Wear"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"לשחזר את <xliff:g id="APPNAME">%1$s</xliff:g> מ-<xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"תהליך ההורדה של האפליקציה יתחיל ברקע"</string>
     <string name="restore" msgid="8460854736328970444">"שחזור"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"אין חיבור לאינטרנט"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"שחזור האפליקציה יתחיל אוטומטית כשהמכשיר יחובר לאינטרנט"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"משהו השתבש"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"הייתה בעיה בניסיון לשחזר את האפליקציה הזו"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"אין מספיק נפח אחסון פנוי"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"כדי לשחזר את האפליקציה הזו צריך לפנות מקום במכשיר. נפח האחסון הנדרש: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"נדרשת פעולה"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"כדי לשחזר את האפליקציה הזו יש לפעול לפי השלבים הבאים"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> במצב מושבת"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"כדי לשחזר את האפליקציה הזו, צריך להפעיל את <xliff:g id="INSTALLERNAME">%1$s</xliff:g> בהגדרות"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"ההתקנה של <xliff:g id="INSTALLERNAME">%1$s</xliff:g> הוסרה"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"כדי לשחזר את האפליקציה הזו, צריך להתקין את <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"המשך"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"צריך לפנות נפח אחסון"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"הגדרות"</string>
+    <string name="close" msgid="5214897374055647996">"סגירה"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-ja/strings.xml b/packages/PackageInstaller/res/values-ja/strings.xml
index 58e46a6..dd0d00e 100644
--- a/packages/PackageInstaller/res/values-ja/strings.xml
+++ b/packages/PackageInstaller/res/values-ja/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"このユーザーは不明なアプリをインストールできません"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"このユーザーはアプリをインストールできません"</string>
     <string name="ok" msgid="7871959885003339302">"OK"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"更新する"</string>
     <string name="manage_applications" msgid="5400164782453975580">"アプリの管理"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"容量不足"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"アップデートのアンインストール"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> は次のアプリの一部です。"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"このアプリをアンインストールしますか?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"このアプリを"<b>"すべての"</b>"ユーザーからアンインストールしますか?このアプリとそのデータはデバイスの"<b>"すべての"</b>"ユーザーから削除されます。"</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"<xliff:g id="USERNAME">%1$s</xliff:g> さんのアプリをアンインストールしますか?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"このアプリを仕事用プロファイルからアンインストールしますか?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"アプリのデータ(<xliff:g id="SIZE">%1$s</xliff:g>)を保持"</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"このアプリを削除しますか?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"このアプリをアンインストールしますか?<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> のクローンも削除されます。"</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"このアプリをプライベート スペースからアンインストールしますか?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"アンインストールを実行しています"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"エラーになったアンインストール"</string>
     <string name="uninstalling" msgid="8709566347688966845">"アンインストールしています…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"ユーザーを管理"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> をアンインストールできませんでした。"</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"パッケージの解析中に問題が発生しました。"</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Wear ではインストールやアンインストールはできません。"</string>
     <string name="message_staging" msgid="8032722385658438567">"アプリを準備しています…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"不明"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"セキュリティ上の理由から、お使いのタブレットでは現在、この提供元からの不明なアプリをインストールすることはできません。これは [設定] で変更できます。"</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"不明なアプリをインストールするとタブレットや個人データの侵害に対する安全性が低下します。このアプリをインストールすることで、アプリの使用により生じる可能性があるタブレットへの侵害やデータの損失について、ユーザーご自身が単独で責任を負うことに同意することになります。"</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"不明なアプリをインストールするとテレビや個人データの侵害に対する安全性が低下します。このアプリをインストールすることで、アプリの使用により生じる可能性があるテレビへの侵害やデータの損失について、ユーザーご自身が単独で責任を負うことに同意することになります。"</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> のクローン"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"次へ"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"設定"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Wearアプリ インストール/アンインストール"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> から <xliff:g id="APPNAME">%1$s</xliff:g> を復元しますか?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"このアプリのダウンロードをバックグラウンドで開始します"</string>
     <string name="restore" msgid="8460854736328970444">"復元する"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"オフラインです"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"インターネットに接続すると、このアプリは自動的に復元されます"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"エラーが発生しました"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"このアプリを復元しようとしたときに問題が発生しました"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"空き容量が不足しています"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"このアプリを復元するには、このデバイスの空き容量を増やしてください。必要なストレージ: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"必要な対応"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"このアプリを復元するには、次の手順を行います"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> は無効です"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"このアプリを復元するには、設定で <xliff:g id="INSTALLERNAME">%1$s</xliff:g> を有効にしてください"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> はアンインストールされています"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"このアプリを復元するには、<xliff:g id="INSTALLERNAME">%1$s</xliff:g> をインストールする必要があります"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"続行"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"ストレージの消去"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"設定"</string>
+    <string name="close" msgid="5214897374055647996">"閉じる"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-ka/strings.xml b/packages/PackageInstaller/res/values-ka/strings.xml
index bbd63d1..7d4c1fd 100644
--- a/packages/PackageInstaller/res/values-ka/strings.xml
+++ b/packages/PackageInstaller/res/values-ka/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"ამ მომხმარებელს არ შეუძლია უცნობი აპების ინსტალაცია"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"ამ მომხმარებელს არ აქვს აპების ინსტალაციის უფლება"</string>
     <string name="ok" msgid="7871959885003339302">"კარგი"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"მაინც განახლდეს"</string>
     <string name="manage_applications" msgid="5400164782453975580">"აპების მართვა"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"მეხსიერება არასაკმარისია"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"განახლების დეინსტალაცია"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> არის შემდეგი აპის ნაწილი:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"გსურთ ამ აპის დეინსტალაცია?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"გსურთ ამ აპის დეინსტალაცია "<b>"ყველა"</b>" მომხმარებლისთვის? აპლიკაცია და მისი მონაცემები ამოიშლება "<b>"ყველა"</b>" მომხმარებლის პროფილიდან მოწყობილობაზე."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"გსურთ ამ აპის დეინსტალაცია <xliff:g id="USERNAME">%1$s</xliff:g>-ისთვის?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"გსურთ ამ აპის დეინსტალაცია თქვენი სამსახურის პროფილიდან?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"შენარჩუნდეს აპების მონაცემების <xliff:g id="SIZE">%1$s</xliff:g>."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"გსურთ ამ აპის წაშლა?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"გსურთ ამ აპის დეინსტალაცია? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> კლონი ასევე წაიშლება."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"გსურთ ამ აპის დეინსტალაცია თქვენი პირადი სივრციდან?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"გაშვებული დეინსტალაციები"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"შეუსრულებელი დეინსტალაციები"</string>
     <string name="uninstalling" msgid="8709566347688966845">"მიმდინარეობს დეინსტალაცია…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"მომხმარებლების მართვა"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ის დეინსტალაცია ვერ მოხერხდა."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"პაკეტის გაანალიზებისას წარმოიქმნა პრობლემა."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"ინსტალაცია/დეინსტალაცია მხარდაუჭერელია Wear-ზე."</string>
     <string name="message_staging" msgid="8032722385658438567">"მიმდინარეობს აპის შუალედური შენახვა…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"უცნობი"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"თქვენივე უსაფრთხოებისთვის თქვენს ტაბლეტს არ აქვს ამ წყაროდან უცნობი აპების ინსტალაციის ნებართვა. ამის შეცვლა პარამეტრებში შეგიძლიათ."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"თქვენი ტაბლეტი და პერსონალური მონაცემები მეტად დაუცველია უცნობი აპების მხრიდან შეტევების წინაშე. ამ აპის ინსტალაციის შემთხვევაში, თქვენ თანახმა ხართ, პასუხისმგებელი იყოთ მისი გამოყენების შედეგად ტაბლეტისთვის მიყენებულ ზიანსა თუ მონაცემების დაკარგვაზე."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"თქვენი ტელევიზორი და პერსონალური მონაცემები მეტად დაუცველია უცნობი აპების მხრიდან შეტევების წინაშე. ამ აპის ინსტალაციის შემთხვევაში, თქვენ თანახმა ხართ, პასუხისმგებელი იყოთ მისი გამოყენების შედეგად ტელევიზორისთვის მიყენებულ ზიანსა თუ მონაცემების დაკარგვაზე."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> კლონის შექმნა"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"გაგრძელება"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"პარამეტრები"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Wear აპების ინსტალაცია/დეინსტალაცია"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"აღვადგინოთ <xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="INSTALLERNAME">%1$s</xliff:g>-დან?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"ამ აპის ჩამოტვირთვა ფონურ რეჟიმში დაიწყება"</string>
     <string name="restore" msgid="8460854736328970444">"აღდგენა"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"თქვენ ხაზგარეშე რეჟიმში ხართ"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"ეს აპი ავტომატურად აღდგება, როცა დაუკავშირდებით ინტერნეტს"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"წარმოიქმნა შეფერხება"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"ამ აპის აღდგენისას წარმოიქმნა პრობლემა"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"მეხსიერება საკმარისი არ არის"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"ამ აპის აღსადგენად შეგიძლიათ, გამოათავისუფლოთ მეხსიერება ამ მოწყობილობაზე. საჭიროა მეხსიერება: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"საჭიროა მოქმედება"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"ამ აპის აღსადგენად მიჰყევით შემდეგ ნაბიჯებს"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> გამორთულია"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"ამ აპის აღსადგენად ჩართეთ <xliff:g id="INSTALLERNAME">%1$s</xliff:g> პარამეტრებში"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> დეინსტალირებულია"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"ამ აპის აღსადგენად უნდა დააინსტალიროთ <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"გაგრძელება"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"მეხსიერების გასუფთავება"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"პარამეტრები"</string>
+    <string name="close" msgid="5214897374055647996">"დახურვა"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-kk/strings.xml b/packages/PackageInstaller/res/values-kk/strings.xml
index 02843b8..f731bbc 100644
--- a/packages/PackageInstaller/res/values-kk/strings.xml
+++ b/packages/PackageInstaller/res/values-kk/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Бұл пайдаланушы белгісіз қолданбаларды орната алмайды"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Бұл пайдаланушының қолданбаларды орнату рұқсаты жоқ"</string>
     <string name="ok" msgid="7871959885003339302">"Жарайды"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Бәрібір жаңарту"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Қолданбаларды басқару"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Орын жоқ"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Жаңа нұсқаны жою"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> келесі қолданбаның бөлігі:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Осы қолданба жойылсын ба?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Бұл қолданба "<b>"барлық"</b>" пайдаланушылар үшін жойылсын ба? Қолданба және оның деректері құрылғыдағы "<b>"барлық"</b>" пайдаланушылардан өшіріледі."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"<xliff:g id="USERNAME">%1$s</xliff:g> үшін осы қолданба жойылсын ба?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Бұл қолданба жұмыс профиліңізден жойылсын ба?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Қолданба деректерін (<xliff:g id="SIZE">%1$s</xliff:g>) сақтау."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Осы қолданба жойылсын ба?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Осы қолданба жойылсын ба? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> клоны да жойылады."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Осы құрылғыны жеке бөлмеңізден жойғыңыз келе ме?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Орындалып жатқан жою процестері"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Сәтсіз жою әрекеттері"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Жойылуда…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Пайдаланушыларды басқару"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасын жою мүмкін емес."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Пакетті талдау кезінде ақау пайда болды."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Wear жүйесінде \"Орнату/Жою\" әрекеттері қолданылмайды."</string>
     <string name="message_staging" msgid="8032722385658438567">"Қолданба дайындалуда…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Белгісіз"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Қауіпсіздік үшін планшетке бұл дереккөзден белгісіз қолданбаларды орнатуға рұқсат берілмейді. Мұны \"Параметрлер\" бөлімінен өзгертуіңізге болады."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Планшет және жеке деректер белгісіз қолданбалардың шабуылына ұшырауы мүмкін. Бұл қолданбаны орнату арқылы оны пайдалану нәтижесіндегі планшетке келетін залалға немесе деректердің жоғалуына өзіңіз ғана жауапты болатыныңызға келісесіз."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Теледидар және жеке деректер белгісіз қолданбалардың шабуылына ұшырауы мүмкін. Бұл қолданбаны орнату арқылы оны пайдалану нәтижесіндегі теледидарға келетін қандай да бір залалға немесе деректердің жоғалуына өзіңіз ғана жауапты болатыныңызға келісесіз."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> клоны"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Жалғастыру"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Параметрлер"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Wear қолданбасын орнату/жою"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"<xliff:g id="APPNAME">%1$s</xliff:g> қолданбасын <xliff:g id="INSTALLERNAME">%1$s</xliff:g> арқылы қалпына келтіру керек пе?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Бұл қолданба фондық режимде жүктеп алына бастайды."</string>
     <string name="restore" msgid="8460854736328970444">"Қалпына келтіру"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Құрылғыңыз офлайн режимде"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Бұл қолданба құрылғыңыз интернетке қосылғанда автоматты түрде қалпына келеді."</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Бірдеңе дұрыс болмады"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Бұл құрылғыны қалпына келтіру үшін әрекет жасалғанда мәселе туындады."</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Жадта орын жеткіліксіз"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Бұл қолданбаны қалпына келтіргіңіз келсе, осы құрылғыда орын босатуға болады. Қажетті жад көлемі: <xliff:g id="BYTES">%1$s</xliff:g>."</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Әрекет қажет"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Бұл қолданбаны қалпына келтіру үшін келесі қадамдарды орындаңыз."</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> өшірілген"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Бұл қолданбаны қалпына келтіру үшін параметрлерден <xliff:g id="INSTALLERNAME">%1$s</xliff:g> қызметін қосыңыз."</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> жойылған"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Бұл қолданбаны қалпына келтіру үшін орнатқышты (<xliff:g id="INSTALLERNAME">%1$s</xliff:g>) орнатуыңыз керек."</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Жалғастыру"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Жадты тазалау"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Параметрлер"</string>
+    <string name="close" msgid="5214897374055647996">"Жабу"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-km/strings.xml b/packages/PackageInstaller/res/values-km/strings.xml
index bb84976..7ae0ce7 100644
--- a/packages/PackageInstaller/res/values-km/strings.xml
+++ b/packages/PackageInstaller/res/values-km/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"អ្នកប្រើប្រាស់​នេះ​មិនអាច​ដំឡើងកម្មវិធីមិនស្គាល់​​បាន​ទេ"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"មិន​អនុញ្ញាត​ឱ្យអ្នក​ប្រើ​ប្រាស់នេះ​ដំឡើងកម្មវិធីទេ"</string>
     <string name="ok" msgid="7871959885003339302">"យល់ព្រម"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"មិនអីទេ ដំឡើង​កំណែ​ចុះ"</string>
     <string name="manage_applications" msgid="5400164782453975580">"គ្រប់គ្រង​កម្មវិធី"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"អស់​ទំហំផ្ទុក"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"លុប​កំណែ​ថ្មី"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g>​ ​ជា​ផ្នែក​មួយ​នៃ​កម្មវិធី​ដូច​ខាង​ក្រោម​នេះ​៖"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"តើ​អ្នក​ចង់​លុប​កម្មវិធី​នេះ​ដែរទេ?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"តើ​អ្នក​ចង់​លុប​កម្មវិធី​នេះ​សម្រាប់​អ្នកប្រើប្រាស់"<b>"ទាំងអស់"</b>"ដែរទេ? កម្មវិធីនេះ និង​ទិន្នន័យ​របស់​វា​នឹង​ត្រូវ​បាន​លុប​ចេញ​ពី​អ្នកប្រើប្រាស់"<b>"ទាំងអស់"</b>"នៅលើ​ឧបករណ៍​នេះ។"</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"តើ​អ្នក​ចង់​លុប​កម្មវិធី​នេះ​សម្រាប់​អ្នកប្រើប្រាស់ <xliff:g id="USERNAME">%1$s</xliff:g> ដែរទេ?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"តើអ្នក​ចង់លុប​កម្មវិធីនេះ​ពីកម្រងព័ត៌មាន​ការងាររបស់អ្នក​ដែរទេ?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"រក្សាទុក​ទិន្នន័យ​កម្មវិធីទំហំ <xliff:g id="SIZE">%1$s</xliff:g>។"</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"តើអ្នកចង់លុបកម្មវិធីនេះដែរឬទេ?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"តើ​អ្នក​ចង់​លុប​កម្មវិធី​នេះ​ដែរឬទេ? ក្លូន <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ក៏នឹងត្រូវបានលុបផងដែរ។"</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"តើអ្នកចង់លុបកម្មវិធីនេះចេញពី private space របស់អ្នកដែរទេ?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"កំពុង​ដំណើរការ​ការលុប"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"ការលុប​ដែល​បរាជ័យ"</string>
     <string name="uninstalling" msgid="8709566347688966845">"កំពុង​លុប…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"គ្រប់គ្រងអ្នកប្រើប្រាស់"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"មិន​អាច​លុប <xliff:g id="APP_NAME">%1$s</xliff:g> បាន​ទេ។"</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"មាន​បញ្ហា​ក្នុង​ការ​ញែក​​កញ្ចប់។"</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"សកម្មភាព​ដំឡើង/លុបចេញមិនអាចប្រើ​នៅលើ Wear បានទេ។"</string>
     <string name="message_staging" msgid="8032722385658438567">"កំពុងសាកល្បងកម្មវិធី…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"មិនស្គាល់"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"ដើម្បីសុវត្ថិភាពរបស់អ្នក បច្ចុប្បន្នទូរទស្សន៍របស់អ្នកមិនត្រូវបានអនុញ្ញាតឱ្យដំឡើងកម្មវិធីដែលមិនស្គាល់ពីប្រភពនេះទេ។ អ្នកអាច​ប្ដូរវាបាន​នៅក្នុងការ​កំណត់។"</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"ថេប្លេត និងទិន្នន័យផ្ទាល់ខ្លួនរបស់អ្នកងាយនឹងរងគ្រោះពីការវាយប្រហារពីកម្មវិធីដែលមិនស្គាល់។ ប្រសិនបើដំឡើងកម្មវិធីនេះ មានន័យថាអ្នកទទួលខុសត្រូវលើការខូចខាតទាំងឡាយចំពោះថេប្លេត ឬការបាត់បង់ទិន្នន័យរបស់អ្នក ដែលអាចបណ្ដាលមកពីការប្រើប្រាស់កម្មវិធីនេះ។"</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"ទូរទស្សន៍ និងទិន្នន័យផ្ទាល់ខ្លួនរបស់អ្នកងាយនឹងរងគ្រោះពីការវាយប្រហារពីកម្មវិធីដែលមិនស្គាល់។ ប្រសិនបើដំឡើងកម្មវិធីនេះ មានន័យថាអ្នកទទួលខុសត្រូវលើការខូចខាតទាំងឡាយចំពោះទូរទស្សន៍ ឬការបាត់បង់ទិន្នន័យរបស់អ្នក ដែលអាចបណ្ដាលមកពីការប្រើប្រាស់កម្មវិធីនេះ។"</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"ក្លូន <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"បន្ត"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"ការកំណត់"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"ការដំឡើង/ការលុបកម្មវិធីឧបករណ៍​ពាក់​"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"ស្ដារ <xliff:g id="APPNAME">%1$s</xliff:g> ពី <xliff:g id="INSTALLERNAME">%1$s</xliff:g> ឬ?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"កម្មវិធីនេះនឹងចាប់ផ្ដើមទាញយកនៅផ្ទៃខាងក្រោយ"</string>
     <string name="restore" msgid="8460854736328970444">"ស្ដារ"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"អ្នកគ្មាន​អ៊ីនធឺណិត​ទេ"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"កម្មវិធីនេះនឹងស្ដារដោយស្វ័យប្រវត្តិ នៅពេលអ្នកភ្ជាប់អ៊ីនធឺណិត"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"មានអ្វីមួយខុសប្រក្រតី"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"មានបញ្ហាក្នុងការព្យាយាមស្ដារកម្មវិធីនេះ"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"ទំហំផ្ទុក​មិន​គ្រប់គ្រាន់"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"ដើម្បីស្ដារកម្មវិធីនេះ អ្នកត្រូវបង្កើនទំហំផ្ទុកទំនេរនៅលើឧបករណ៍នេះ។ តម្រូវឱ្យមានទំហំផ្ទុក៖ <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"សកម្មភាព​ដែលតម្រូវឱ្យធ្វើ"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"អនុវត្តតាមជំហានបន្ទាប់ ដើម្បីស្ដារកម្មវិធីនេះ"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> ត្រូវបានបិទ"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"ដើម្បីស្ដារកម្មវិធីនេះ សូមបើក <xliff:g id="INSTALLERNAME">%1$s</xliff:g> នៅក្នុងការកំណត់"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> ត្រូវបានលុប"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"ដើម្បីស្ដារកម្មវិធីនេះ អ្នកនឹងត្រូវដំឡើង <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"បន្ត"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"សម្អាត​ទំហំ​ផ្ទុក"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"ការកំណត់"</string>
+    <string name="close" msgid="5214897374055647996">"បិទ"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-kn/strings.xml b/packages/PackageInstaller/res/values-kn/strings.xml
index 476b45d..ec0746d 100644
--- a/packages/PackageInstaller/res/values-kn/strings.xml
+++ b/packages/PackageInstaller/res/values-kn/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"ಈ ಬಳಕೆದಾರರು ಅಪರಿಚಿತ ಆ್ಯಪ್‌ಗಳನ್ನು ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್‌ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"ಆ್ಯಪ್‌ಗಳನ್ನು ಇನ್‌ಸ್ಟಾಲ್‌ ಮಾಡಲು ಈ ಬಳಕೆದಾರರನ್ನು ಅನುಮತಿಸಲಾಗುವುದಿಲ್ಲ"</string>
     <string name="ok" msgid="7871959885003339302">"ಸರಿ"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"ಪರವಾಗಿಲ್ಲ, ಅಪ್‌ಡೇಟ್ ಮಾಡಿ"</string>
     <string name="manage_applications" msgid="5400164782453975580">"ಆ್ಯಪ್ ನಿರ್ವಹಿಸಿ"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"ಸಂಗ್ರಹಣೆ ಖಾಲಿ ಇಲ್ಲ"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"ಅಪ್‌ಡೇಟ್‌ ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಿ"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> ಎಂಬುದು ಕೆಳಗಿನ ಆ್ಯಪ್‌ನ ಭಾಗವಾಗಿದೆ:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"ನೀವು ಈ ಆ್ಯಪ್‌ ಅನ್ನು ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್‌ ಮಾಡಲು ಬಯಸುವಿರಾ?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"ನೀವು "<b>"ಎಲ್ಲಾ"</b>" ಬಳಕೆದಾರರಿಗೂ ಈ ಆ್ಯಪ್‌ ಅನ್ನು ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್‌ ಮಾಡಲು ಬಯಸುವಿರಾ? ಸಾಧನದಲ್ಲಿನ "<b>"ಎಲ್ಲಾ"</b>" ಬಳಕೆದಾರರಿಂದ ಆ್ಯಪ್‌ ಮತ್ತು ಅದರ ಡೇಟಾವನ್ನು ತೆಗೆದುಹಾಕಲಾಗುವುದು."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"<xliff:g id="USERNAME">%1$s</xliff:g> ಬಳಕೆದಾರರಿಗೆ ಈ ಆ್ಯಪ್‌ ಅನ್ನು ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್‌ ಮಾಡಲು ನೀವು ಬಯಸುವಿರಾ?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"ನಿಮ್ಮ ಉದ್ಯೋಗದ ಪ್ರೊಫೈಲ್‌ನಿಂದ ಈ ಆ್ಯಪ್‌ ಅನ್ನು ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಲು ನೀವು ಬಯಸುವಿರಾ?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"ಆ್ಯಪ್ ಡೇಟಾದಲ್ಲಿ <xliff:g id="SIZE">%1$s</xliff:g> ಇರಿಸಿಕೊಳ್ಳಿ."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"ನೀವು ಈ ಆ್ಯಪ್ ಅನ್ನು ಅಳಿಸಲು ಬಯಸುತ್ತೀರಾ?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"ನೀವು ಈ ಆ್ಯಪ್ ಅನ್ನು ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಲು ಬಯಸುತ್ತೀರಾ? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ಕ್ಲೋನ್ ಅನ್ನು ಸಹ ಅಳಿಸಲಾಗುತ್ತದೆ."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"ನಿಮ್ಮ ಖಾಸಗಿ ಸ್ಪೇಸ್‌ನಿಂದ ಈ ಆ್ಯಪ್ ಅನ್ನು ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಲು ನೀವು ಬಯಸುತ್ತೀರಾ?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"ಚಾಲನೆಯಲ್ಲಿರುವ ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್‌ಗಳು"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"ವಿಫಲಗೊಂಡ ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್‌ಗಳು"</string>
     <string name="uninstalling" msgid="8709566347688966845">"ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್‌ ಮಾಡಲಾಗುತ್ತಿದೆ..."</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"ಬಳಕೆದಾರರನ್ನು ನಿರ್ವಹಿಸಿ"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಅನ್ನು ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್‌ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"ಪ್ಯಾಕೇಜ್ ಪಾರ್ಸ್ ಮಾಡುವಲ್ಲಿ ಸಮಸ್ಯೆ ಕಂಡುಬಂದಿದೆ."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Wear ನಲ್ಲಿ ಇನ್‌ಸ್ಟಾಲ್/ಅನ್ಇನ್‌ಸ್ಟಾಲ್ ಕ್ರಿಯೆಗಳು ಬೆಂಬಲಿತವಾಗಿಲ್ಲ."</string>
     <string name="message_staging" msgid="8032722385658438567">"ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಲು ಸಿದ್ಧವಿರುವ ಆ್ಯಪ್…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"ಅಪರಿಚಿತ"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"ನಿಮ್ಮ ಸುರಕ್ಷತೆಯ ದೃಷ್ಟಿಯಿಂದ, ಈ ಮೂಲದಿಂದ ಬಂದಿರುವ ಅಪರಿಚಿತ ಆ್ಯಪ್‌ಗಳನ್ನು ಇನ್‌ಸ್ಟಾಲ್‌ ಮಾಡಲು ಪ್ರಸ್ತುತ ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್‌ಗೆ ಅನುಮತಿಯಿಲ್ಲ. ನೀವು ಇದನ್ನು ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ ಬದಲಾಯಿಸಬಹುದು."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್ ಹಾಗೂ ವೈಯಕ್ತಿಕ ಡೇಟಾ, ಅಪರಿಚಿತ ಆ್ಯಪ್‌ಗಳ ದಾಳಿಗೆ ತುತ್ತಾಗುವ ಸಾಧ್ಯತೆ ಹೆಚ್ಚಾಗಿದೆ. ಈ ಆ್ಯಪ್‌ ಅನ್ನು ಇನ್‌ಸ್ಟಾಲ್‌ ಮಾಡುವ ಮೂಲಕ, ನಿಮ್ಮ ಫೋನ್‌ಗೆ ಯಾವುದೇ ಹಾನಿ ಉಂಟಾದರೆ ಅಥವಾ ಅದರ ಬಳಕೆಯಿಂದ ಡೇಟಾ ನಷ್ಟವಾದರೆ, ಅದಕ್ಕೆ ನೀವೇ ಜವಾಬ್ದಾರರು ಎನ್ನುವುದನ್ನು ಒಪ್ಪಿಕೊಳ್ಳುತ್ತೀರಿ."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"ನಿಮ್ಮ ಟಿವಿ ಹಾಗೂ ವೈಯಕ್ತಿಕ ಡೇಟಾ, ಅಪರಿಚಿತ ಆ್ಯಪ್‌ಗಳ ದಾಳಿಗೆ ತುತ್ತಾಗುವ ಸಾಧ್ಯತೆ ಹೆಚ್ಚಾಗಿದೆ. ಈ ಆ್ಯಪ್‌ ಅನ್ನು ಇನ್‌ಸ್ಟಾಲ್‌ ಮಾಡುವ ಮೂಲಕ, ನಿಮ್ಮ ಟಿವಿಗೆ ಯಾವುದೇ ಹಾನಿ ಉಂಟಾದರೆ ಅಥವಾ ಅದರ ಬಳಕೆಯಿಂದ ಡೇಟಾ ನಷ್ಟವಾದರೆ, ಅದಕ್ಕೆ ನೀವೇ ಜವಾಬ್ದಾರರು ಎನ್ನುವುದನ್ನು ಒಪ್ಪಿಕೊಳ್ಳುತ್ತೀರಿ."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ಕ್ಲೋನ್"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"ಮುಂದುವರಿಸಿ"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"wear ಆ್ಯಪ್‌ಗಳನ್ನು ಇನ್‌ಸ್ಟಾಲ್‌/ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್‌ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> ನಿಂದ <xliff:g id="APPNAME">%1$s</xliff:g> ಅನ್ನು ಮರುಸ್ಥಾಪಿಸಬೇಕೆ?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"ಹಿನ್ನೆಲೆಯಲ್ಲಿ ಡೌನ್‌ಲೋಡ್ ಆಗಲು ಈ ಆ್ಯಪ್ ಪ್ರಾರಂಭವಾಗುತ್ತದೆ"</string>
     <string name="restore" msgid="8460854736328970444">"ಮರುಸ್ಥಾಪಿಸಿ"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"ನೀವು ಆಫ್‌ಲೈನ್‌ನಲ್ಲಿರುವಿರಿ"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"ನೀವು ಇಂಟರ್ನೆಟ್‌ಗೆ ಕನೆಕ್ಟ್ ಮಾಡಿದಾಗ, ಈ ಆ್ಯಪ್ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಮರುಸ್ಥಾಪನೆಯಾಗುತ್ತದೆ"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"ಏನೋ ತಪ್ಪಾಗಿದೆ"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"ಈ ಆ್ಯಪ್ ಅನ್ನು ಮರುಸ್ಥಾಪಿಸಲು ಪ್ರಯತ್ನಿಸುವಾಗ ಸಮಸ್ಯೆ ಕಂಡುಬಂದಿದೆ"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"ಸಾಕಷ್ಟು ಸಂಗ್ರಹಣೆ ಇಲ್ಲ"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"ಈ ಆ್ಯಪ್ ಅನ್ನು ಮರುಸ್ಥಾಪಿಸಲು, ನೀವು ಈ ಸಾಧನದಲ್ಲಿ ಸ್ಥಳಾವಕಾಶವನ್ನು ತೆರವುಗೊಳಿಸಬಹುದು. ಅಗತ್ಯವಿರುವ ಸಂಗ್ರಹಣೆ: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"ಕ್ರಮದ ಅಗತ್ಯವಿದೆ"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"ಈ ಆ್ಯಪ್ ಅನ್ನು ಮರುಸ್ಥಾಪಿಸಲು ಮುಂದಿನ ಹಂತಗಳನ್ನು ಅನುಸರಿಸಿ"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"ಈ ಆ್ಯಪ್ ಅನ್ನು ಮರುಸ್ಥಾಪಿಸಲು, ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ <xliff:g id="INSTALLERNAME">%1$s</xliff:g> ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> ಅನ್ನು ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಲಾಗಿದೆ"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"ಈ ಆ್ಯಪ್ ಅನ್ನು ಮರುಸ್ಥಾಪಿಸಲು, ನೀವು <xliff:g id="INSTALLERNAME">%1$s</xliff:g> ಅನ್ನು ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡುವ ಅಗತ್ಯವಿದೆ"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"ಮುಂದುವರಿಸಿ"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"ಸಂಗ್ರಹಣೆಯನ್ನು ತೆರವುಗೊಳಿಸಿ"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
+    <string name="close" msgid="5214897374055647996">"ಮುಚ್ಚಿರಿ"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-ko/strings.xml b/packages/PackageInstaller/res/values-ko/strings.xml
index 7ae19ac..9fbff25 100644
--- a/packages/PackageInstaller/res/values-ko/strings.xml
+++ b/packages/PackageInstaller/res/values-ko/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"이 사용자는 알 수 없는 앱을 설치할 수 없습니다."</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"이 사용자는 앱을 설치할 권한이 없습니다."</string>
     <string name="ok" msgid="7871959885003339302">"확인"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"업데이트"</string>
     <string name="manage_applications" msgid="5400164782453975580">"앱 관리"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"여유 공간이 없음"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"업데이트 제거"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g>은(는) 다음 앱의 일부입니다."</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"이 앱을 제거하시겠습니까?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119"><b>"모든"</b>" 사용자에 대해 이 앱을 제거하시겠습니까? 기기를 사용하는 "<b>"모든"</b>" 사용자에 대해 애플리케이션 및 데이터가 삭제됩니다."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"<xliff:g id="USERNAME">%1$s</xliff:g>님의 기기에 설치된 앱을 제거하시겠습니까?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"직장 프로필에서 이 앱을 제거하시겠습니까?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"앱 데이터 크기를 <xliff:g id="SIZE">%1$s</xliff:g>로 유지합니다."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"이 앱을 삭제하시겠습니까?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"이 앱을 제거하시겠습니까? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> 클론도 삭제됩니다."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"비공개 스페이스에서 이 앱을 제거하시겠습니까?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"실행 중인 제거 작업"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"실패한 제거 작업"</string>
     <string name="uninstalling" msgid="8709566347688966845">"제거 중..."</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"사용자 관리"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> 앱을 제거할 수 없습니다."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"패키지를 파싱하는 중 문제가 발생했습니다."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Wear에서 지원되지 않는 설치/제거 작업"</string>
     <string name="message_staging" msgid="8032722385658438567">"앱 준비 중…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"알 수 없음"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"보안상의 이유로 이 출처의 알 수 없는 앱을 태블릿에 설치할 수 없습니다. 설정에서 변경할 수 있습니다."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"태블릿과 개인 데이터는 알 수 없는 앱의 공격에 더욱 취약합니다. 이 앱을 설치하면 앱 사용으로 인해 발생할 수 있는 모든 태블릿 손상이나 데이터 손실에 사용자가 책임을 진다는 것에 동의하게 됩니다."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"TV와 개인 데이터는 알 수 없는 앱의 공격에 더욱 취약합니다. 이 앱을 설치하면 앱 사용으로 인해 발생할 수 있는 모든 TV 손상이나 데이터 손실에 사용자가 책임을 진다는 것에 동의하게 됩니다."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> 복제"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"계속"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"설정"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Wear 앱 설치/제거"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g>에서 <xliff:g id="APPNAME">%1$s</xliff:g> 앱을 복원하시겠습니까?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"백그라운드에서 앱이 다운로드되기 시작합니다"</string>
     <string name="restore" msgid="8460854736328970444">"복원"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"오프라인 상태"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"인터넷에 연결되면 이 앱은 자동으로 복원됩니다"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"문제가 발생했습니다"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"이 앱을 복원하려고 시도하던 중 문제가 발생했습니다"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"저장용량 부족"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"이 앱을 사용하려면 이 기기의 여유 공간을 확보해야 합니다 필요한 저장용량: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"조치 필요"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"이 앱을 복원하려면 다음 단계를 따르세요"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> 사용 중지됨"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"이 앱을 복원하려면 설정에서 설치 프로그램(<xliff:g id="INSTALLERNAME">%1$s</xliff:g>)을 사용 설정해야 합니다."</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> 제거됨"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"이 앱을 복원하려면 <xliff:g id="INSTALLERNAME">%1$s</xliff:g>를 설치해야 합니다"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"계속"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"저장용량 비우기"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"설정"</string>
+    <string name="close" msgid="5214897374055647996">"닫기"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-ky/strings.xml b/packages/PackageInstaller/res/values-ky/strings.xml
index faf3df2..b6d3e21 100644
--- a/packages/PackageInstaller/res/values-ky/strings.xml
+++ b/packages/PackageInstaller/res/values-ky/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Бул колдонуучу белгисиз колдонмолорду орното албайт"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Бул колдонуучу колдонмолорду орното албайт"</string>
     <string name="ok" msgid="7871959885003339302">"ЖАРАЙТ"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Баары бир жаңыртылсын"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Колд. башкаруу"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Бош орун жок"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Жаңыртууну чыгарып салуу"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> төмөнкү колдонмонун бөлүгү:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Бул колдонмону чыгарып саласызбы?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Бул колдонмо "<b>"бардык"</b>" колдонуучулардан алынып салынсынбы? Бул колдонмо жана анын дайындары бул түзмөктүн "<b>"бардык"</b>" колдонуучуларынан өчүрүлөт."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Бул колдонмону <xliff:g id="USERNAME">%1$s</xliff:g> үчүн чыгарып саласызбы?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Бул колдонмону жумуш профилиңизден чыгарып саласызбы?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Колдонмонун <xliff:g id="SIZE">%1$s</xliff:g> дайындарын сактоо."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Бул колдонмону өчүрөсүзбү?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Бул колдонмону чыгарып саласызбы? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> клону да өчүрүлөт."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Бул колдонмону жеке чөйрөдөн чыгарып саласызбы?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Чыгарылып салынууда"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Чыгарылып салынбай калгандар"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Чыгарылып салынууда…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Колдонуучуларды башкаруу"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосун чыгарып салуу мүмкүн эмес."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Таңгакты талдоодо маселе келип чыкты."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Орнотуу/чыгарып салуу аракеттери Android Wear\'де колдоого алынбайт."</string>
     <string name="message_staging" msgid="8032722385658438567">"Күтө туруңуз…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Белгисиз"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Коопсуздук максатында, планшетиңизге бул булактан колдонмолорду орнотууга болбойт. Бул параметрди каалаган убакта жөндөөлөрдөн өзгөртө аласыз."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Планшетиңиз жана жеке дайын-даректериңиз белгисиз колдонмолордон зыян тартып калышы мүмкүн. Бул колдонмону орнотуп, аны пайдалануудан улам планшетиңизге кандайдыр бир зыян келтирилсе же дайын-даректериңизды жоготуп алсаңыз, өзүңүз жооптуу болосуз."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Сыналгыңыз жана жеке дайын-даректериңиз белгисиз колдонмолордон зыян тартып калышы мүмкүн. Бул колдонмону орнотуп, аны пайдалануудан улам сыналгыңызга кандайдыр бир зыян келтирилсе же дайын-даректериңизды жоготуп алсаңыз, өзүңүз жооптуу болосуз."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> клону"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Улантуу"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Параметрлер"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Тагынма колдонмолорду орнотуу/чыгаруу"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="INSTALLERNAME">%1$s</xliff:g> платформасынан калыбына келтирилсинби?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Бул колдонмо фондо жүктөлүп алына баштайт"</string>
     <string name="restore" msgid="8460854736328970444">"Калыбына келтирүү"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Интернет байланышыңыз жок"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Интернетке туташканыңызда бул колдонмо автоматтык түрдө калыбына келтирилет"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Бир жерден ката кетти"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Бул колдонмону калыбына келтирүүдө маселе келип чыкты"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Сактагычта орун жетишсиз"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Бул колдонмону калыбына келтирүү үчүн түзмөктө орун бошотуңуз. Сактагыч талап кылынат: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Аракет талап кылынат"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Бул колдонмону калыбына келтирүү үчүн кийинки кадамдарды аткарыңыз"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> өчүрүлгөн"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Бул колдонмону калыбына келтирүү үчүн Параметрлерден <xliff:g id="INSTALLERNAME">%1$s</xliff:g> кызматын иштетиңиз"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> орнотулду"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Бул колдонмону калыбына келтирүү үчүн <xliff:g id="INSTALLERNAME">%1$s</xliff:g> кызматын орнотуп алышыңыз керек"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Улантуу"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Сактагычты тазалоо"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Параметрлер"</string>
+    <string name="close" msgid="5214897374055647996">"Жабуу"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-lo/strings.xml b/packages/PackageInstaller/res/values-lo/strings.xml
index e9b3e8e..d9b33ff 100644
--- a/packages/PackageInstaller/res/values-lo/strings.xml
+++ b/packages/PackageInstaller/res/values-lo/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"ຜູ້ໃຊ້ນີ້ບໍ່ສາມາດຕິດຕັ້ງແອັບທີ່ບໍ່ຮູ້ຈັກໄດ້"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"ຜູ້ໃຊ້ນີ້ບໍ່ໄດ້ຮັບອະນຸຍາດໃຫ້ຕິດຕັ້ງແອັບໄດ້"</string>
     <string name="ok" msgid="7871959885003339302">"ຕົກລົງ"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"ຢືນຢັນການອັບເດດ"</string>
     <string name="manage_applications" msgid="5400164782453975580">"ຈັດການແອັບ"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"ພື້ນທີ່ຫວ່າງບໍ່ພຽງພໍ"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"ຖອນການຕິດຕັ້ງອັບເດດ"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> ແມ່ນ​ສ່ວນ​ໜຶ່ງຂອງແອັບຕໍ່ໄປນີ້:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"ທ່ານຕ້ອງການຖອນການຕິດຕັ້ງແອັບນີ້ບໍ່?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"ທ່ານຕ້ອງການທີ່ຈະຖອນການຕິດຕັ້ງແອັບນີ້ສຳລັງຜູ້ໃຊ້"<b>"ທຸກຄົນ"</b>"ບໍ່? ແອັບພລິເຄຊັນ ແລະ ຂໍ້ມູນຂອງມັນຈະຖືກລຶບອອກຈາກຜູ້ໃຊ້"<b>"ທັງໝົດ"</b>"ໃນອຸປະກອນນີ້."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"ທ່ານ​ຕ້ອງ​ການ​ຖອນ​ການ​ຕິດ​ຕັ້ງ​ແອັບ​ນີ້​ສຳ​ລັບ​ຜູ້​ໃຊ້ <xliff:g id="USERNAME">%1$s</xliff:g> ບໍ່?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"ທ່ານຕ້ອງການຖອນການຕິດຕັ້ງແອັບນີ້ຈາກ​ໂປຣ​ໄຟລ໌​ບ່ອນ​ເຮັດ​ວຽກບໍ?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"ຮັກສາຂະໜາດຂໍ້ມູນແອັບ <xliff:g id="SIZE">%1$s</xliff:g> ໄວ້."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"ທ່ານຕ້ອງການລຶບແອັບນີ້ບໍ?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"ທ່ານຕ້ອງການຖອນການຕິດຕັ້ງແອັບນີ້ບໍ່? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ໂຄລນຈະຖືກລຶບນຳ."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"ທ່ານຕ້ອງການຖອນການຕິດຕັ້ງແອັບນີ້ຈາກພື້ນທີ່ສ່ວນຕົວຂອງທ່ານບໍ?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"ກຳລັງຖອນການຕິດຕັ້ງ"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"ຖອນການຕິດຕັ້ງບໍ່ສຳເລັດ"</string>
     <string name="uninstalling" msgid="8709566347688966845">"ກຳລັງຖອນການຕິດຕັ້ງ..."</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"ຈັດການຜູ້ໃຊ້"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ່ສາມາດຖອນອອກໄດ້."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"ເກີດບັນຫາໃນການແຍກວິເຄາະແພັກເກດ."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"ຕິດຕັ້ງ/ຖອນການຕິດຕັ້ງ ຄຳສັ່ງທີ່ບໍ່ຮອງຮັບຢູ່ Wear."</string>
     <string name="message_staging" msgid="8032722385658438567">"ກຳລັງຮຽງແອັບ…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"ບໍ່ຮູ້ຈັກ"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"ເພື່ອຄວາມປອດໄພຂອງທ່ານ, ຕອນນີ້ແທັບເລັດຂອງທ່ານບໍ່ອະນຸຍາດໃຫ້ຕິດຕັ້ງແອັບທີ່ບໍ່ຮູ້ຈັກຈາກແຫຼ່ງທີ່ມານີ້ໄດ້. ທ່ານສາມາດປ່ຽນສິ່ງນີ້ໄດ້ໃນການຕັ້ງຄ່າ."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"ແທັບເລັດ ແລະ ຂໍ້ມູນສ່ວນຕົວຂອງທ່ານອາດຖືກໂຈມຕີໄດ້ໂດຍແອັບທີ່ບໍ່ຮູ້ຈັກ. ໂດຍການຕິດຕັ້ງແອັບນີ້, ແມ່ນທ່ານຍອມຮັບວ່າທ່ານຈະຮັບຜິດຊອບຕໍ່ຄວາມເສຍຫາຍໃດໆກໍຕາມທີ່ເກີດຂຶ້ນຕໍ່ໂທລະທັດຂອງທ່ານ ຫຼື ການສູນເສຍຂໍ້ມູນທີ່ອາດເກີດຈາກການນຳໃຊ້ມັນ."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"ໂທລະທັດ ແລະ ຂໍ້ມູນສ່ວນຕົວຂອງທ່ານອາດຖືກໂຈມຕີໄດ້ໂດຍແອັບທີ່ບໍ່ຮູ້ຈັກ. ໂດຍການຕິດຕັ້ງແອັບນີ້, ແມ່ນທ່ານຍອມຮັບວ່າທ່ານຈະຮັບຜິດຊອບຕໍ່ຄວາມເສຍຫາຍໃດໆກໍຕາມທີ່ເກີດຂຶ້ນຕໍ່ໂທລະທັດຂອງທ່ານ ຫຼື ການສູນເສຍຂໍ້ມູນທີ່ອາດເກີດຈາກການນຳໃຊ້ມັນ."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ໂຄລນ"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"ສືບຕໍ່"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"ການຕັ້ງຄ່າ"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"ການຕິດຕັ້ງ/ຖອນການຕິດຕັ້ງແອັບ Wear"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"ກູ້ຄືນ <xliff:g id="APPNAME">%1$s</xliff:g> ຈາກ <xliff:g id="INSTALLERNAME">%1$s</xliff:g> ບໍ?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"ແອັບນີ້ຈະເລີ່ມດາວໂຫຼດໃນພື້ນຫຼັງ"</string>
     <string name="restore" msgid="8460854736328970444">"ກູ້ຄືນ"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"ທ່ານອອບລາຍຢູ່"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"ແອັບນີ້ຈະກູ້ຄືນໂດຍອັດຕະໂນມັດເມື່ອທ່ານເຊື່ອມຕໍ່ກັບອິນເຕີເນັດ"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"ມີບາງຢ່າງຜິດພາດເກີດຂຶ້ນ"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"ເກີດບັນຫາໃນລະຫວ່າງທີ່ພະຍາຍາມກູ້ຄືນແອັບນີ້"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"ບ່ອນຈັດເກັບຂໍ້ມູນບໍ່ພຽງພໍ"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"ເພື່ອກູ້ຄືນແອັບນີ້, ທ່ານສາມາດເພີ່ມພື້ນທີ່ຫວ່າງໃນອຸປະກອນນີ້ໄດ້. ໂດຍຈະຕ້ອງໃຊ້ບ່ອນຈັດເກັບຂໍ້ມູນ: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"ຕ້ອງດຳເນີນການ"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"ປະຕິບັດຕາມຂັ້ນຕອນຕໍ່ໄປເພື່ອກູ້ຄືນແອັບນີ້"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> ຖືກປິດການນຳໃຊ້"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"ເພື່ອກູ້ແອັບນີ້ຄືນມາ, ໃຫ້ເປີດການນຳໃຊ້ <xliff:g id="INSTALLERNAME">%1$s</xliff:g> ໃນການຕັ້ງຄ່າ"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> ຖືກຖອນການຕິດຕັ້ງ"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"ເພື່ອກູ້ຄືນແອັບນີ້, ທ່ານຈະຕ້ອງຕິດຕັ້ງ <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"ສືບຕໍ່"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"ລຶບລ້າງບ່ອນຈັດເກັບຂໍ້ມູນ"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"ການຕັ້ງຄ່າ"</string>
+    <string name="close" msgid="5214897374055647996">"ປິດ"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-lt/strings.xml b/packages/PackageInstaller/res/values-lt/strings.xml
index 654dee0..b5ae480 100644
--- a/packages/PackageInstaller/res/values-lt/strings.xml
+++ b/packages/PackageInstaller/res/values-lt/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Šis naudotojas negali diegti nežinomų programų"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Šiam naudotojui neleidžiama diegti programų"</string>
     <string name="ok" msgid="7871959885003339302">"Gerai"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Vis tiek atnaujinti"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Tvark. progr."</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Nėra vietos"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Pašalinti naujinį"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"Veikla „<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g>“ yra toliau nurodytos programos dalis."</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Ar norite pašalinti šią programą?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Ar norite pašalinti šią programą "<b>"visiems"</b>" naudotojams? Programa ir jos duomenys bus pašalinti "<b>"visiems"</b>" įrenginio naudotojams."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Ar norite pašalinti šią naudotojo <xliff:g id="USERNAME">%1$s</xliff:g> programą?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Ar norite pašalinti šią programą iš savo darbo profilio?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Palikti <xliff:g id="SIZE">%1$s</xliff:g> programų duomenų."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Ar norite ištrinti šią programą?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Ar norite pašalinti šią programą? „<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>“ kopija taip pat bus ištrinta."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Ar norite pašalinti šią programą iš privačios erdvės?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Vykdomi pašalinimai"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Nepavykę pašalinimai"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Pašalinama…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Tvarkyti naudotojus"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"Nepavyko pašalinti „<xliff:g id="APP_NAME">%1$s</xliff:g>“."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Analizuojant paketą kilo problema."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Diegimo / pašalinimo veiksmai nepalaikomi sistemoje „Wear“."</string>
     <string name="message_staging" msgid="8032722385658438567">"Programa pateikiama etapais…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Nežinoma"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Saugos sumetimais šiuo metu planšetiniame kompiuteryje neleidžiama diegti nežinomų programų iš šio šaltinio. Tai galite pakeisti nustatymuose."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Planšetinis kompiuteris ir asmens duomenys labiau pažeidžiami įdiegus nežinomų programų. Įdiegdami šią programą sutinkate, kad patys esate atsakingi už žalą planšetiniam kompiuteriui arba prarastus duomenis dėl šios programos naudojimo."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"TV ir asmens duomenys labiau pažeidžiami įdiegus nežinomų programų. Įdiegdami šią programą sutinkate, kad patys esate atsakingi už žalą TV arba prarastus duomenis dėl šios programos naudojimo."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"„<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>“ kopija"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Tęsti"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Nustatymai"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Įdiegiamos / pašalinamos „Wear“ program."</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Atkurti „<xliff:g id="APPNAME">%1$s</xliff:g>“ iš „<xliff:g id="INSTALLERNAME">%1$s</xliff:g>“?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Šios programos atsisiuntimas bus pradėtas fone"</string>
     <string name="restore" msgid="8460854736328970444">"Atkurti"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Esate neprisijungę"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Ši programa bus automatiškai atkurta, kai prisijungsite prie interneto"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Kažkas nepavyko"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Bandant atkurti šią programą iškilo problema"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Trūksta saugyklos vietos"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Kad atkurtumėte šią programą, galite atlaisvinti vietos šiame įrenginyje. Reikia saugyklos vietos: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Būtina imtis veiksmų"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Atlikite toliau nurodytus veiksmus, kad atkurtumėte šią programą"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"„<xliff:g id="INSTALLERNAME">%1$s</xliff:g>“ išjungta"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Kad atkurtumėte šią programą, įgalinkite „<xliff:g id="INSTALLERNAME">%1$s</xliff:g>“ nustatymuose"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"„<xliff:g id="INSTALLERNAME">%1$s</xliff:g>“ pašalinta"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Kad atkurtumėte šią programą, turėsite įdiegti „<xliff:g id="INSTALLERNAME">%1$s</xliff:g>“"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Tęsti"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Išvalyti saugyklą"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Nustatymai"</string>
+    <string name="close" msgid="5214897374055647996">"Uždaryti"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-lv/strings.xml b/packages/PackageInstaller/res/values-lv/strings.xml
index 2d319fc..61b5392 100644
--- a/packages/PackageInstaller/res/values-lv/strings.xml
+++ b/packages/PackageInstaller/res/values-lv/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Šis lietotājs nevar instalēt nezināmas lietotnes"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Šim lietotājam nav atļauts instalēt lietotnes"</string>
     <string name="ok" msgid="7871959885003339302">"Labi"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Tik un tā atjaunināt"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Pārv. lietotnes"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Nav brīvas vietas"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Atinstalēt atjauninājumu"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> ir daļa no šādas lietotnes:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Vai vēlaties atinstalēt šo lietotni?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Vai vēlaties atinstalēt šo lietotni "<b>"visiem"</b>" lietotājiem? Šī lietojumprogramma un tās dati tiks noņemti no "<b>"visiem"</b>" ierīces lietotāju kontiem."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Vai vēlaties atinstalēt šo lietotni lietotājam <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Vai vēlaties atinstalēt šo lietotni no sava darba profila?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Iegūstiet <xliff:g id="SIZE">%1$s</xliff:g> (lietotnes dati)."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Vai vēlaties izdzēst šo lietotni?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Vai vēlaties atinstalēt šo lietotni? Tiks izdzēsts arī lietotnes <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> klons."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Vai vēlaties atinstalēt šo lietotni no savas privātās mapes?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Pašreizējās atinstalēšanas operācijas"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Nesekmīgi atinstalēšanas mēģinājumi"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Notiek atinstalēšana…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Pārvaldīt lietotājus"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"Lietotni <xliff:g id="APP_NAME">%1$s</xliff:g> nevarēja atinstalēt."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Parsējot pakotni, radās problēma."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Operētājsistēmā Wear netiek atbalstīta instalēšana/atinstalēšana."</string>
     <string name="message_staging" msgid="8032722385658438567">"Lietotne tiek izstādīta…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Nezināma"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Drošības apsvērumu dēļ jūsu planšetdatorā pašlaik nav atļauts instalēt nezināmas lietotnes no šī avota. Jūs varat to mainīt iestatījumos."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Jūsu planšetdators un personas dati ir neaizsargātāki pret uzbrukumiem no nezināmām lietotnēm. Instalējot šo lietotni, jūs piekrītat, ka esat atbildīgs par planšetdatora bojājumiem vai datu zudumu, kas var rasties lietotnes dēļ."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Jūsu televizors un personas dati ir neaizsargātāki pret uzbrukumiem no nezināmām lietotnēm. Instalējot šo lietotni, jūs piekrītat, ka esat atbildīgs par televizora bojājumiem vai datu zudumu, kas var rasties lietotnes dēļ."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Lietotnes <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> klons"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Tālāk"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Iestatījumi"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Wear lietotņu instalēšana/atinstalēšana"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Vai atjaunot lietotni <xliff:g id="APPNAME">%1$s</xliff:g> no <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Fonā tiks sākta šīs lietotnes lejupielāde."</string>
     <string name="restore" msgid="8460854736328970444">"Atjaunot"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Jūs esat bezsaistē"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Šī lietotne tiks automātiski atjaunota, kad izveidosiet savienojumu ar internetu."</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Radās problēma"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Mēģinot atjaunot šo lietotni, radās problēma."</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Krātuvē nepietiek vietas"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Lai atjaunotu šo lietotni, jums ir jāatbrīvo vieta ierīces krātuvē. Nepieciešamā vieta: <xliff:g id="BYTES">%1$s</xliff:g>."</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Nepieciešamā darbība"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Veiciet tālāk minētās darbības, lai atjaunotu šo lietotni."</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"Programma <xliff:g id="INSTALLERNAME">%1$s</xliff:g> ir atspējota"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Lai atjaunotu šo lietotni, iestatījumos iespējojiet programmu <xliff:g id="INSTALLERNAME">%1$s</xliff:g>."</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"Programma <xliff:g id="INSTALLERNAME">%1$s</xliff:g> ir atinstalēta"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Lai atjaunotu šo lietotni, jums ir jāinstalē programma <xliff:g id="INSTALLERNAME">%1$s</xliff:g>."</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Turpināt"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Notīrīt krātuvi"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Iestatījumi"</string>
+    <string name="close" msgid="5214897374055647996">"Aizvērt"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-mk/strings.xml b/packages/PackageInstaller/res/values-mk/strings.xml
index e02c3c5..300ef67 100644
--- a/packages/PackageInstaller/res/values-mk/strings.xml
+++ b/packages/PackageInstaller/res/values-mk/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Корисников не може да инсталира непознати апликации"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"На корисников не му е дозволено да инсталира апликации"</string>
     <string name="ok" msgid="7871959885003339302">"Во ред"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Сепак ажурирај"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Управување со апликациите"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Нема простор"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Деинсталирајте ажурирање"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> е дел од следната апликација:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Дали сакате да ја деинсталирате оваа апликација?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Дали сакате да ја деинсталирате оваа апликација за "<b>"сите"</b>" корисници? Апликацијата и нејзините податоци ќе се отстранат од "<b>"сите"</b>" корисници на уредот."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Дали сакате да ја деинсталирате апликацијава за корисникот <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Дали сакате да ја деинсталирате апликацијава од работниот профил?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Задржи <xliff:g id="SIZE">%1$s</xliff:g> податоци на апликацијата."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Дали сакате да ја избришете оваа апликација?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Дали сакате да ја деинсталирате оваа апликација? Ќе се избрише и клонот на <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Дали сакате да ја деинсталирате апликацијава од вашиот „Приватен простор“?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Деинсталации во тек"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Неуспешни деинсталации"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Се деинсталира…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Управувај со корисници"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> не може да се деинсталира."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Настана проблем при анализирањето на пакетот."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Дејствата „Инсталирај/деинсталирај“ не се поддржани на Wear."</string>
     <string name="message_staging" msgid="8032722385658438567">"Апликацијата се поставува…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Непозната"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"За ваша безбедност, таблетот нема дозвола за инсталирање непознати апликации од изворов во моментов. Ова може да го промените во „Поставки“."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Таблетот и личните податоци се поподложни на напади од апликации од непознати извори. Ако ја инсталирате апликацијава, се согласувате дека сте одговорни за каква било штета на таблетот или загуба на податоци поради нејзиното користење."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Телевизорот и личните податоци се поподложни на напади од апликации од непознати извори. Ако ја инсталирате апликацијава, се согласувате дека сте одговорни за каква било штета на телевизорот или загуба на податоци поради нејзиното користење."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Клон на <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Продолжи"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Поставки"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Се инсталираат/деинсталираат аплик. Wear"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Да се врати <xliff:g id="APPNAME">%1$s</xliff:g> од <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Апликацијава ќе почне да се презема во заднина"</string>
     <string name="restore" msgid="8460854736328970444">"Враќање"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Офлајн сте"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Апликацијава ќе се врати автоматски кога ќе се поврзете на интернет"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Нешто тргна наопаку"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Се јави проблем при обидот за враќање на апликацијава"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Нема доволно простор"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"За да ја вратите апликацијава, може да ослободите простор на уредов. Потребен простор: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Потребно е дејство"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Следете ги следниве чекори за да ја вратите апликацијава"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"Оневозможено: <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"За да ја вратите апликацијава, овозможете <xliff:g id="INSTALLERNAME">%1$s</xliff:g> во „Поставки“"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"Деинсталирано: <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"За да ја вратите апликацијава, треба да инсталирате <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Продолжете"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Ослободете простор"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Поставки"</string>
+    <string name="close" msgid="5214897374055647996">"Затворете"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-ml/strings.xml b/packages/PackageInstaller/res/values-ml/strings.xml
index 2e5dcfb..7f071f6 100644
--- a/packages/PackageInstaller/res/values-ml/strings.xml
+++ b/packages/PackageInstaller/res/values-ml/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"ഈ ഉപയോക്താവിന്, അജ്ഞാത ആപ്പുകൾ ഇൻസ്‌റ്റാൾ ചെയ്യാനാവില്ല"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"ആപ്പുകൾ ഇൻ‌സ്‌റ്റാൾ ചെയ്യാൻ ഈ ഉപയോക്താവിന് അനുവാദമില്ല"</string>
     <string name="ok" msgid="7871959885003339302">"ശരി"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"എന്തായാലും അപ്‌ഡേറ്റ് ചെയ്യുക"</string>
     <string name="manage_applications" msgid="5400164782453975580">"ആപ്പുകൾ മാനേജ് ചെയ്യുക"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"ഇടമില്ല"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"അപ്‌ഡേറ്റ്, അൺ ഇ‌ൻസ്‌റ്റാൾ ചെയ്യുക"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g>, ഇനിപ്പറയുന്ന ആപ്പിന്റെ ഭാഗമാണ് :"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"ഈ ആപ്പ് അൺ ഇൻസ്‌റ്റാൾ ചെയ്യണോ?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"ഈ അപ്പ് "<b>"എല്ലാ"</b>" ഉപയോക്താക്കൾക്കുമായി അൺ ഇൻസ്‌റ്റാൾ ചെയ്യണോ? ഉപകരണത്തിലെ "<b>"എല്ലാ"</b>" ഉപയോക്താക്കളിൽ നിന്നും ആപ്പും അതിന്റെ ഡാറ്റയും നീക്കം ചെയ്യപ്പെടും."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"<xliff:g id="USERNAME">%1$s</xliff:g> എന്ന ഉപയോക്താവിനായി ഈ ആപ്പ് അൺ ഇൻസ്‌റ്റാൾ ചെയ്യണോ?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"നിങ്ങളുടെ ഔദ്യോഗിക പ്രൊഫൈലിൽ നിന്ന് ഈ ആപ്പ് അൺ ഇൻസ്‌റ്റാൾ ചെയ്യണോ?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"<xliff:g id="SIZE">%1$s</xliff:g> ആപ്പ് ഡാറ്റ വയ്ക്കുക."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"ഈ ആപ്പ് ഇല്ലാതാക്കണോ?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"ഈ ആപ്പ് അൺഇൻസ്റ്റാൾ ചെയ്യണോ? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ക്ലോൺ ചെയ്യലും ഇല്ലാതാക്കും."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"നിങ്ങളുടെ സ്വകാര്യ സ്‌പെയ്‌സിൽ നിന്ന് ഈ ആപ്പ് അൺഇൻസ്റ്റാൾ ചെയ്യണോ?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"നിലവിൽ അൺഇൻസ്‌റ്റാൾ ചെയ്യുന്നവ"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"അൺ ഇൻസ്‌റ്റാൾ ചെയ്യാൻ കഴിയാഞ്ഞവ"</string>
     <string name="uninstalling" msgid="8709566347688966845">"അണ്‍‌ ഇൻസ്‌റ്റാൾ ചെയ്യുന്നു..."</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"ഉപയോക്താക്കളെ നിയന്ത്രിക്കുക"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> അൺ ഇൻസ്‌റ്റാൾ ചെയ്യാനായില്ല."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"പാക്കേജ് വിശകലനം ചെയ്യുന്നതിൽ ഒരു പ്രശ്‌നമുണ്ടായി."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"ഇൻസ്‌റ്റാൾ/അൺഇൻസ്‌റ്റാൾ ചെയ്യുന്നത് Wear പിന്തുണയ്‌ക്കുന്നില്ല."</string>
     <string name="message_staging" msgid="8032722385658438567">"ആപ്പ് തയ്യാറാക്കുന്നു…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"അജ്ഞാതം"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"നിങ്ങളുടെ സുരക്ഷയ്‌ക്ക്, ഈ ഉറവിടത്തിൽ നിന്നുള്ള അജ്ഞാതമായ ആപ്പുകൾ ഇൻസ്‌റ്റാൾ ചെയ്യാൻ നിലവിൽ നിങ്ങളുടെ ടാബ്‌ലെറ്റിന് അനുമതിയില്ല. നിങ്ങൾക്ക് ഇത് ക്രമീകരണത്തിൽ മാറ്റാം."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"അജ്ഞാതമായ ആപ്പുകളാൽ നിങ്ങളുടെ ടാബ്‌ലെറ്റും വ്യക്തിഗത ഡാറ്റയും ആക്രമിക്കപ്പെടാനുള്ള സാധ്യത വളരെ കൂടുതലാണ്. ഈ ആപ്പ് ഇൻസ്‌റ്റാൾ ചെയ്യുന്നതിലൂടെ, ഇത് ഉപയോഗിക്കുന്നതിനാൽ നിങ്ങളുടെ ടാബ്‌ലെറ്റിന് സംഭവിച്ചേക്കാവുന്ന ഏത് നാശനഷ്‌ടത്തിന്റെയും അല്ലെങ്കിൽ ഡാറ്റാ നഷ്‌ടത്തിന്റെയും ഉത്തരവാദിത്തം നിങ്ങൾക്കായിരിക്കുമെന്ന് അംഗീകരിക്കുന്നു."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"അജ്ഞാതമായ ആപ്പുകളാൽ നിങ്ങളുടെ ടിവിയും വ്യക്തിഗത ഡാറ്റയും ആക്രമിക്കപ്പെടാനുള്ള സാധ്യത വളരെ കൂടുതലാണ്. ഈ ആപ്പ് ഇൻസ്‌റ്റാൾ ചെയ്യുന്നതിലൂടെ, ഇത് ഉപയോഗിക്കുന്നതിനാൽ നിങ്ങളുടെ ടിവിക്ക് സംഭവിച്ചേക്കാവുന്ന ഏത് നാശനഷ്‌ടത്തിന്റെയും അല്ലെങ്കിൽ ഡാറ്റാ നഷ്‌ടത്തിന്റെയും ഉത്തരവാദിത്തം നിങ്ങൾക്കായിരിക്കുമെന്ന് അംഗീകരിക്കുന്നു."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ക്ലോൺ ചെയ്യൽ"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"തുടരുക"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"ക്രമീകരണം"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Wear ആപ്പ് ഇൻസ്‌റ്റാൾ/അൺ ഇൻസ്‌റ്റാൾ ചെയ്യുന്നു"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> എന്നതിൽ നിന്ന് <xliff:g id="APPNAME">%1$s</xliff:g> പുനഃസ്ഥാപിക്കണോ?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"പശ്ചാത്തലത്തിൽ ഈ ആപ്പ് ഡൗൺലോഡ് ചെയ്ത് തുടങ്ങും"</string>
     <string name="restore" msgid="8460854736328970444">"പുനഃസ്ഥാപിക്കുക"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"നിങ്ങൾ ഓഫ്‌ലൈനാണ്"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"നിങ്ങൾ ഇന്റർനെറ്റിലേക്ക് കണക്റ്റ് ചെയ്തിരിക്കുമ്പോൾ, ഈ ആപ്പ് സ്വയമേവ പുനഃസ്ഥാപിക്കും"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"എന്തോ കുഴപ്പമുണ്ടായി"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"ഈ ആപ്പ് പുനഃസ്ഥാപിക്കുന്നതിൽ ഒരു പ്രശ്നമുണ്ടായി"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"മതിയായ സ്‌റ്റോറേജ് ഇല്ല"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"ഈ ആപ്പ് പുനഃസ്ഥാപിക്കുന്നതിന്, ഈ ഉപകരണത്തിൽ ഇടം സൃഷ്ടിക്കാം. ആവശ്യമായ സ്‌റ്റോറേജ്: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"നടപടി ആവശ്യമാണ്"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"ഈ ആപ്പ് പുനഃസ്ഥാപിക്കാൻ തുടർന്നുള്ള ഘട്ടങ്ങൾ പാലിക്കുക"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> പ്രവർത്തനരഹിതമാക്കി"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"ഈ ആപ്പ് പുനഃസ്ഥാപിക്കുന്നതിന്, ക്രമീകരണത്തിൽ <xliff:g id="INSTALLERNAME">%1$s</xliff:g> പ്രവർത്തനക്ഷമമാക്കുക"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> അൺഇൻസ്റ്റാൾ ചെയ്തു"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"ഈ ആപ്പ് പുനഃസ്ഥാപിക്കുന്നതിന്, നിങ്ങൾ <xliff:g id="INSTALLERNAME">%1$s</xliff:g> ഇൻസ്റ്റാൾ ചെയ്യേണ്ടതുണ്ട്"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"തുടരുക"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"സ്‌റ്റോറേജ് മായ്‌ക്കുക"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"ക്രമീകരണം"</string>
+    <string name="close" msgid="5214897374055647996">"അടയ്‌ക്കുക"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-mn/strings.xml b/packages/PackageInstaller/res/values-mn/strings.xml
index 5deda94..35beb14 100644
--- a/packages/PackageInstaller/res/values-mn/strings.xml
+++ b/packages/PackageInstaller/res/values-mn/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Энэ хэрэглэгч тодорхойгүй апп суулгах боломжгүй"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Энэ хэрэглэгч нь апп суулгах зөвшөөрөлгүй байна"</string>
     <string name="ok" msgid="7871959885003339302">"ОК"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Ямартай ч шинэчлэх"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Аппуудыг удирдах"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Орон зай дутагдаж байна"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Шинэчлэлтийг устгах"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> нь дараах аппын хэсэг болно:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Та энэ аппыг устгахыг хүсэж байна уу?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Та энэ аппыг "<b>"бүх"</b>" хэрэглэгчээс устгахыг хүсэж байна уу? Апп болон доторх өгөгдлийг төхөөрөмж дээрх "<b>"бүх"</b>" хэрэглэгчээс устгана."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Та энэ аппыг <xliff:g id="USERNAME">%1$s</xliff:g> хэрэглэгчийн өмнөөс устгахыг хүсэж байна уу?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Та энэ аппыг ажлын профайлаасаа устгахыг хүсэж байна уу?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Аппын өгөгдлийн <xliff:g id="SIZE">%1$s</xliff:g>-г үлдээнэ үү."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Та энэ аппыг устгахыг хүсэж байна уу?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Та энэ аппыг устгахыг хүсэж байна уу? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-н хувилалыг мөн устгана."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Та энэ аппыг хувийн орон зайнаасаа устгахдаа итгэлтэй байна уу?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Устгаж байна"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Устгаж чадсангүй"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Устгаж байна…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Хэрэглэгчдийг удирдах"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g>-г устгаж чадсангүй."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Багцыг шинжлэхэд алдаа гарсан."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Андройд Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Wear-д суулгах/устгах үйлдлийг дэмждэггүй."</string>
     <string name="message_staging" msgid="8032722385658438567">"Аппыг байршуулж байна…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Тодорхойгүй"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Таны аюулгүй байдлыг хангах үүднээс таны таблетыг одоогоор энэ эх сурвалжаас тодорхойгүй аппууд суулгахыг зөвшөөрөөгүй. Та үүнийг Тохиргоо хэсэгт өөрчлөх боломжтой."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Таны таблет болон хувийн өгөгдөл тодорхойгүй апп суулгасан тохиолдолд гэмтэж болзошгүй. Энэ аппыг суулгаснаар үүнийг ашигласнаас үүдэн таны таблетад гэмтэл гарах, эсвэл өгөгдөл устах зэрэг эрсдэлийг хариуцна гэдгээ зөвшөөрч байна."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Таны ТВ болон хувийн өгөгдөл тодорхойгүй апп суулгасан тохиолдолд гэмтэж болзошгүй. Энэ аппыг суулгаснаар үүнийг ашигласнаас үүдэн таны ТВ-д гэмтэл гарах, эсвэл өгөгдөл устах зэрэг эрсдэлийг хариуцна гэдгээ зөвшөөрч байна."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> клон"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Үргэлжлүүлэх"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Тохиргоо"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Wear аппуудыг суулгаж/устгаж байна"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"<xliff:g id="APPNAME">%1$s</xliff:g>-г <xliff:g id="INSTALLERNAME">%1$s</xliff:g>-с сэргээх үү?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Энэ аппыг дэвсгэрт татаж эхэлнэ"</string>
     <string name="restore" msgid="8460854736328970444">"Сэргээх"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Та офлайн байна"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Таныг интернэтэд холбогдсон үед энэ аппыг автоматаар сэргээнэ"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Ямар нэг алдаа гарлаа"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Энэ аппыг сэргээхээр оролдоход асуудал гарлаа"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Хангалттай хадгалах сан байхгүй"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Энэ аппыг сэргээхийн тулд та энэ төхөөрөмжид сул зай гаргах боломжтой. Шаардлагатай хадгалах сан: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Арга хэмжээ авах шаардлагатай"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Энэ аппыг сэргээхийн тулд дараах алхмуудыг дагана уу"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g>-г идэвхгүй болгосон"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Энэ аппыг сэргээхийн тулд Тохиргоонд <xliff:g id="INSTALLERNAME">%1$s</xliff:g>-г идэвхжүүлнэ үү"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g>-г устгасан"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Энэ аппыг сэргээхийн тулд та <xliff:g id="INSTALLERNAME">%1$s</xliff:g>-г суулгах шаардлагатай"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Үргэлжлүүлэх"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Хадгалах санг цэвэрлэх"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Тохиргоо"</string>
+    <string name="close" msgid="5214897374055647996">"Хаах"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-mr/strings.xml b/packages/PackageInstaller/res/values-mr/strings.xml
index 53ca403..44a0e27 100644
--- a/packages/PackageInstaller/res/values-mr/strings.xml
+++ b/packages/PackageInstaller/res/values-mr/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"या वापरकर्त्याद्वारे अज्ञात अ‍ॅप्स इंस्टॉल केली जाऊ शकत नाहीत"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"या वापरकर्त्याला अ‍ॅप्स इंस्टॉल करण्याची अनुमती नाही"</string>
     <string name="ok" msgid="7871959885003339302">"ओके"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"तरीही अपडेट करा"</string>
     <string name="manage_applications" msgid="5400164782453975580">"अ‍ॅप्स व्यवस्थापन"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"जागा संपली"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"अपडेट अनइंस्टॉल करा"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> खालील ॲपचा भाग आहे:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"तुम्हाला हे अ‍ॅप अनइंस्टॉल करायचे आहे का?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"तुम्हाला हे अ‍ॅप "<b>"सर्व"</b>" वापरकर्त्यांसाठी अनइंस्टॉल करायचे आहे का? अ‍ॅप्लिकेशन आणि त्याचा डेटा डिव्हाइसवरील "<b>"सर्व"</b>" वापरकर्त्यांकडून काढला जाईल."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"तुम्हाला <xliff:g id="USERNAME">%1$s</xliff:g> वापरकर्त्यासाठी हे अ‍ॅप अनइंस्टॉल करायचे आहे का?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"तुम्हाला तुमच्या कार्य प्रोफाइलमधून हे ॲप अनइंस्टॉल करायचे आहे का?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"ॲप डेटा पैकी <xliff:g id="SIZE">%1$s</xliff:g> ठेवा."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"तुम्हाला हे अ‍ॅप हटवायचे आहे का?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"तुम्हाला हे अ‍ॅप अनइंस्टॉल करायचे आहे का? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> क्लोनदेखील हटवले जाईल."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"तुम्हाला तुमच्या खाजगी स्पेसमधून हे अ‍ॅप काढून टाकायचे आहे का?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"अनइंस्टॉल रन होत आहेत"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"अनइंस्टॉल करता आले नाही"</string>
     <string name="uninstalling" msgid="8709566347688966845">"अनइंस्टॉल करत आहे…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"वापरकर्त्यांना व्यवस्‍थापित करा"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> अनइंस्टॉल केले जाऊ शकले नाही."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"पॅकेज पार्स करण्यात समस्या आली."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"इंस्टॉल करा/अनइंस्टॉल करा क्रिया Wear वर सपोर्ट करत नाहीत."</string>
     <string name="message_staging" msgid="8032722385658438567">"अ‍ॅप सुरुवातीच्या स्थितीत आहे…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"अज्ञात"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"तुमच्या सुरक्षिततेसाठी, तुमच्या टॅबलेटला सध्या या स्रोतावरील अज्ञात अ‍ॅप्स इंस्टॉल करण्याची अनुमती नाही. तुम्ही हे सेटिंग्‍ज मध्‍ये बदलू शकता."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"तुमचा टॅबलेट आणि वैयक्तिक डेटा अज्ञात अ‍ॅप्‍सकडून होणार्‍या अटॅकमुळे अधिक असुरक्षित आहे. हे अ‍ॅप इंस्टॉल करून, तुम्‍ही सहमती देता की ते वापरल्‍याने तुमच्‍या टॅबलेटचे कोणत्‍याही प्रकारे होणारे नुकसान किंवा डेटा हानीसाठी तुम्‍ही जबाबदार आहात."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"तुमचा टीव्‍ही आणि वैयक्तिक डेटा अज्ञात अ‍ॅप्‍सकडून होणार्‍या अटॅकमुळे अधिक असुरक्षित आहे. हे अ‍ॅप इंस्टॉल करून, तुम्ही सहमती देता की ते वापरल्‍याने तुमच्‍या टीव्‍हीचे कोणत्‍याही प्रकारे होणारे नुकसान किंवा डेटा हानीसाठी तुम्‍ही जबाबदार आहात."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> क्लोन केलेले"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"सुरू ठेवा"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"सेटिंग्ज"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"wear अ‍ॅप्स इंस्टॉल/अनइंस्टॉल करत आहे"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> मधून <xliff:g id="APPNAME">%1$s</xliff:g> रिस्टोअर करायचे आहे का?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"हे ॲप बॅकग्राउंडमध्ये डाउनलोड होण्यास सुरुवात होईल"</string>
     <string name="restore" msgid="8460854736328970444">"रिस्टोअर करा"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"तुम्ही ऑफलाइन आहात"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"तुम्ही इंटरनेटशी कनेक्ट केले असेल, तेव्हा हे अ‍ॅप आपोआप रिस्टोअर होईल"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"काहीतरी चुकले"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"हे अ‍ॅप रिस्टोअर करताना समस्या आली होती"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"पुरेसे स्टोरेज नाही"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"हे अ‍ॅप रिस्टोअर करण्यासाठी, तुम्ही या डिव्हाइसवरील जागा मोकळी करू शकता. स्टोरेज आवश्यक आहे: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"कृती आवश्यक आहे"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"हे अ‍ॅप रिस्टोअर करण्यासाठी पुढील पायऱ्या फॉलो करा"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> बंद केले आहे"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"हे अ‍ॅप रिस्टोअर करण्यासाठी, सेटिंग्ज मध्ये <xliff:g id="INSTALLERNAME">%1$s</xliff:g> सुरू करा"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> अनइंस्टॉल केले आहे"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"हे अ‍ॅप रिस्टोअर करण्यासाठी, तुम्हाला <xliff:g id="INSTALLERNAME">%1$s</xliff:g> इंस्टॉल करावे लागेल"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"पुढे सुरू ठेवा"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"स्‍टोरेज साफ करा"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"सेटिंग्ज"</string>
+    <string name="close" msgid="5214897374055647996">"बंद करा"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-ms/strings.xml b/packages/PackageInstaller/res/values-ms/strings.xml
index 4b0b560..489c74e 100644
--- a/packages/PackageInstaller/res/values-ms/strings.xml
+++ b/packages/PackageInstaller/res/values-ms/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Apl yang tidak diketahui tidak boleh dipasang oleh pengguna ini"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Pengguna ini tidak dibenarkan memasang apl"</string>
     <string name="ok" msgid="7871959885003339302">"OK"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Kemas kinikan juga"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Urus apl"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Kehabisan ruang"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Nyahpasang kemas kini"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> merupakan sebahagian daripada apl berikut:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Adakah anda mahu menyahpasang apl ini?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Adakah anda mahu menyahpasang apl ini untuk "<b>"semua"</b>" pengguna? Aplikasi dan datanya akan dialih keluar daripada "<b>"semua"</b>" pengguna pada peranti."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Adakah anda ingin menyahpasang apl ini untuk pengguna <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Adakah anda mahu menyahpasang apl ini daripada profil kerja anda?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Simpan <xliff:g id="SIZE">%1$s</xliff:g> data apl."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Adakah anda mahu memadamkan apl ini?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Adakah anda mahu menyahpasang apl ini? Klon <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> juga akan dipadamkan."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Adakah anda mahu menyahpasang apl ini daripada ruang peribadi anda?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Penyahpasangan yang sedang berjalan"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Penyahpasangan yang gagal"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Menyahpasang…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Urus pengguna"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak dapat dinyahpasang."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Masalah telah berlaku semasa menghuraikan pakej."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Tindakan pasang/nyahpasang tidak disokong pada Wear."</string>
     <string name="message_staging" msgid="8032722385658438567">"Pemeringkatan apl…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Tidak diketahui"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Untuk keselamatan, tablet anda kini tidak dibenarkan memasang apl yang tidak diketahui daripada sumber ini buat masa ini. Anda boleh menukar pilihan ini dalam Tetapan."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Tablet dan data peribadi anda lebih mudah diserang oleh apl yang tidak diketahui. Dengan memasang apl ini, anda bersetuju bahawa anda bertanggungjawab atas sebarang kerosakan pada tablet anda atau kehilangan data yang mungkin disebabkan oleh penggunaan apl tersebut."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"TV dan data peribadi anda lebih mudah diserang oleh apl yang tidak diketahui. Dengan memasang apl ini, anda bersetuju bahawa anda bertanggungjawab atas sebarang kerosakan pada TV anda atau kehilangan data yang mungkin disebabkan oleh penggunaan apl tersebut."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Klon <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Teruskan"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Tetapan"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Memasang/menyahpasang apl wear"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Pulihkan <xliff:g id="APPNAME">%1$s</xliff:g> daripada <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Apl ini akan mula dimuat turun dalam latar"</string>
     <string name="restore" msgid="8460854736328970444">"Pulihkan"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Anda berstatus luar talian"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Apl ini akan dipulihkan secara automatik apabila anda disambungkan kepada Internet"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Ada yang tidak kena"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Terdapat masalah semasa memuatkan apl ini"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Storan tidak mencukupi"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Untuk memulihkan apl ini, anda boleh mengosongkan ruang storan pada peranti ini. Storan diperlukan: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Tindakan diperlukan"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Ikut langkah seterusnya untuk memulihkan apl ini"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> dilumpuhkan"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Untuk memulihkan apl ini, dayakan <xliff:g id="INSTALLERNAME">%1$s</xliff:g> dalam Tetapan"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> dinyahpasang"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Untuk memulihkan apl ini, anda perlu memasang <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Teruskan"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Kosongkan storan"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Tetapan"</string>
+    <string name="close" msgid="5214897374055647996">"Tutup"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-my/strings.xml b/packages/PackageInstaller/res/values-my/strings.xml
index 302c2c3..bc2cb8e 100644
--- a/packages/PackageInstaller/res/values-my/strings.xml
+++ b/packages/PackageInstaller/res/values-my/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"အရင်းအမြစ်မသိသော အက်ပ်များကို ဤအသုံးပြုသူက ထည့်သွင်းခွင့်မရှိပါ"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"ဤအသုံးပြုသူသည် အက်ပ်များကို ထည့်သွင်းခွင့်မရှိပါ"</string>
     <string name="ok" msgid="7871959885003339302">"OK"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"ဘာဖြစ်ဖြစ် အပ်ဒိတ်လုပ်ရန်"</string>
     <string name="manage_applications" msgid="5400164782453975580">"အက်ပ်စီမံခြင်း"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"နေရာလွတ်မရှိပါ"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"အပ်ဒိတ်ကို ဖယ်ရှားရန်"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> သည် အောက်ပါအက်ပ်၏ တစ်စိတ်တစ်ဒေသဖြစ်သည်−"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"ဤအက်ပ်ကို ဖယ်ရှားလိုပါသလား။"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"ဤအပလီကေးရှင်းကို အသုံးပြုသူ "<b>"အားလုံး"</b>" အတွက် ဖယ်ရှားလိုပါသလား။ ဤအပလီကေးရှင်းနှင့် သက်ဆိုင်ရာ အချက်အလက်များ အားလုံးကို "<b>" က "</b>" စက်အသုံးပြုသူများအတွက် ဖယ်ရှားလိုက်ပါမည်။"</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"သင်သည် အသုံးပြုသူ <xliff:g id="USERNAME">%1$s</xliff:g> အတွက် ဤအကောင့်ကို ဖယ်ရှားလိုပါသလား။"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"သင့်အလုပ်ပရိုဖိုင်ကနေ ဤအက်ပ်ကို ဖယ်ရှားလိုတာ သေချာပါသလား။"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"အက်ပ်ဒေတာများ၏ <xliff:g id="SIZE">%1$s</xliff:g> ကို ထားရှိရန်။"</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"ဤအက်ပ်ကို ဖျက်လိုသလား။"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"ဤအက်ပ်ကို ဖယ်ရှားလိုသလား။ <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ပုံတူပွားကိုလည်း ဖျက်လိုက်မည်။"</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"ဤအက်ပ်ကို သင့်သီးသန့်နေရာမှ ဖယ်ရှားလိုသလား။"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"ပရိုဂရမ်ကို ဖယ်ရှားနေပါသည်"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"ပရိုဂရမ်ကို ဖယ်ရှား၍မရပါ"</string>
     <string name="uninstalling" msgid="8709566347688966845">"ပရိုဂရမ်ကို ဖယ်ရှားနေသည်..."</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"အသုံးပြုသူများအား စီမံရန်"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> ကို ဖယ်ရှား၍ မရပါ"</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"ပက်ကေ့ဂျ်ကို ခွဲခြမ်းစိတ်ဖြာနေစဉ် ပြဿနာရှိနေသည်။"</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Wear ပေါ်တွင် ထည့်သွင်းခြင်း/ဖယ်ရှားခြင်းများကို ပံ့ပိုးမထားပါ။"</string>
     <string name="message_staging" msgid="8032722385658438567">"အက်ပ်ကို ပြင်ဆင်နေသည်…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"အမည်မသိ"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"လုံခြုံရေးအရ ဤရင်းမြစ်မှရယူထားသည့် အမျိုးအမည်မသိသောအက်ပ်များကို သင့်တက်ဘလက်တွင် လောလောဆယ် ထည့်သွင်းခွင့်မရှိပါ။ ၎င်းကို ‘ဆက်တင်များ’ တွင် ပြောင်းနိုင်ပါသည်။"</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"သင်၏ တက်ဘလက်နှင့် ကိုယ်ရေးကိုယ်တာ အချက်အလက်များသည် အမျိုးအမည် မသိသောအက်ပ်များ၏ တိုက်ခိုက်ခြင်းကို ပိုမိုခံရနိုင်ပါသည်။ ဤအက်ပ်ကို ထည့်သွင်းအသုံးပြုခြင်းအားဖြင့် ဖြစ်ပေါ်လာနိုင်သော တက်ဘလက်ပျက်စီးမှု သို့မဟုတ် ဒေတာဆုံးရှုံးမှုများအတွက် သင့်ထံ၌သာ တာဝန်ရှိကြောင်း သဘောတူရာရောက်ပါသည်။"</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"သင်၏ TV နှင့် ကိုယ်ရေးကိုယ်တာ အချက်အလက်များသည် အမျိုးအမည် မသိသောအက်ပ်များ၏ တိုက်ခိုက်ခြင်းကို ပိုမိုခံရနိုင်ပါသည်။ ဤအက်ပ်ကို ထည့်သွင်းအသုံးပြုခြင်းအားဖြင့် ဖြစ်ပေါ်လာနိုင်သော TV ပျက်စီးမှု သို့မဟုတ် ဒေတာဆုံးရှုံးမှုများအတွက် သင့်ထံ၌သာ တာဝန်ရှိကြောင်း သဘောတူရာရောက်ပါသည်။"</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ပုံတူပွား"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"ရှေ့ဆက်ရန်"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"ဆက်တင်များ"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"wear အက်ပ်ကိုထည့်သွင်းခြင်း/ဖယ်ရှားခြင်း"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> မှ <xliff:g id="APPNAME">%1$s</xliff:g> ကို ပြန်ယူမလား။"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"ဤအက်ပ်ကို နောက်ခံတွင် စတင်ဒေါင်းလုဒ်လုပ်ပါမည်"</string>
     <string name="restore" msgid="8460854736328970444">"ပြန်ယူရန်"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"သင်အော့ဖ်လိုင်း ဖြစ်နေသည်"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"အင်တာနက် ချိတ်ဆက်ထားသည့်အခါ ဤအက်ပ်ကို အလိုအလျောက် ပြန်ယူပါမည်"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"တစ်ခုခုမှားသွားသည်"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"ဤအက်ပ်ကို ပြန်ယူရန် ကြိုးပမ်းရာတွင် ပြဿနာရှိသည်"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"သိုလှောင်ခန်း မလုံလောက်ပါ"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"ဤအက်ပ်ကို ပြန်ယူရန် ဤစက်တွင် နေရာလွတ်ပြုလုပ်နိုင်သည်။ သိုလှောင်ခန်း လိုအပ်သည်- <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"လုပ်ဆောင်ချက် လိုအပ်သည်"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"ဤအက်ပ်ကို ပြန်ယူရန် နောက်အဆင့်များအတိုင်း လုပ်ဆောင်ပါ"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> ကို ပိတ်ထားသည်"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"ဤအက်ပ်ကို ပြန်ယူရန် ဆက်တင်များတွင် <xliff:g id="INSTALLERNAME">%1$s</xliff:g> ဖွင့်ပါ"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> ကို ဖယ်ရှားထားသည်"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"ဤအက်ပ်ကို ပြန်ယူရန် <xliff:g id="INSTALLERNAME">%1$s</xliff:g> ကို ထည့်သွင်းရမည်"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"ရှေ့ဆက်ရန်"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"သိုလှောင်ခန်း ရှင်းလင်းရန်"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"ဆက်တင်များ"</string>
+    <string name="close" msgid="5214897374055647996">"ပိတ်ရန်"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-nb/strings.xml b/packages/PackageInstaller/res/values-nb/strings.xml
index 65c0cb8..2a24daa 100644
--- a/packages/PackageInstaller/res/values-nb/strings.xml
+++ b/packages/PackageInstaller/res/values-nb/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Ukjente apper kan ikke installeres av denne brukeren"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Brukeren har ikke tillatelse til å installere apper"</string>
     <string name="ok" msgid="7871959885003339302">"OK"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Oppdater likevel"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Administrer apper"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Tom for plass"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Avinstaller oppdateringen"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> er del av følgende app:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Vil du avinstallere denne appen?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Vil du avinstallere denne appen for "<b>"alle"</b>" brukere? Appen og tilhørende data blir fjernet fra "<b>"alle"</b>" brukere på enheten."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Ønsker du å avinstallere denne appen for brukeren <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Vil du avinstallere denne appen fra jobbprofilen din?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Behold <xliff:g id="SIZE">%1$s</xliff:g> med appdata."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Vil du slette denne appen?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Vil du avinstallere denne appen? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-klonen slettes også."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Vil du avinstallere denne appen fra det private området ditt?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Avinstalleringer som er i gang"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Mislykkede avinstalleringer"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Avinstallerer …"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Administrer brukere"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> kunne ikke installeres."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Det oppsto et problem med analysen av pakken."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Handlinger for å installere og avinstallere støttes ikke på Wear."</string>
     <string name="message_staging" msgid="8032722385658438567">"Klargjør appen …"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Ukjent"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Nettbrettet har for øyeblikket ikke tillatelse til å installere ukjente apper fra denne kilden, for å ivareta sikkerheten din. Du kan endre dette i innstillingene."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Nettbrettet ditt og de personlige dataene dine er mer sårbare for angrep fra ukjente apper. Når du installerer denne appen, samtykker du i at du er ansvarlig for eventuelle skader på nettbrettet eller tap av data som kan skyldes bruk av appen."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"TV-en din og de personlige dataene dine er mer sårbare for angrep fra ukjente apper. Når du installerer denne appen, samtykker du i at du er ansvarlig for eventuelle skader på TV-en eller tap av data som kan skyldes bruk av appen."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-klon"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Fortsett"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Innstillinger"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Installerer/avinstallerer Wear-apper"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Vil du gjenopprette <xliff:g id="APPNAME">%1$s</xliff:g> fra <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Denne appen begynner å laste ned i bakgrunnen"</string>
     <string name="restore" msgid="8460854736328970444">"Gjenopprett"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Du er uten nett"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Denne appen gjenopprettes automatisk når du er koblet til internett"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Noe gikk galt"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Det oppsto et problem med å gjenopprette denne appen"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Ikke nok lagringsplass"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"For å gjenopprette denne appen kan du frigjøre plass på enheten. Nødvendig lagringsplass: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Handling påkrevd"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Følg de neste trinnene for å gjenopprette denne appen"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> er deaktivert"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"For å gjenopprette denne appen, aktiver <xliff:g id="INSTALLERNAME">%1$s</xliff:g> i innstillingene"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> er avinstallert"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"For å gjenopprette denne appen må du installere <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Fortsett"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Frigjør lagringsplass"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Innstillinger"</string>
+    <string name="close" msgid="5214897374055647996">"Lukk"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-ne/strings.xml b/packages/PackageInstaller/res/values-ne/strings.xml
index b72218c..7dbe141 100644
--- a/packages/PackageInstaller/res/values-ne/strings.xml
+++ b/packages/PackageInstaller/res/values-ne/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"यी प्रयोगकर्ता अज्ञात एपहरू इन्स्टल गर्न सक्नुहुन्न"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"यो प्रयोगकर्तालाई एपहरू इन्स्टल गर्ने अनुमति छैन"</string>
     <string name="ok" msgid="7871959885003339302">"ठिक छ"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"जे भए पनि अपडेट गर्नुहोस्"</string>
     <string name="manage_applications" msgid="5400164782453975580">"एपको प्रबन्ध गर्नु…"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"खाली ठाउँ छैन"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"अद्यावधिकको स्थापना रद्द गर्नु…"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> निम्न एपको अंश हो:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"तपाईं यो एप अनइन्स्टल गर्न चाहनुहुन्छ?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"तपाईं "<b>"सबै"</b>" प्रयोगकर्ताका लागि यो एप अनइन्स्टल गर्न चाहनुहुन्छ? डिभाइसका "<b>"सबै"</b>" प्रयोगकर्ताहरूबाट उक्त एप र यसको डेटा हटाइने छ।"</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"तपाईं प्रयोगकर्ता <xliff:g id="USERNAME">%1$s</xliff:g> का लागि यो एप अनइन्स्टल गर्न चाहनुहुन्छ?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"तपाईं आफ्नो कार्य प्रोफाइलबाट यो एप अनइन्स्टल गर्न चाहनुहुन्छ?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"<xliff:g id="SIZE">%1$s</xliff:g> एपको डेटा राख्नुहोस्।"</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"तपाईं यो एप मेटाउन चाहनुहुन्छ?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"तपाईं यो एप अनइन्स्टल गर्न चाहनुहुन्छ? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> क्लोन पनि मेटाइने छ।"</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"तपाईं आफ्नो निजी स्पेसबाट यो एप अनइन्स्टल गर्न चाहनुहुन्छ?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"चलिरहेका स्थापना रद्द गर्ने कार्यहरू"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"असफल भएका स्थापना रद्द गर्ने कार्यहरू"</string>
     <string name="uninstalling" msgid="8709566347688966845">"स्थापना रद्द गर्दै…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"प्रयोगकर्ताहरूको व्यवस्थापन गर्नुहोस्"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> को स्थापना रद्द गर्न सकिएन।"</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"प्याकेजलाई पार्स गर्ने क्रममा समस्या भयो।"</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Wear मा स्थापना/स्थापना रद्द गर्ने कारबाहीहरू समर्थित छैनन्।"</string>
     <string name="message_staging" msgid="8032722385658438567">"एप स्थापना गर्न तयारी गर्दै…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"अज्ञात"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"तपाईंको सुरक्षार्थ हाल तपाईंको ट्याब्लेटमा यो स्रोतबाट अज्ञात एपहरू इन्स्टल गर्ने अनुमति दिइएको छैन। तपाईं सेटिङमा गई यो कुरा परिवर्तन गर्न सक्नुहुन्छ।"</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"तपाईंको ट्याब्लेट तथा व्यक्तिगत डेटा अज्ञात एपहरूबाट हुने आक्रमणको चपेटामा पर्ने बढी जोखिममा हुन्छन्। यो एप स्थापना गरेर तपाईं यसको प्रयोगबाट तपाईंको ट्याब्लेटमा हुन सक्ने क्षति वा डेटाको नोक्सानीका लागि स्वयं जिम्मेवार हुने कुरामा सहमत हुनुहुन्छ।"</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"तपाईंको टिभी तथा व्यक्तिगत डेटा अज्ञात एपहरूबाट हुने आक्रमणको चपेटामा पर्ने बढी जोखिममा हुन्छन्। यो एप स्थापना गरेर तपाईं यसको प्रयोगबाट तपाईंको टिभी मा हुन सक्ने क्षति वा डेटाको नोक्सानीका लागि स्वयं जिम्मेवार हुने कुरामा सहमत हुनुहुन्छ।"</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> क्लोन"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"जारी राख्नुहोस्"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"सेटिङहरू"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"वेयर एपहरूको स्थापना/स्थापना रद्द गर्दै"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> बाट <xliff:g id="APPNAME">%1$s</xliff:g> रिस्टोर गर्ने हो?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"यो एप ब्याकग्राउन्डमा डाउनलोड हुन थाल्ने छ"</string>
     <string name="restore" msgid="8460854736328970444">"रिस्टोर गर्नुहोस्"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"तपाईंको डिभाइस अफलाइन छ"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"तपाईंको डिभाइस इन्टरनेटमा कनेक्ट भएपछि यो एप स्वतः रिस्टोर हुने छ"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"कुनै समस्या आयो"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"यो एप रिस्टोर गर्ने क्रममा कुनै समस्या आयो"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"पर्याप्त खाली ठाउँ छैन"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"यो एप रिस्टोर गर्न तपाईं यो डिभाइसमा ठाउँ खाली गर्न सक्नुहुन्छ। आवश्यक भण्डारण: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"कारबाही गर्नु पर्ने हुन्छ"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"यो एप रिस्टोर गर्न आगामी चरणहरू पालना गर्नुहोस्"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> अफ गरिएको छ"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"यो एप रिस्टोर गर्न सेटिङमा गई <xliff:g id="INSTALLERNAME">%1$s</xliff:g> अन गर्नुहोस्"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> अनइन्स्टल गरिएको छ"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"यो एप रिस्टोर गर्न तपाईंले <xliff:g id="INSTALLERNAME">%1$s</xliff:g> इन्स्टल गर्नु पर्ने हुन्छ"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"जारी राख्नुहोस्"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"भण्डारण खाली गर्नुहोस्"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"सेटिङ"</string>
+    <string name="close" msgid="5214897374055647996">"बन्द गर्नुहोस्"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-nl/strings.xml b/packages/PackageInstaller/res/values-nl/strings.xml
index a1eb708..4816bab 100644
--- a/packages/PackageInstaller/res/values-nl/strings.xml
+++ b/packages/PackageInstaller/res/values-nl/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Onbekende apps kunnen niet worden geïnstalleerd door deze gebruiker"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Deze gebruiker mag geen apps installeren"</string>
     <string name="ok" msgid="7871959885003339302">"OK"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Toch updaten"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Apps beheren"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Geen ruimte beschikbaar"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Update verwijderen"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> maakt deel uit van de volgende app:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Wil je deze app verwijderen?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Wil je deze app verwijderen voor "<b>"alle"</b>" gebruikers? Deze app en de gegevens ervan worden verwijderd voor "<b>"alle"</b>" gebruikers van het apparaat."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Wil je deze app verwijderen voor de gebruiker <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Wil je deze app verwijderen uit je werkprofiel?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"<xliff:g id="SIZE">%1$s</xliff:g> aan app-gegevens behouden."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Wil je deze app verwijderen?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Wil je deze app verwijderen? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-kloon wordt ook verwijderd."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Wil je deze app verwijderen uit je privéruimte?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Actieve verwijderingen"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Mislukte verwijderingen"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Verwijderen…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Gebruikers beheren"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> kan niet worden verwijderd."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Er is een probleem opgetreden bij het parseren van het pakket."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Acties voor installeren/verwijderen niet ondersteund op Wear."</string>
     <string name="message_staging" msgid="8032722385658438567">"App uitvoeren…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Onbekend"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Uit veiligheidsoverwegingen heeft je tablet momenteel geen toestemming om onbekende apps van deze bron te installeren. Je kunt dit wijzigen via Instellingen."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Je tablet en persoonsgegevens zijn kwetsbaarder voor aanvallen door onbekende apps. Als je deze app installeert, ga je ermee akkoord dat je verantwoordelijk bent voor eventuele schade aan je tablet of gegevensverlies als gevolg van het gebruik van de app."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Je tv en persoonsgegevens zijn kwetsbaarder voor aanvallen door onbekende apps. Als je deze app installeert, ga je ermee akkoord dat je verantwoordelijk bent voor eventuele schade aan je tv of gegevensverlies als gevolg van het gebruik van de app."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>-kloon"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Doorgaan"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Instellingen"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Wear-apps installeren/verwijderen"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"<xliff:g id="APPNAME">%1$s</xliff:g> herstellen via <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Deze app wordt gedownload op de achtergrond"</string>
     <string name="restore" msgid="8460854736328970444">"Herstellen"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Je bent offline"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Deze app wordt automatisch hersteld als je verbinding hebt met internet"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Er is iets misgegaan"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Er is iets misgegaan bij het herstellen van deze app"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Onvoldoende opslagruimte"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Je kunt ruimte op dit apparaat vrijmaken om deze app te herstellen. Vereiste opslagruimte: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Actie vereist"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Voer de volgende stappen uit om deze app te herstellen"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> is uitgezet"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Zet <xliff:g id="INSTALLERNAME">%1$s</xliff:g> aan via Instellingen om deze app te herstellen"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> is verwijderd"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Je moet <xliff:g id="INSTALLERNAME">%1$s</xliff:g> installeren om deze app te herstellen"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Doorgaan"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Opslag wissen"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Instellingen"</string>
+    <string name="close" msgid="5214897374055647996">"Sluiten"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-or/strings.xml b/packages/PackageInstaller/res/values-or/strings.xml
index a1c685c..70eab2d 100644
--- a/packages/PackageInstaller/res/values-or/strings.xml
+++ b/packages/PackageInstaller/res/values-or/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"ଏହି ୟୁଜରଙ୍କ ଦ୍ୱାରା ଅଜଣା ଆପ୍‍ ଇନଷ୍ଟଲ୍‍ କରାଯାଇପାରିବ ନାହିଁ"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"ଏହି ୟୁଜର୍‌ ଆପ୍‍ ଇନଷ୍ଟଲ୍‍ କରିପାରିବେ ନାହିଁ"</string>
     <string name="ok" msgid="7871959885003339302">"ଠିକ୍ ଅଛି"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"ଯେ କୌଣସି ମତେ ଅପଡେଟ କରନ୍ତୁ"</string>
     <string name="manage_applications" msgid="5400164782453975580">"ଆପ୍‌ଗୁଡ଼ିକର ପରିଚାଳନା କରନ୍ତୁ"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"ଆଉ ସ୍ଥାନ ନାହିଁ"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"ଅପଡେଟ୍‍ ଅନଇନଷ୍ଟଲ୍‌ କରନ୍ତୁ"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> ହେଉଛି ନିମ୍ନ ଆପ୍‍ର ଏକ ଅଂଶ।"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"ଆପଣ ଏହି ଆପ୍‍ ଅନଇନଷ୍ଟଲ୍‌ କରିବାକୁ ଚାହାଁନ୍ତି କି?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"ଆପଣ "<b>"ସମସ୍ତ"</b>" ୟୁଜର୍‌ଙ୍କ ପାଇଁ ଏହି ଆପ୍‌କୁ ଅନଷ୍ଟଲ୍‍ କରିବାକୁ ଚାହୁଁଛନ୍ତି କି? ଡିଭାଇସ୍‌ରେ ଥିବା "<b>"ସମସ୍ତ"</b>" ୟୁଜର୍‌ ଆପ୍ଲିକେଶନ୍‍ ଏବଂ ତାହାର ଡାଟା ବାହାର କରିଦିଆଯିବ।"</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"ୟୁଜର୍‌ <xliff:g id="USERNAME">%1$s</xliff:g>ଙ୍କ ପାଇଁ ଆପଣ ଏହି ଆପ୍‍ ଇନଷ୍ଟଲ୍‍ କରିବେ କି?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"ଆପଣ ଆପଣଙ୍କ ୱାର୍କ ପ୍ରୋଫାଇଲରୁ ଏହି ଆପକୁ ଅନଇନଷ୍ଟଲ କରିବାକୁ ଚାହାଁନ୍ତି କି?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"<xliff:g id="SIZE">%1$s</xliff:g> ଆକାରର ଆପ୍‍ ଡାଟା ରଖନ୍ତୁୁ।"</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"ଆପଣ ଏହି ଆପକୁ ଡିଲିଟ କରିବାକୁ ଚାହୁଁଛନ୍ତି?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"ଆପଣ ଏହି ଆପକୁ ଅନଇନଷ୍ଟଲ କରିବାକୁ ଚାହୁଁଛନ୍ତି? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> କ୍ଲୋନକୁ ମଧ୍ୟ ଡିଲିଟ କରାଯିବ।"</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"ଆପଣ ଆପଣଙ୍କ ପ୍ରାଇଭେଟ ସ୍ପେସରୁ ଏହି ଆପକୁ ଅନଇନଷ୍ଟଲ କରିବାକୁ ଚାହାଁନ୍ତି?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"ଅନଇନଷ୍ଟଲ୍‌ ଚାଲୁଛି"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"ବିଫଳ ହୋଇଥିବା ଅନଇନଷ୍ଟଲ୍‌"</string>
     <string name="uninstalling" msgid="8709566347688966845">"ଅନ୍‌ଇନଷ୍ଟଲ୍‌ କରାଯାଉଛି…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"ୟୁଜର୍‌ଙ୍କୁ ପରିଚାଳନା କରନ୍ତୁ"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> ଅନଇନଷ୍ଟଲ୍‍ କରିହେଲା ନାହିଁ।"</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"ଏହି ପ୍ୟାକେଜ୍‍ ପାର୍ସ କରିବାରେ ସମସ୍ୟା ଥିଲା।"</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"ୱିଅର୍‌ରେ ଇନଷ୍ଟଲ୍‍/ଅନଇନଷ୍ଟଲ୍‍ କାର୍ଯ୍ୟ ସପୋର୍ଟ କରେନାହିଁ।"</string>
     <string name="message_staging" msgid="8032722385658438567">"ଆପ୍‍ ପର୍ଯ୍ୟାୟଭୁକ୍ତ କରାଯାଉଛି…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"ଅଜଣା"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"ଆପଣଙ୍କ ସୁରକ୍ଷା ପାଇଁ, ଆପଣଙ୍କ ଟାବଲେଟକୁ ବର୍ତ୍ତମାନ ଏହି ସୋର୍ସରୁ ଆସିଥିବା ଅଜଣା ଆପଗୁଡ଼ିକୁ ଇନଷ୍ଟଲ୍ କରିବା ପାଇଁ ଅନୁମତି ଦିଆଯାଇନାହିଁ। ଆପଣ ଏହାକୁ ସେଟିଂସରେ ପରିବର୍ତ୍ତନ କରିପାରିବେ।"</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"ଅଜଣା ଆପ୍‌ ଦ୍ୱାରା ଆପଣଙ୍କ ଟାବଲେଟ୍‍ ଏବଂ ବ୍ୟକ୍ତିଗତ ଡାଟାକୁ ନଷ୍ଟ କରାଯାଇପାରିବାର ସମ୍ଭାବନା ବହୁତ ଅଧିକ। ଏହି ଆପ୍‌କୁ ଇନଷ୍ଟଲ୍‌ କରିବାର ଅର୍ଥ ହେଉଛି ଆପଣଙ୍କ ଟାବ୍‌ଲେଟ୍‌ରେ ଘଟିବା କୌଣସି ପ୍ରକାର କ୍ଷତି କିମ୍ବା ସେଗୁଡ଼ିକର ବ୍ୟବହାରରୁ ହେବା କୌଣସି ପ୍ରକାର ଡାଟାର ହାନୀ ପାଇଁ ଆପଣ ଦାୟୀ ରହିବାକୁ ରାଜି ହୁଅନ୍ତି।"</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"ଅଜଣା ଆପ୍‌ ଦ୍ୱାରା ଆପଣଙ୍କ ଟିଭି ଏବଂ ବ୍ୟକ୍ତିଗତ ଡାଟାକୁ ନଷ୍ଟ କରାଯାଇପାରିବାର ସମ୍ଭାବନା ବହୁତ ଅଧିକ। ଏହି ଆପ୍‌କୁ ଇନଷ୍ଟଲ୍‌ କରିବାର ଅର୍ଥ ହେଉଛି ଆପଣଙ୍କ ଟିଭିରେ ଘଟିବା କୌଣସି ପ୍ରକାର କ୍ଷତି କିମ୍ବା ସେଗୁଡ଼ିକର ବ୍ୟବହାରରୁ ହେବା କୌଣସି ପ୍ରକାର ଡାଟାର ହାନୀ ପାଇଁ ଆପଣ ଦାୟୀ ରହିବାକୁ ରାଜି ହୁଅନ୍ତି।"</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> କ୍ଲୋନ"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"ଜାରି ରଖନ୍ତୁ"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"ସେଟିଂସ"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"ୱିଅର୍‍ ଆପ୍‍ ଇନଷ୍ଟଲ୍‌/ଅନଇନଷ୍ଟଲ୍‍ କରାଯାଉଛି"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g>ରୁ <xliff:g id="APPNAME">%1$s</xliff:g>କୁ ରିଷ୍ଟୋର କରିବେ?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"ଏହି ଆପ ପୃଷ୍ଠପଟରେ ଡାଉନଲୋଡ ହେବା ଆରମ୍ଭ କରିବ"</string>
     <string name="restore" msgid="8460854736328970444">"ରିଷ୍ଟୋର କରନ୍ତୁ"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"ଆପଣ ଅଫଲାଇନ ଅଛନ୍ତି"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"ଆପଣ ଇଣ୍ଟରନେଟ ସହ କନେକ୍ଟ ହେଲେ ଏହି ଆପ ସ୍ୱତଃ ରିଷ୍ଟୋର ହେବ"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"କିଛି ତ୍ରୁଟି ହୋଇଛି"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"ଏହି ଆପ ରିଷ୍ଟୋର କରିବାକୁ ଚେଷ୍ଟା କରିବା ସମୟରେ ଏକ ସମସ୍ୟା ହୋଇଛି"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"ଯଥେଷ୍ଟ ଷ୍ଟୋରେଜ ନାହିଁ"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"ଏହି ଆପ ରିଷ୍ଟୋର କରିବା ପାଇଁ ଆପଣ ଏହି ଡିଭାଇସରେ ସ୍ପେସ ଖାଲି କରିପାରିବେ। ଷ୍ଟୋରେଜ ଆବଶ୍ୟକ: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"ପଦକ୍ଷେପ ନେବା ଆବଶ୍ୟକ"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"ଏହି ଆପ ରିଷ୍ଟୋର କରିବାକୁ ପରବର୍ତ୍ତୀ ଷ୍ଟେପଗୁଡ଼ିକୁ ଫଲୋ କରନ୍ତୁ"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g>କୁ ଅକ୍ଷମ କରାଯାଇଛି"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"ଏହି ଆପକୁ ରିଷ୍ଟୋର କରିବା ପାଇଁ ସେଟିଂସରେ <xliff:g id="INSTALLERNAME">%1$s</xliff:g>କୁ ସକ୍ଷମ କରନ୍ତୁ"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g>କୁ ଅନଇନଷ୍ଟଲ କରାଯାଇଛି"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"ଏହି ଆପ ରିଷ୍ଟୋର କରିବା ପାଇଁ ଆପଣଙ୍କୁ <xliff:g id="INSTALLERNAME">%1$s</xliff:g> ଇନଷ୍ଟଲ କରିବାକୁ ହେବ"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"ଜାରି ରଖନ୍ତୁ"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"ଷ୍ଟୋରେଜ ଖାଲି କରନ୍ତୁ"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"ସେଟିଂସ"</string>
+    <string name="close" msgid="5214897374055647996">"ବନ୍ଦ କରନ୍ତୁ"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-pa/strings.xml b/packages/PackageInstaller/res/values-pa/strings.xml
index 1c7fb862..d91d032 100644
--- a/packages/PackageInstaller/res/values-pa/strings.xml
+++ b/packages/PackageInstaller/res/values-pa/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"ਇਹ ਵਰਤੋਂਕਾਰ ਅਗਿਆਤ ਐਪਾਂ ਨੂੰ ਸਥਾਪਤ ਨਹੀਂ ਕਰ ਸਕਦਾ"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"ਇਸ ਵਰਤੋਂਕਾਰ ਨੂੰ ਐਪਾਂ ਸਥਾਪਤ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ"</string>
     <string name="ok" msgid="7871959885003339302">"ਠੀਕ ਹੈ"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"ਫਿਰ ਵੀ ਅੱਪਡੇਟ ਕਰੋ"</string>
     <string name="manage_applications" msgid="5400164782453975580">"ਐਪਾਂ ਪ੍ਰਬੰਧਿਤ ਕਰੋ"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"ਜਗ੍ਹਾ ਖਾਲੀ ਨਹੀਂ"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"ਅੱਪਡੇਟ ਅਣਸਥਾਪਤ ਕਰੋ"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> ਅੱਗੇ ਦਿੱਤੀ ਐਪ ਦਾ ਭਾਗ ਹੈ:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"ਕੀ ਤੁਸੀਂ ਇਸ ਐਪ ਨੂੰ ਅਣਸਥਾਪਤ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"ਕੀ ਤੁਸੀਂ ਇਸ ਐਪ ਨੂੰ "<b>"ਸਾਰੇ"</b>" ਵਰਤੋਂਕਾਰਾਂ ਲਈ ਅਣਸਥਾਪਤ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ? ਐਪਲੀਕੇਸ਼ਨ ਅਤੇ ਇਸਦਾ ਡਾਟਾ ਡੀਵਾਈਸ \'ਤੇ "<b>"ਸਾਰੇ"</b>" ਵਰਤੋਂਕਾਰਾਂ ਵੱਲੋਂ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ।"</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"ਕੀ ਤੁਸੀਂ ਵਰਤੋਂਕਾਰ <xliff:g id="USERNAME">%1$s</xliff:g> ਲਈ ਇਸ ਐਪ ਨੂੰ ਅਣਸਥਾਪਤ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"ਕੀ ਤੁਸੀਂ ਇਸ ਐਪ ਨੂੰ ਆਪਣੇ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਤੋਂ ਅਣਸਥਾਪਤ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"<xliff:g id="SIZE">%1$s</xliff:g> ਐਪ ਡਾਟਾ ਰੱਖੋ।"</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"ਕੀ ਤੁਸੀਂ ਇਸ ਐਪ ਨੂੰ ਮਿਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"ਕੀ ਤੁਸੀਂ ਇਸ ਐਪ ਨੂੰ ਅਣਸਥਾਪਤ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ਦੇ ਕਲੋਨ ਨੂੰ ਵੀ ਮਿਟਾਇਆ ਜਾਵੇਗਾ।"</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"ਕੀ ਤੁਸੀਂ ਇਸ ਐਪ ਨੂੰ ਆਪਣੇ ਨਿੱਜੀ ਸਪੇਸ ਤੋਂ ਅਣਸਥਾਪਤ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"ਚੱਲ ਰਹੀਆਂ ਅਣਸਥਾਪਨਾਵਾਂ"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"ਅਸਫਲ ਅਣਸਥਾਪਨਾਵਾਂ"</string>
     <string name="uninstalling" msgid="8709566347688966845">"ਅਣਸਥਾਪਤ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"ਵਰਤੋਂਕਾਰਾਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਨੂੰ ਅਣਸਥਾਪਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ।"</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"ਪੈਕੇਜ ਨੂੰ ਪਾਰਸ ਕਰਨ ਵਿੱਚ ਇੱਕ ਸਮੱਸਿਆ ਸੀ।"</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Wear \'ਤੇ ਸਥਾਪਤ ਜਾਂ ਅਣਸਥਾਪਤ ਕਰਨ ਦੀਆਂ ਕਾਰਵਾਈਆਂ ਸਮਰਥਿਤ ਨਹੀਂ ਹਨ।"</string>
     <string name="message_staging" msgid="8032722385658438567">"ਐਪ ਨੂੰ ਸਟੇਜ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"ਅਗਿਆਤ"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"ਤੁਹਾਡੀ ਸੁਰੱਖਿਆ ਲਈ, ਫ਼ਿਲਹਾਲ ਤੁਹਾਡੇ ਟੈਬਲੈੱਟ ਨੂੰ ਇਸ ਸਰੋਤ ਤੋਂ ਅਗਿਆਤ ਐਪਾਂ ਸਥਾਪਤ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ। ਤੁਸੀਂ ਇਸ ਨੂੰ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਬਦਲ ਸਕਦੇ ਹੋ।"</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"ਤੁਹਾਡਾ ਟੈਬਲੈੱਟ ਅਤੇ ਨਿੱਜੀ ਡਾਟਾ ਅਗਿਆਤ ਐਪਾਂ ਤੋਂ ਹਮਲੇ ਪ੍ਰਤੀ ਵਧੇਰੇ ਵਿੰਨਣਸ਼ੀਲ ਹਨ। ਇਹ ਐਪ ਸਥਾਪਤ ਕਰਕੇ, ਤੁਸੀਂ ਸਹਿਮਤੀ ਦਿੰਦੇ ਹੋ ਕਿ ਆਪਣੇ ਟੈਬਲੈੱਟ ਨੂੰ ਹੋਣ ਵਾਲੇ ਕਿਸੇ ਵੀ ਨੁਕਸਾਨ ਜਾਂ ਡਾਟੇ ਦੀ ਹਾਨੀ ਲਈ ਤੁਸੀਂ ਜ਼ੁੰਮੇਵਾਰ ਹੋ ਜੋ ਸ਼ਾਇਦ ਇਸ ਐਪ ਨੂੰ ਵਰਤਣ ਦੇ ਨਤੀਜੇ ਵਜੋਂ ਹੋ ਸਕਦਾ ਹੈ।"</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"ਤੁਹਾਡਾ ਟੀਵੀ ਅਤੇ ਨਿੱਜੀ ਡਾਟਾ ਅਗਿਆਤ ਐਪਾਂ ਤੋਂ ਹਮਲੇ ਪ੍ਰਤੀ ਵਧੇਰੇ ਵਿੰਨਣਸ਼ੀਲ ਹਨ। ਇਹ ਐਪ ਸਥਾਪਤ ਕਰਕੇ, ਤੁਸੀਂ ਸਹਿਮਤੀ ਦਿੰਦੇ ਹੋ ਕਿ ਆਪਣੇ ਟੀਵੀ ਨੂੰ ਹੋਣ ਵਾਲੇ ਕਿਸੇ ਵੀ ਨੁਕਸਾਨ ਜਾਂ ਡਾਟੇ ਦੀ ਹਾਨੀ ਲਈ ਤੁਸੀਂ ਜ਼ੁੰਮੇਵਾਰ ਹੋ ਜੋ ਸ਼ਾਇਦ ਇਸ ਐਪ ਨੂੰ ਵਰਤਣ ਦੇ ਨਤੀਜੇ ਵਜੋਂ ਹੋ ਸਕਦਾ ਹੈ।"</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ਦਾ ਕਲੋਨ"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"ਜਾਰੀ ਰੱਖੋ"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"ਸੈਟਿੰਗਾਂ"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"ਵੀਅਰ ਐਪਾਂ ਸਥਾਪਤ ਜਾਂ ਅਣਸਥਾਪਤ ਕਰਨਾ"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"ਕੀ <xliff:g id="APPNAME">%1$s</xliff:g> ਨੂੰ <xliff:g id="INSTALLERNAME">%1$s</xliff:g> ਤੋਂ ਮੁੜ-ਬਹਾਲ ਕਰਨਾ ਹੈ?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"ਇਹ ਐਪ ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਡਾਊਨਲੋਡ ਹੋਣੀ ਸ਼ੁਰੂ ਹੋ ਜਾਵੇਗੀ"</string>
     <string name="restore" msgid="8460854736328970444">"ਮੁੜ-ਬਹਾਲ ਕਰੋ"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"ਤੁਸੀਂ ਆਫ਼ਲਾਈਨ ਹੋ"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"ਜਦੋਂ ਤੁਸੀਂ ਇੰਟਰਨੈੱਟ ਨਾਲ ਕਨੈਕਟ ਹੁੰਦੇ ਹੋ, ਤਾਂ ਇਹ ਐਪ ਸਵੈਚਲਿਤ ਤੌਰ \'ਤੇ ਮੁੜ-ਬਹਾਲ ਹੋ ਜਾਵੇਗੀ"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"ਕੋਈ ਗੜਬੜ ਹੋ ਗਈ"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"ਇਸ ਐਪ ਨੂੰ ਮੁੜ-ਬਹਾਲ ਕਰਨ ਵੇਲੇ ਕੋਈ ਸਮੱਸਿਆ ਆਈ"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"ਲੋੜੀਂਦੀ ਸਟੋਰੇਜ ਨਹੀਂ ਹੈ"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"ਇਸ ਐਪ ਨੂੰ ਮੁੜ-ਬਹਾਲ ਕਰਨ ਲਈ, ਤੁਸੀਂ ਆਪਣੇ ਡੀਵਾਈਸ \'ਤੇ ਜਗ੍ਹਾ ਖਾਲੀ ਕਰ ਸਕਦੇ ਹੋ। ਲੋੜੀਂਦੀ ਸਟੋਰੇਜ: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"ਕਾਰਵਾਈ ਦੀ ਲੋੜ"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"ਇਸ ਐਪ ਨੂੰ ਮੁੜ-ਬਹਾਲ ਕਰਨ ਲਈ ਅਗਲੇ ਪੜਾਵਾਂ ਦੀ ਪਾਲਣਾ ਕਰੋ"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> ਨੂੰ ਬੰਦ ਕੀਤਾ ਗਿਆ"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"ਇਸ ਐਪ ਨੂੰ ਮੁੜ-ਬਹਾਲ ਕਰਨ ਲਈ, ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਜਾ ਕੇ<xliff:g id="INSTALLERNAME">%1$s</xliff:g> ਨੂੰ ਚਾਲੂ ਕਰੋ"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> ਨੂੰ ਅਣਸਥਾਪਤ ਕੀਤਾ ਗਿਆ"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"ਇਸ ਐਪ ਨੂੰ ਮੁੜ-ਬਹਾਲ ਕਰਨ ਲਈ, ਤੁਹਾਨੂੰ <xliff:g id="INSTALLERNAME">%1$s</xliff:g> ਨੂੰ ਸਥਾਪਤ ਕਰਨ ਦੀ ਲੋੜ ਪਵੇਗੀ"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"ਜਾਰੀ ਰੱਖੋ"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"ਸਟੋਰੇਜ ਕਲੀਅਰ ਕਰੋ"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"ਸੈਟਿੰਗਾਂ"</string>
+    <string name="close" msgid="5214897374055647996">"ਬੰਦ ਕਰੋ"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-pl/strings.xml b/packages/PackageInstaller/res/values-pl/strings.xml
index 8fa11ed..41bec16 100644
--- a/packages/PackageInstaller/res/values-pl/strings.xml
+++ b/packages/PackageInstaller/res/values-pl/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Ten użytkownik nie może instalować nieznanych aplikacji"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Ten użytkownik nie może instalować aplikacji"</string>
     <string name="ok" msgid="7871959885003339302">"OK"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Zaktualizuj mimo to"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Zarządzaj aplikacjami"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Brak miejsca"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Odinstaluj aktualizację"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> jest częścią następującej aplikacji:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Odinstalować tę aplikację?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Chcesz odinstalować tę aplikację dla "<b>"wszystkich"</b>" użytkowników? Ta aplikacja i jej dane zostaną usunięte dla "<b>"wszystkich"</b>" użytkowników na urządzeniu."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Chcesz odinstalować tę aplikację dla użytkownika <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Czy chcesz odinstalować tę aplikację z profilu służbowego?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Zachowaj <xliff:g id="SIZE">%1$s</xliff:g> danych aplikacji."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Chcesz usunąć tę aplikację?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Chcesz odinstalować tę aplikację? Klon aplikacji <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> również zostanie usunięty."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Chcesz odinstalować tę aplikację ze swojego obszaru prywatnego?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Aktywne odinstalowania"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Nieudane odinstalowania"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Odinstalowuję…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Zarządzaj użytkownikami"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"Nie można odinstalować aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Podczas analizowania pakietu wystąpił problem."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Wear nie obsługuje instalowania ani odinstalowywania."</string>
     <string name="message_staging" msgid="8032722385658438567">"Przygotowuję aplikację…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Inny"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Ze względów bezpieczeństwa na Twoim tablecie nie można obecnie instalować nieznanych aplikacji z tego źródła. Możesz to zmienić w Ustawieniach."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Dane na tablecie i prywatne są bardziej narażone na atak nieznanych aplikacji. Instalując tę aplikację, bierzesz na siebie odpowiedzialność za ewentualne uszkodzenie tabletu lub utratę danych w wyniku jej używania."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Dane na telewizorze i prywatne są bardziej narażone na atak nieznanych aplikacji. Instalując tę aplikację, bierzesz na siebie odpowiedzialność za ewentualne uszkodzenie telewizora lub utratę danych w wyniku jej używania."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Klon aplikacji <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Dalej"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Ustawienia"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Instalacja/usuwanie aplikacji na Wear"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Przywrócić aplikację <xliff:g id="APPNAME">%1$s</xliff:g> z aplikacji <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Ta aplikacja zacznie pobieranie w tle"</string>
     <string name="restore" msgid="8460854736328970444">"Przywróć"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Jesteś offline"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Ta aplikacja zostanie automatycznie przywrócona, gdy połączysz się z internetem"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Coś poszło nie tak"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Podczas przywracania tej aplikacji wystąpił błąd"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Za mało miejsca na dane"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Aby przywrócić tę aplikację, musisz zwolnić miejsce na urządzeniu. Wymagane miejsce na dane: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Wymagane działanie"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Aby przywrócić tę aplikację, wykonaj następne czynności"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"Aplikacja <xliff:g id="INSTALLERNAME">%1$s</xliff:g> jest wyłączona"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Aby przywrócić tę aplikację, włącz aplikację <xliff:g id="INSTALLERNAME">%1$s</xliff:g> w Ustawieniach"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"Aplikacja <xliff:g id="INSTALLERNAME">%1$s</xliff:g> jest odinstalowana"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Aby przywrócić tę aplikację, musisz zainstalować aplikację <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Dalej"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Wyczyść pamięć"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Ustawienia"</string>
+    <string name="close" msgid="5214897374055647996">"Zamknij"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-pt-rBR/strings.xml b/packages/PackageInstaller/res/values-pt-rBR/strings.xml
index 71ecb2b3..9d943a5 100644
--- a/packages/PackageInstaller/res/values-pt-rBR/strings.xml
+++ b/packages/PackageInstaller/res/values-pt-rBR/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Apps desconhecidos não podem ser instalados por este usuário"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Este usuário não tem permissão para instalar apps"</string>
     <string name="ok" msgid="7871959885003339302">"OK"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Atualizar mesmo assim"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Gerenciar apps"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Sem espaço"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Desinstalar atualização"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> é parte do seguinte app:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Você quer desinstalar este app?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Quer desinstalar este app para "<b>"todos"</b>" os usuários? O aplicativo e os dados dele serão removidos para "<b>"todos"</b>" os usuários do dispositivo."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Quer desinstalar este app para o usuário <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Você quer desinstalar esse app do seu perfil de trabalho?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Manter <xliff:g id="SIZE">%1$s</xliff:g> de dados do app."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Quer excluir este app?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Quer desinstalar este app? O clone <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> também vai ser excluído."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Você quer desinstalar esse app do seu espaço particular?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Executando desinstalações"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Falha nas desinstalações"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Desinstalando…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Gerenciar usuários"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"Não foi possível desinstalar <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Ocorreu um problema ao analisar o pacote."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"As ações de instalar/desinstalar não são compatíveis com o Android Wear."</string>
     <string name="message_staging" msgid="8032722385658438567">"Testando app…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Desconhecido"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Para sua segurança, o tablet não tem permissão para instalar apps desconhecidos dessa fonte. Você pode mudar isso nas configurações."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Seu tablet e seus dados pessoais estão mais vulneráveis a ataques de apps desconhecidos. Ao instalar esse app, você concorda que é responsável por qualquer perda de dados ou dano ao dispositivo causados pelo uso desses apps."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Sua TV e seus dados pessoais estão mais vulneráveis a ataques de apps desconhecidos. Ao instalar esse app, você concorda que é responsável por qualquer perda de dados ou dano ao dispositivo causados pelo uso desses apps."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Clone de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Continuar"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Configurações"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Instalando/desinstalando apps do Wear"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Restaurar <xliff:g id="APPNAME">%1$s</xliff:g> usando o app <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"O download desse app será feito em segundo plano"</string>
     <string name="restore" msgid="8460854736328970444">"Restaurar"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Você está off-line"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Este app será restaurado automaticamente quando você tiver uma conexão de Internet"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Algo deu errado"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Ocorreu um problema ao tentar restaurar este app"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Armazenamento insuficiente"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Para restaurar o app, libere espaço no dispositivo. Armazenamento necessário: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Ação necessária"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Siga as próximas etapas para restaurar este app"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"A <xliff:g id="INSTALLERNAME">%1$s</xliff:g> está desativada"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Para restaurar o app, ative a <xliff:g id="INSTALLERNAME">%1$s</xliff:g> nas Configurações"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"A <xliff:g id="INSTALLERNAME">%1$s</xliff:g> não está instalada"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Para restaurar o app, instale a <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Continuar"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Limpar armazenamento"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Configurações"</string>
+    <string name="close" msgid="5214897374055647996">"Fechar"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-pt-rPT/strings.xml b/packages/PackageInstaller/res/values-pt-rPT/strings.xml
index 1d5c1a2..0ddbaf0 100644
--- a/packages/PackageInstaller/res/values-pt-rPT/strings.xml
+++ b/packages/PackageInstaller/res/values-pt-rPT/strings.xml
@@ -44,6 +44,7 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Este utilizador não pode instalar aplicações desconhecidas."</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Este utilizador não tem autorização para instalar aplicações."</string>
     <string name="ok" msgid="7871959885003339302">"OK"</string>
+    <string name="archive" msgid="4447791830199354721">"Arquivar"</string>
     <string name="update_anyway" msgid="8792432341346261969">"Atualizar mesmo assim"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Gerir app"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Sem espaço"</string>
@@ -58,6 +59,11 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Desinstalar atualização"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> faz parte da seguinte app:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Desinstalar esta app?"</string>
+    <string name="archive_application_text" msgid="8482325710714386348">"Os seus dados pessoais vão ser guardados"</string>
+    <string name="archive_application_text_all_users" msgid="3151229641681672580">"Arquivar esta app para todos os utilizadores? Os seus dados pessoais vão ser guardados"</string>
+    <string name="archive_application_text_current_user_work_profile" msgid="1450487362134779752">"Arquivar esta app no seu perfil de trabalho? Os seus dados pessoais vão ser guardados"</string>
+    <string name="archive_application_text_user" msgid="2586558895535581451">"Arquivar esta app para <xliff:g id="USERNAME">%1$s</xliff:g>? Os seus dados pessoais vão ser guardados"</string>
+    <string name="archive_application_text_current_user_private_profile" msgid="1958423158655599132">"Quer arquivar esta app do seu espaço privado? Os seus dados pessoais vão ser guardados"</string>
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Quer desinstalar esta app para "<b>"todos"</b>" os utilizadores? A app e os respetivos dados serão removidos de "<b>"todos"</b>" os utilizadores do dispositivo."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Quer desinstalar esta app para o utilizador <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Quer desinstalar esta app do seu perfil de trabalho?"</string>
@@ -66,6 +72,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Manter <xliff:g id="SIZE">%1$s</xliff:g> de dados da app."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Quer apagar esta app?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Quer desinstalar esta app? O clone de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> também vai ser apagado."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Quer desinstalar esta app do seu espaço privado?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Desinstalações em execução"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Desinstalações com falha"</string>
     <string name="uninstalling" msgid="8709566347688966845">"A desinstalar…"</string>
@@ -85,8 +92,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Gerir utilizadores"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"Não foi possível desinstalar a app <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Ocorreu um problema ao analisar o pacote."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"As ações de instalar/desinstalar não são compatíveis com o Android Wear."</string>
     <string name="message_staging" msgid="8032722385658438567">"A preparar a app…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Desconhecida"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Para sua segurança, o tablet não está atualmente autorizado a instalar apps desconhecidas a partir desta origem. Pode alterar esta opção nas Definições."</string>
@@ -97,6 +102,7 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"O seu tablet e os dados pessoais estão mais vulneráveis a ataques por parte de aplicações desconhecidas. Ao instalar esta app, concorda que é responsável por quaisquer danos causados ao tablet ou pelas perdas de dados que possam resultar da utilização da mesma."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"A sua TV e os dados pessoais estão mais vulneráveis a ataques por parte de aplicações desconhecidas. Ao instalar esta app, concorda que é responsável por quaisquer danos causados à TV ou pelas perdas de dados que possam resultar da utilização da mesma."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Clone de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <string name="archiving_app_label" msgid="1127085259724124725">"Arquivar <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>?"</string>
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Continuar"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Definições"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Instalar/desinstalar aplicações Wear"</string>
@@ -106,4 +112,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Restaurar <xliff:g id="APPNAME">%1$s</xliff:g> a partir da <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Esta app vai começar a ser transferida em segundo plano"</string>
     <string name="restore" msgid="8460854736328970444">"Restaurar"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Está offline"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Esta app vai ser reposta automaticamente quando estabelecer ligação à Internet"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Algo correu mal"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Ocorreu um problema ao tentar repor esta app"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Sem armazenamento suficiente"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Para repor esta app, pode libertar espaço neste dispositivo. Armazenamento necessário: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Ação necessária"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Siga os passos abaixo para repor esta app"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"O instalador <xliff:g id="INSTALLERNAME">%1$s</xliff:g> está desativado"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Para repor esta app, ative o instalador <xliff:g id="INSTALLERNAME">%1$s</xliff:g> nas Definições"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"O instalador <xliff:g id="INSTALLERNAME">%1$s</xliff:g> está desinstalado"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Para repor esta app, tem de instalar o instalador <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Continuar"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Limpar armazenamento"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Definições"</string>
+    <string name="close" msgid="5214897374055647996">"Fechar"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-pt/strings.xml b/packages/PackageInstaller/res/values-pt/strings.xml
index 71ecb2b3..9d943a5 100644
--- a/packages/PackageInstaller/res/values-pt/strings.xml
+++ b/packages/PackageInstaller/res/values-pt/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Apps desconhecidos não podem ser instalados por este usuário"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Este usuário não tem permissão para instalar apps"</string>
     <string name="ok" msgid="7871959885003339302">"OK"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Atualizar mesmo assim"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Gerenciar apps"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Sem espaço"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Desinstalar atualização"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> é parte do seguinte app:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Você quer desinstalar este app?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Quer desinstalar este app para "<b>"todos"</b>" os usuários? O aplicativo e os dados dele serão removidos para "<b>"todos"</b>" os usuários do dispositivo."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Quer desinstalar este app para o usuário <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Você quer desinstalar esse app do seu perfil de trabalho?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Manter <xliff:g id="SIZE">%1$s</xliff:g> de dados do app."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Quer excluir este app?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Quer desinstalar este app? O clone <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> também vai ser excluído."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Você quer desinstalar esse app do seu espaço particular?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Executando desinstalações"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Falha nas desinstalações"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Desinstalando…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Gerenciar usuários"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"Não foi possível desinstalar <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Ocorreu um problema ao analisar o pacote."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"As ações de instalar/desinstalar não são compatíveis com o Android Wear."</string>
     <string name="message_staging" msgid="8032722385658438567">"Testando app…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Desconhecido"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Para sua segurança, o tablet não tem permissão para instalar apps desconhecidos dessa fonte. Você pode mudar isso nas configurações."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Seu tablet e seus dados pessoais estão mais vulneráveis a ataques de apps desconhecidos. Ao instalar esse app, você concorda que é responsável por qualquer perda de dados ou dano ao dispositivo causados pelo uso desses apps."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Sua TV e seus dados pessoais estão mais vulneráveis a ataques de apps desconhecidos. Ao instalar esse app, você concorda que é responsável por qualquer perda de dados ou dano ao dispositivo causados pelo uso desses apps."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Clone de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Continuar"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Configurações"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Instalando/desinstalando apps do Wear"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Restaurar <xliff:g id="APPNAME">%1$s</xliff:g> usando o app <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"O download desse app será feito em segundo plano"</string>
     <string name="restore" msgid="8460854736328970444">"Restaurar"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Você está off-line"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Este app será restaurado automaticamente quando você tiver uma conexão de Internet"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Algo deu errado"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Ocorreu um problema ao tentar restaurar este app"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Armazenamento insuficiente"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Para restaurar o app, libere espaço no dispositivo. Armazenamento necessário: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Ação necessária"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Siga as próximas etapas para restaurar este app"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"A <xliff:g id="INSTALLERNAME">%1$s</xliff:g> está desativada"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Para restaurar o app, ative a <xliff:g id="INSTALLERNAME">%1$s</xliff:g> nas Configurações"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"A <xliff:g id="INSTALLERNAME">%1$s</xliff:g> não está instalada"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Para restaurar o app, instale a <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Continuar"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Limpar armazenamento"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Configurações"</string>
+    <string name="close" msgid="5214897374055647996">"Fechar"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-ro/strings.xml b/packages/PackageInstaller/res/values-ro/strings.xml
index 810f544..cf50304 100644
--- a/packages/PackageInstaller/res/values-ro/strings.xml
+++ b/packages/PackageInstaller/res/values-ro/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Aplicațiile necunoscute nu pot fi instalate de acest utilizator"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Acest utilizator nu are permisiunea să instaleze aplicații"</string>
     <string name="ok" msgid="7871959885003339302">"OK"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Actualizează oricum"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Gestionează"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Spațiu de stocare insuficient"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Dezinstalează actualizarea"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> face parte din următoarea aplicație:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Dezinstalezi această aplicație?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Dezinstalezi această aplicație pentru "<b>"toți"</b>" utilizatorii? Aplicația și datele acesteia vor fi eliminate de la "<b>"toți"</b>" utilizatorii de pe acest dispozitiv."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Dezinstalezi această aplicație pentru utilizatorul <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Dezinstalezi această aplicație din profilul de serviciu?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Păstrează <xliff:g id="SIZE">%1$s</xliff:g> din datele aplicației."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Vrei să ștergi această aplicație?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Dezinstalezi această aplicație? Se va șterge și clona <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Dezinstalezi aplicația din spațiul privat?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Dezinstalări în curs"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Dezinstalări nereușite"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Se dezinstalează…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Gestionează utilizatorii"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"Aplicația <xliff:g id="APP_NAME">%1$s</xliff:g> nu a putut fi dezinstalată."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"A apărut o problemă la analizarea pachetului."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Acțiunile de instalare și dezinstalare nu sunt acceptate pe Wear."</string>
     <string name="message_staging" msgid="8032722385658438567">"Se pregătește aplicația…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Necunoscut"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Din motive de securitate, tableta nu are permisiunea să instaleze aplicații necunoscute din această sursă. Poți modifica această opțiune în setări."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Tableta și datele tale personale sunt mai vulnerabile la un atac din partea aplicațiilor necunoscute. Dacă instalezi aplicația, accepți că ești singura persoană responsabilă pentru deteriorarea tabletei sau pentru pierderea datelor, care pot avea loc în urma folosirii acesteia."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Televizorul și datele tale cu caracter personal sunt mai vulnerabile la un atac din partea aplicațiilor necunoscute. Dacă instalezi această aplicație, accepți că ești singura persoană responsabilă pentru deteriorarea televizorului sau pentru pierderea datelor, care pot avea loc în urma folosirii acesteia."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Clonează <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Continuă"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Setări"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Se (dez)instalează aplicațiile Wear"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Restabilești <xliff:g id="APPNAME">%1$s</xliff:g> din <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Descărcarea aplicației va începe în fundal"</string>
     <string name="restore" msgid="8460854736328970444">"Restabilește"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Ești offline"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Aplicația va fi restabilită automat după ce te conectezi la internet"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"A apărut o eroare"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"A apărut o problemă la restabilirea aplicației"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Nu există suficient spațiu de stocare"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Pentru a restabili aplicația, eliberează spațiu pe dispozitiv. Spațiu de stocare necesar: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Acțiune necesară"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Urmează pașii de mai jos pentru a restabili aplicația"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> este dezactivat"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Pentru a restabili aplicația, activează <xliff:g id="INSTALLERNAME">%1$s</xliff:g> în Setări"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> este dezinstalat"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Pentru a restabili aplicația, va trebui să instalezi <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Continuă"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Șterge datele stocate"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Setări"</string>
+    <string name="close" msgid="5214897374055647996">"Închide"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-ru/strings.xml b/packages/PackageInstaller/res/values-ru/strings.xml
index e368f12..2a85a0c 100644
--- a/packages/PackageInstaller/res/values-ru/strings.xml
+++ b/packages/PackageInstaller/res/values-ru/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Этот пользователь не может устанавливать неизвестные приложения."</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Этому пользователю не разрешено устанавливать приложения."</string>
     <string name="ok" msgid="7871959885003339302">"ОК"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Все равно обновить"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Управление приложениями"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Недостаточно места"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Удалить обновление"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> – часть следующего приложения:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Удалить приложение?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Удалить это приложение для "<b>"всех"</b>" пользователей устройства? Они потеряют доступ как к приложению, так и к связанным с ним данным."<b></b></string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Удалить это приложение из профиля <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Удалить это приложение из рабочего профиля?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Сохранить данные приложения (<xliff:g id="SIZE">%1$s</xliff:g>)"</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Удалить это приложение?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Удалить это приложение? Клон приложения <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> также будет удален."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Удалить это приложение из личного пространства?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Активные процессы удаления"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Ошибки удаления"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Удаление…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Управление пользователями"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"Не удалось удалить приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Не удалось обработать пакет."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Wear OS"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Установка и удаление не поддерживаются в Wear OS."</string>
     <string name="message_staging" msgid="8032722385658438567">"Подождите…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Неизвестное приложение"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"В целях безопасности ваш планшет блокирует установку неизвестных приложений из этого источника. Этот параметр можно изменить в настройках."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Ваши персональные данные и данные планшета более уязвимы для атак приложений из неизвестных источников. Устанавливая это приложение, вы берете на себя всю ответственность за последствия, связанные с его использованием, то есть за любой ущерб, нанесенный планшету, и возможную потерю данных."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Ваши персональные данные и данные телевизора более уязвимы для атак приложений из неизвестных источников. Устанавливая это приложение, вы берете на себя всю ответственность за последствия, связанные с его использованием, то есть за любой ущерб, нанесенный телевизору, и возможную потерю данных."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Клон приложения <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Продолжить"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Настройки"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Установка/удаление прилож. для Wear OS"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Восстановить приложение \"<xliff:g id="APPNAME">%1$s</xliff:g>\" из <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Приложение начнет скачиваться в фоновом режиме."</string>
     <string name="restore" msgid="8460854736328970444">"Восстановить"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Нет доступа к Сети"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Приложение автоматически восстановится, когда устройство будет подключено к интернету."</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Что-то пошло не так"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Не удалось восстановить приложение."</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Недостаточно места"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Чтобы восстановить приложение, освободите место на устройстве. Необходимо <xliff:g id="BYTES">%1$s</xliff:g>."</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Требуется действие"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Чтобы восстановить приложение, следуйте дальнейшим инструкциям."</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"Установщик \"<xliff:g id="INSTALLERNAME">%1$s</xliff:g>\" отключен"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Чтобы восстановить приложение, включите установщик \"<xliff:g id="INSTALLERNAME">%1$s</xliff:g>\" в настройках."</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"Установщик \"<xliff:g id="INSTALLERNAME">%1$s</xliff:g>\" удален"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Чтобы восстановить приложение, установите программу \"<xliff:g id="INSTALLERNAME">%1$s</xliff:g>\"."</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Продолжить"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Очистить хранилище"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Настройки"</string>
+    <string name="close" msgid="5214897374055647996">"Закрыть"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-si/strings.xml b/packages/PackageInstaller/res/values-si/strings.xml
index cea50a6..ae94d48 100644
--- a/packages/PackageInstaller/res/values-si/strings.xml
+++ b/packages/PackageInstaller/res/values-si/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"මෙම පරිශීලකයා මඟින් නොදන්නා යෙදුම් ස්ථාපනය කළ නොහැක"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"මෙම පරිශීලකයාට යෙදුම් ස්ථාපනය කිරීමට අවසර නැත"</string>
     <string name="ok" msgid="7871959885003339302">"හරි"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"කෙසේ වෙතත් යාවත්කාලීන කරන්න"</string>
     <string name="manage_applications" msgid="5400164782453975580">"යෙදුම් කළමනාකරණය කරන්න"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"ඉඩ නොමැත"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"යාවත්කාලිනය අස්ථාපනය කරන්න"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> පහත යෙදුමේ කොටසකි:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"ඔබට මෙම යෙදුම අස්ථාපනය කිරීමට අවශ්‍යද?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119"><b>"සියලු"</b>" පරිශීලකයන් සඳහා මෙම යෙදුම අස්ථාපනය කිරීමට ඔබට අවශ්‍යද? උපාංගයෙහි "<b>"සියලු"</b>" පරිශීලකයන් සඳහා යෙදුම සහ එහි දත්ත ඉවත්වනු ඇත."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"<xliff:g id="USERNAME">%1$s</xliff:g> පරිශීලකයා සඳහා මෙම යෙදුම අස්ථාපනය කිරීමට ඔබට අවශ්‍යයද?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"ඔබට කාර්යාල පැතිකඩ වෙතින් මෙම යෙදුම අස්ථාපනය කිරීමට අවශ්‍යද?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"යෙදුම් දත්තවලින් <xliff:g id="SIZE">%1$s</xliff:g> තබා ගන්න."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"ඔබට මෙම යෙදුම මැකීමට අවශ්‍ය ද?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"ඔබට මෙම යෙදුම අස්ථාපනය කිරීමට අවශ්‍ය ද? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ක්ලෝනය ද මකා දැමෙනු ඇත."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"ඔබට ඔබේ පෞද්ගලික අවකාශයෙන් මෙම යෙදුම අස්ථාපනය කිරීමට අවශ්‍ය ද?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"අස්ථාපන ධාවනය කරමින්"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"අසාර්ථක වූ අස්ථාපන"</string>
     <string name="uninstalling" msgid="8709566347688966845">"අස්ථාපනය කරමින්…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"පරිශීලකයන් කළමනාකරණය කරන්න"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> අස්ථාපනය කල නොහැක."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"පැකේජය විග්‍රහ කිරීමේදී ගැටළුවක් ඇති විය."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Wear මත ස්ථාපන/අස්ථාපනය ක්‍රියා සහාය දක්වන්නේ නැත."</string>
     <string name="message_staging" msgid="8032722385658438567">"යෙදුම වේදිකාගත කරමින්..."</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"නොදනී"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"ඔබගේ ආරක්ෂාව සඳහා, ඔබගේ ටැබ්ලටයට දැනට මෙම මූලාශ්‍රයෙන් නොදන්නා යෙදුම් ස්ථාපනය කිරීමට ඉඩ නොදේ. ඔබට සැකසීම් තුළ මෙය වෙනස් කළ හැකිය."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"ඔබගේ ටැබ්ලට් පරිගණකය සහ පුද්ගලික දත්තවලට නොදන්නා යෙදුම් මඟින් තර්ජන එල්ල කිරීමේ හැකියාව වැඩිය. මෙම යෙදුම් ස්ථාපනය කිරීමෙන් සහ භාවිත කිරීමෙන් ඔබ ඔබේ ටැබ්ලට් පරිගණකය සඳහා සිදු වන යම් හානි හෝ එය භාවිත කිරීමේ ප්‍රතිඵලයක් ලෙස සිදු වන දත්ත හානි සඳහා ඔබ වගකිව යුතු බවට එකඟ වේ."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"ඔබගේ TV සහ පුද්ගලික දත්තවලට නොදන්නා යෙදුම් මඟින් තර්ජන එල්ල කිරීමේ හැකියාව වැඩිය. මෙම යෙදුම් ස්ථාපනය කිරීමෙන් සහ භාවිත කිරීමෙන් ඔබ ඔබේ TV සඳහා සිදු වන යම් හානි හෝ එය භාවිත කිරීමේ ප්‍රතිඵලයක් ලෙස සිදු වන දත්ත හානි සඳහා ඔබ වගකිව යුතු බවට එකඟ වේ."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ක්ලෝනය"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"ඉදිරියට යන්න"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"සැකසීම්"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Wear යෙදුම් ස්ථාපනය/අස්ථාපනය කරමින්"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> වෙතින් <xliff:g id="APPNAME">%1$s</xliff:g> ප්‍රතිසාධනය කරන්න ද?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"මෙම යෙදුම පසුබිමේ බාගැනීම ආරම්භ කරනු ඇත"</string>
     <string name="restore" msgid="8460854736328970444">"ප්‍රතිසාධනය කරන්න"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"ඔබ නොබැඳි වේ"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"ඔබ අන්තර්ජාලයට සම්බන්ධ වූ විට මෙම යෙදුම ස්වයංක්‍රීයව ප්‍රතිසාධනය වනු ඇත"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"යමක් වැරදී ඇත"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"මෙම යෙදුම ප්‍රතිසාධනය කිරීමට උත්සාහ කිරීමේ ගැටලුවක් ඇති විය"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"ප්‍රමාණවත් ආචයනයක් නොමැත"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"මෙම යෙදුම ප්‍රතිසාධනය කිරීම සඳහා, ඔබට මෙම උපාංගයෙහි ඉඩ නිදහස් කර ගත හැක. අවශ්‍ය ආචයනය: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"ක්‍රියාමාර්ගය අවශ්‍යයි"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"මෙම යෙදුම ප්‍රතිසාධනය කිරීමට මීළඟ පියවර අනුගමනය කරන්න"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> අබල කර ඇත"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"මෙම යෙදුම ප්‍රතිසාධනය කිරීම සඳහා, සැකසීම් තුළ <xliff:g id="INSTALLERNAME">%1$s</xliff:g> සබල කරන්න"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> අස්ථාපනය කර ඇත"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"මෙම යෙදුම ප්‍රතිසාධනය කිරීම සඳහා, ඔබට <xliff:g id="INSTALLERNAME">%1$s</xliff:g> ස්ථාපනය කිරීමට අවශ්‍ය වනු ඇත"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"ඉදිරියට යන්න"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"ආචයනය හිස් කරන්න"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"සැකසීම්"</string>
+    <string name="close" msgid="5214897374055647996">"වසන්න"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-sk/strings.xml b/packages/PackageInstaller/res/values-sk/strings.xml
index 34117c3..53d4a84 100644
--- a/packages/PackageInstaller/res/values-sk/strings.xml
+++ b/packages/PackageInstaller/res/values-sk/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Tento používateľ nemôže inštalovať neznáme aplikácie"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Tento používateľ nemá povolené inštalovať aplikácie"</string>
     <string name="ok" msgid="7871959885003339302">"OK"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Napriek tomu aktualizovať"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Spravovať aplikácie"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Nedostatok miesta"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Odinštalovať aktualizáciu"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"Aktivita <xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> je súčasťou nasledujúcej aplikácie:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Chcete túto aplikáciu odinštalovať?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Chcete odinštalovať túto aplikáciu pre "<b>"všetkých"</b>" používateľov? Aplikácia a jej údaje sa odstránia z tohto zariadenia pre "<b>"všetkých"</b>" používateľov."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Chcete túto aplikáciu odinštalovať pre používateľa <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Chcete túto aplikáciu odinštalovať zo svojho pracovného profilu?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Zachovať nasledujúcu veľkosť dát aplikácie: <xliff:g id="SIZE">%1$s</xliff:g>."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Chcete túto aplikáciu odstrániť?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Chcete túto aplikáciu odinštalovať? Bude odstránený aj klon aplikácie <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Chcete túto aplikáciu odinštalovať zo svojho súkromného priestoru?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Prebiehajúce odinštalovania"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Neúspešné odinštalácie"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Prebieha odinštalovanie..."</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Spravovať používateľov"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"Aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g> sa nepodarilo odinštalovať."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Pri analýze balíka sa vyskytol problém."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Wear nepodporuje akciu inštalácie/odinštalovania."</string>
     <string name="message_staging" msgid="8032722385658438567">"Aplikácia je zavádzaná po etapách…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Neznáma"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Váš tablet momentálne nemôže z bezpečnostných dôvodov inštalovať neznáme aplikácie z tohto zdroja. Môžete to zmeniť v Nastaveniach."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Váš tablet a osobné dáta sú náchylnejšie na útok z neznámych aplikácií. Inštaláciou tejto aplikácie vyjadrujete súhlas s tým, že nesiete zodpovednosť za akékoľvek poškodenie tabletu alebo stratu dát, ktoré by mohli nastať pri jej používaní."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Váš televízor a osobné údaje sú náchylnejšie na útok z neznámych aplikácií. Inštaláciou tejto aplikácie vyjadrujete súhlas s tým, že nesiete zodpovednosť za akékoľvek poškodenie televízora alebo stratu údajov, ktoré by mohli nastať pri jej používaní."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Klon aplikácie <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Pokračovať"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Nastavenia"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Inštalácia/odinštalovanie aplikácií Wear"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Chcete obnoviť <xliff:g id="APPNAME">%1$s</xliff:g> z inštalátora <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Táto aplikácia sa začne sťahovať na pozadí"</string>
     <string name="restore" msgid="8460854736328970444">"Obnoviť"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Ste offline"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Po pripojení k internetu bude táto aplikácia automaticky obnovená"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Niečo sa pokazilo"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Pri pokuse o obnovenie tejto aplikácie sa vyskytol problém"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Úložisko je nedostatočné"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Ak chcete túto aplikáciu obnoviť, môžete uvoľniť priestor v tomto zariadení. Potrebný priestor: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Vyžaduje sa akcia"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Podľa nasledujúcich krokov obnovte túto aplikáciu"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"Inštalátor <xliff:g id="INSTALLERNAME">%1$s</xliff:g> je deaktivovaný"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Ak chcete túto aplikáciu obnoviť, zapnite v Nastaveniach <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"Inštalátor <xliff:g id="INSTALLERNAME">%1$s</xliff:g> je odinštalovaný"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Ak chcete túto aplikáciu obnoviť, musíte si nainštalovať <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Pokračovať"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Vymazať priestor"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Nastavenia"</string>
+    <string name="close" msgid="5214897374055647996">"Zavrieť"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-sl/strings.xml b/packages/PackageInstaller/res/values-sl/strings.xml
index a303759..2f6b697 100644
--- a/packages/PackageInstaller/res/values-sl/strings.xml
+++ b/packages/PackageInstaller/res/values-sl/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Ta uporabnik nima dovoljenja za nameščanje neznanih aplikacij"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Ta uporabnik nima dovoljenja za nameščanje aplikacij"</string>
     <string name="ok" msgid="7871959885003339302">"V redu"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Vseeno posodobi"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Upravlj. aplik."</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Zmanjkalo je prostora"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Odstrani posodobitev"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> je del te aplikacije:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Ali želite odmestiti to aplikacijo?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Ali želite odstraniti aplikacijo za "<b>"vse"</b>" uporabnike? Aplikacija in njeni podatki bodo odstranjeni iz "<b>"vseh"</b>" uporabnikov v napravi."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Ali želite to aplikacijo odstraniti za uporabnika <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Ali želite to aplikacijo odmestiti iz delovnega profila?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Obdrži <xliff:g id="SIZE">%1$s</xliff:g> podatkov aplikacije."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Ali želite izbrisati to aplikacijo?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Ali želite odmestiti to aplikacijo? Izbrisana bo tudi klonirana aplikacija <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Ali želite to aplikacijo odmestiti iz zasebnega prostora?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Odstranitve v teku"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Neuspele odstranitve"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Odstranjevanje …"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Upravljanje uporabnikov"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"Aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g> ni bilo mogoče odstraniti."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Težava pri razčlenjevanju paketa."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Dejanja namestitve in odstranitve v sistemu Android Wear niso podprta."</string>
     <string name="message_staging" msgid="8032722385658438567">"Priprava aplikacije …"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Neznano"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Tablični računalnik zaradi varnosti trenutno nima dovoljenja za nameščanje neznanih aplikacij iz tega vira. To lahko spremenite v nastavitvah."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Neznane aplikacije lahko resno ogrozijo varnost tabličnega računalnika in osebnih podatkov. Z namestitvijo te aplikacije se strinjate, da ste sami odgovorni za morebitno škodo, nastalo v tabličnem računalniku, ali izgubo podatkov, do katerih lahko pride zaradi uporabe te aplikacije."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Neznane aplikacije lahko resno ogrozijo varnost televizorja in osebnih podatkov. Z namestitvijo te aplikacije se strinjate, da ste sami odgovorni za morebitno škodo, nastalo v televizorju, ali izgubo podatkov, do katerih lahko pride zaradi uporabe te aplikacije."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Klonirana aplikacija <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Naprej"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Nastavitve"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Nameščanje/odstranjev. aplikacij za Wear"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Želite obnoviti aplikacijo <xliff:g id="APPNAME">%1$s</xliff:g> iz aplikacije <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Aplikacija bo začela prenos v ozadju"</string>
     <string name="restore" msgid="8460854736328970444">"Obnovi"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Nimate vzpostavljene povezave"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Ta aplikacija bo samodejno obnovljena, ko boste povezani v internet."</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Prišlo je do težave"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Pri obnavljanju te aplikacije je prišlo do težave."</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Ni dovolj prostora za shranjevanje"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Če želite obnoviti to aplikacijo, sprostite prostor v tej napravi. Potrebni prostor za shranjevanje: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Potrebno je ukrepanje"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Če želite obnoviti to aplikacijo, uporabite postopek, opisan v nadaljevanju."</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"Namestitveni program <xliff:g id="INSTALLERNAME">%1$s</xliff:g> je onemogočen"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Če želite obnoviti to aplikacijo, v nastavitvah omogočite »<xliff:g id="INSTALLERNAME">%1$s</xliff:g>«"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"Namestitveni program <xliff:g id="INSTALLERNAME">%1$s</xliff:g> je odmeščen"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Če želite obnoviti to aplikacijo, morate namestiti <xliff:g id="INSTALLERNAME">%1$s</xliff:g>."</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Nadaljuj"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Počisti shrambo"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Nastavitve"</string>
+    <string name="close" msgid="5214897374055647996">"Zapri"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-sq/strings.xml b/packages/PackageInstaller/res/values-sq/strings.xml
index 7f68c8b..1c4b354 100644
--- a/packages/PackageInstaller/res/values-sq/strings.xml
+++ b/packages/PackageInstaller/res/values-sq/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Aplikacionet e panjohura nuk mund të instalohen nga ky përdorues"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Ky përdorues nuk lejohet të instalojë aplikacione"</string>
     <string name="ok" msgid="7871959885003339302">"Në rregull"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Përditësoje gjithsesi"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Menaxho aplikacionet"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Nuk ka hapësirë"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Çinstalo përditësimin"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> është pjesë e aplikacionit të mëposhtëm:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Dëshiron ta çinstalosh këtë aplikacion?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Dëshiron ta çinstalosh këtë aplikacion për "<b>"të gjithë"</b>" përdoruesit? Aplikacioni dhe të dhënat e tij do të hiqen nga "<b>"të gjithë"</b>" përdoruesit e pajisjes."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Dëshiron ta çinstalosh këtë aplikacion për përdoruesin <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Dëshiron ta çinstalosh këtë aplikacion nga profili yt i punës?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Mbaj <xliff:g id="SIZE">%1$s</xliff:g> nga të dhënat e aplikacionit."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Dëshiron ta fshish këtë aplikacion?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Dëshiron ta çinstalosh këtë aplikacion? Kloni i <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> do të fshihet gjithashtu."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Dëshiron ta çinstalosh këtë aplikacion nga hapësira jote private?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Çinstalimet në ekzekutim"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Çinstalimet e dështuara"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Po çinstalohet…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Menaxho përdoruesit"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> nuk mund të çinstalohej."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Kishte një problem me analizimin e paketës."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Instalo/çinstalo veprimet që nuk mbështeten në Wear."</string>
     <string name="message_staging" msgid="8032722385658438567">"Po vihet në përdorim aplikacioni..."</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"I panjohur"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Për sigurinë tënde, tableti yt nuk lejohet aktualisht të instalojë aplikacione të panjohura nga ky burim. Këtë mund ta ndryshosh te \"Cilësimet\"."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Tableti dhe të dhënat e tua personale janë më të cenueshme nga sulmet nga aplikacione të panjohura. Duke instaluar këtë aplikacion, ti pranon se je përgjegjës për çdo dëm ndaj tabletit tënd ose çdo humbje të të dhënave që mund të rezultojë nga përdorimi i tij."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Televizori dhe të dhënat e tua personale janë më të cenueshme nga sulmet nga aplikacione të panjohura. Duke instaluar këtë aplikacion, ti pranon se je përgjegjës për çdo dëm ndaj televizorit tënd ose çdo humbje të të dhënave që mund të rezultojë nga përdorimi i tij."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Klon i <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Vazhdo"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Cilësimet"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Instalimi/çinstalimi i aplikacioneve të Wear"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Të restaurohet <xliff:g id="APPNAME">%1$s</xliff:g> nga <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Ky aplikacion do të fillojë të shkarkohet në sfond"</string>
     <string name="restore" msgid="8460854736328970444">"Restauro"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Je offline"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Ky aplikacion do të restaurohet automatikisht kur të lidhesh me internetin"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Ndodhi një gabim"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Pati një problem gjatë përpjekjes për të restauruar këtë aplikacion"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Hapësira ruajtëse e pamjaftueshme"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Për ta restauruar këtë aplikacion, mund të lirosh hapësirë në këtë pajisje. Hapësira ruajtëse e kërkuar: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Kërkohet veprim"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Ndiq hapat e radhës për të restauruar këtë aplikacion"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> është çaktivizuar"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Për ta restauruar këtë aplikacion, aktivizo <xliff:g id="INSTALLERNAME">%1$s</xliff:g> te \"Cilësimet\""</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> është çinstaluar"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Për ta restauruar këtë aplikacion, do të të duhet të instalosh <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Vazhdo"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Pastro hapësirën ruajtëse"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Cilësimet"</string>
+    <string name="close" msgid="5214897374055647996">"Mbyll"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-sr/strings.xml b/packages/PackageInstaller/res/values-sr/strings.xml
index 196e784..4402d7f 100644
--- a/packages/PackageInstaller/res/values-sr/strings.xml
+++ b/packages/PackageInstaller/res/values-sr/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Овај корисник не може да инсталира непознате апликације"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Овом кориснику није дозвољено да инсталира апликације"</string>
     <string name="ok" msgid="7871959885003339302">"Потврди"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Ипак ажурирај"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Управљајте апл."</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Нема више простора"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Деинсталирај ажурирање"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> је део следеће апликације:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Желите да деинсталирате ову апликацију?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Да ли желите да деинсталирате ову апликацију за "<b>"све"</b>" кориснике? Апликација и подаци уз ње биће уклоњени за "<b>"све"</b>" кориснике овог уређаја."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Желите ли да деинсталирате ову апликацију за корисника <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Да ли желите да деинсталирате ову апликацију са пословног профила?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Задржи <xliff:g id="SIZE">%1$s</xliff:g> података апликације."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Желите да избришете ову апликацију?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Желите да деинсталирате ову апликацију? Клон апликације <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ће такође бити избрисан."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Желите да деинсталирате ову апликацију из приватног простора?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Активна деинсталирања"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Неуспела деинсталирања"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Деинсталира се…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Управљаjте корисницима"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"Нисмо успели да деинсталирамо апликацију <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Дошло је до проблема при рашчлањивању пакета."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Радње Инсталирај/Деинсталирај нису подржане у Wear-у."</string>
     <string name="message_staging" msgid="8032722385658438567">"Апликација се припрема…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Непознато"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Из безбедносних разлога таблету тренутно није дозвољено да инсталира непознате апликације из овог извора. То можете да промените у подешавањима."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Таблет и лични подаци су подложнији нападу непознатих апликација. Ако инсталирате ову апликацију, прихватате да сте одговорни за евентуална оштећења таблета или губитак података до којих може да дође због њеног коришћења."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"ТВ и лични подаци су подложнији нападу непознатих апликација. Ако инсталирате ову апликацију, прихватате да сте одговорни за евентуална оштећења ТВ-а или губитак података до којих може да дође због њеног коришћења."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Клон апликације <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Настави"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Подешавања"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Инсталирање/деинсталирање Wear апликац."</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Желите да вратите <xliff:g id="APPNAME">%1$s</xliff:g> из <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Апликација ће започети преузимање у позадини."</string>
     <string name="restore" msgid="8460854736328970444">"Врати"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Офлајн сте"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Ова апликација ће бити враћена аутоматски када се повежете на интернет"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Дошло је до грешке"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Дошло је до проблема при враћању ове апликације"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Нема довољно меморијског простора"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Морате да ослободите простор на овом уређају да бисте вратили ову апликацију. Потребан меморијски простор: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Треба да реагујете"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Пратите даља упутства да бисте вратили ову апликацију"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> је онемогућен"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Да бисте вратили ову апликацију, омогућите <xliff:g id="INSTALLERNAME">%1$s</xliff:g> у Подешавањима"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> је деинсталиран"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Да бисте вратили ову апликацију, треба да инсталирате <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Настави"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Обриши меморијски простор"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Подешавања"</string>
+    <string name="close" msgid="5214897374055647996">"Затвори"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-sv/strings.xml b/packages/PackageInstaller/res/values-sv/strings.xml
index 0ce696e..ed016a8 100644
--- a/packages/PackageInstaller/res/values-sv/strings.xml
+++ b/packages/PackageInstaller/res/values-sv/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Denna användare får inte installera okända appar"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Användaren har inte behörighet att installera appar"</string>
     <string name="ok" msgid="7871959885003339302">"OK"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Uppdatera ändå"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Hantera appar"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Slut på utrymme"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Avinstallera uppdatering"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> är en del av följande app:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Vill du avinstallera appen?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Vill du avinstallera den här appen för "<b>"alla"</b>" användare? Appen och alla data i den tas bort från "<b>"alla"</b>" användare på enheten."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Vill du avinstallera appen för användaren <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Vill du avinstallera appen från jobbprofilen?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Behåll <xliff:g id="SIZE">%1$s</xliff:g> appdata."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Vill du radera den här appen?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Vill du avinstallera den här appen? Klonen av <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> raderas också."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Vill du avinstallera appen från ditt privata rum?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Avinstallationer som pågår"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Avinstallationer som misslyckats"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Avinstallerar …"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Hantera användare"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"Det gick inte att avinstallera <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Ett problem uppstod när paketet analyserades."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Åtgärder för att installera/avinstallera stöds inte på Wear."</string>
     <string name="message_staging" msgid="8032722385658438567">"Provkör appen …"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Okänd"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Av säkerhetsskäl får okända appar från den här källan inte installeras på surfplattan. Du kan ändra det här i inställningarna."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Din surfplatta och personliga data är mer sårbara för attacker från okända appar. Genom att installera denna app bekräftar du att du är ansvarig för eventuella skador på surfplattan och för dataförlust som kan uppstå vid användning av denna app."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Din tv och personliga data är mer sårbar för attacker från okända appar. Genom att installera denna app bekräftar du att du är ansvarig för eventuella skador på tv:n och för dataförlust som kan uppstå vid användning av denna app."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Klon av <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Fortsätt"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Inställningar"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Wear-appar installeras/avinstalleras"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Vill du återställa <xliff:g id="APPNAME">%1$s</xliff:g> från <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Appen börjar ladda ned i bakgrunden"</string>
     <string name="restore" msgid="8460854736328970444">"Återställ"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Du är offline"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Appen återställs automatiskt när du är ansluten till internet"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Något gick fel"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Det gick inte att återställa appen"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Inte tillräckligt med lagringsutrymme"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Frigör lagringsutrymme på enheten om du vill återställa appen. Tillgängligt lagringsutrymme som krävs: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Åtgärd krävs"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Följ anvisningarna för att återställa appen"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> är inaktiverad"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Aktivera <xliff:g id="INSTALLERNAME">%1$s</xliff:g> i inställningarna om du vill återställa appen"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> är avinstallerad"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Du måste installera <xliff:g id="INSTALLERNAME">%1$s</xliff:g> om du vill återställa appen"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Fortsätt"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Rensa lagringsutrymme"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Inställningar"</string>
+    <string name="close" msgid="5214897374055647996">"Stäng"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-sw/strings.xml b/packages/PackageInstaller/res/values-sw/strings.xml
index 0a34d81..7f03d91 100644
--- a/packages/PackageInstaller/res/values-sw/strings.xml
+++ b/packages/PackageInstaller/res/values-sw/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Mtumiaji huyu hana idhini ya kusakinisha programu ambazo hazijulikani"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Mtumiaji huyu haruhusiwi kusakinisha programu"</string>
     <string name="ok" msgid="7871959885003339302">"Sawa"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Sasisha tu"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Dhibiti programu"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Nafasi imejaa"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Ondoa sasisho"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> ni sehemu ya programu ifuatayo:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Ungependa kuondoa programu hii?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Je, ungependa kuondoa programu hii kwa watumiaji "<b>"wote"</b>"? Programu na data yake zitaondolewa kutoka kwa watumiaji "<b>"wote"</b>" kwenye kifaa."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Je, ungependa kuondoa programu hii kwa mtumiaji <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Ungependa kuondoa programu hii kwenye wasifu wako wa kazini?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Dumisha <xliff:g id="SIZE">%1$s</xliff:g> ya data ya programu."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Ungependa kufuta programu hii?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Ungependa kuondoa programu hii? Nakala ya <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> pia itafutwa."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Je, ungependa kuondoa programu hii kwenye nafasi yako ya faragha?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Programu zinazoondolewa"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Mara ambazo programu haikuondolewa"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Inaondoa…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Dhibiti watumiaji"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"Imeshindwa kuondoa <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Kumekuwa na tatizo la kuchanganua kifurushi."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Huduma ya Android Wear haiwezi kutekeleza vitendo vya Kusakinisha au Kuondoa vipengee."</string>
     <string name="message_staging" msgid="8032722385658438567">"Inatayarisha programu…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Haijulikani"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Kwa sababu ya usalama wako, kompyuta yako kibao kwa sasa hairuhusiwi kusakinisha programu zisizojulikana kutoka chanzo hiki. Unaweza kubadilisha hili katika Mipangilio."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Data yako ya binafsi na ya kompyuta yako kibao inaweza kuathiriwa na programu ambazo hazijulikani. Kwa kusakinisha programu hii, unakubali kuwajibikia uharibifu wowote kwenye kompyuta yako kibao au kupotea kwa data kutokana na matumizi yake."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Data yako ya binafsi na ya televisheni yako inaweza kuathiriwa na programu ambazo hazijulikani. Kwa kusakinisha programu hii, unakubali kuwajibikia uharibifu wowote kwenye televisheni yako au kupotea kwa data kutokana na matumizi yake."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Nakala ya <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Endelea"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Mipangilio"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Inasakinisha/inaondoa programu za Android Wear"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Je, ungependa kurejesha <xliff:g id="APPNAME">%1$s</xliff:g> kutoka kwenye <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Itaanza kupakua programu hii chinichini"</string>
     <string name="restore" msgid="8460854736328970444">"Rejesha"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Uko nje ya mtandao"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Programu hii itarejeshwa kiotomatiki utakapounganisha kwenye intaneti"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Hitilafu fulani imetokea"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Hitilafu fulani imetokea wakati wa kujaribu kurejesha programu hii"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Nafasi ya hifadhi haitoshi"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Ili urejeshe programu hii, unaweza kufuta faili ili upate nafasi kwenye kifaa hiki. Nafasi ya hifadhi inayohitajika: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Unahitaji kuchukua hatua"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Fuata hatua zinazofuata ili urejeshe programu hii"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> imezimwa"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Ili urejeshe programu hii, wezesha <xliff:g id="INSTALLERNAME">%1$s</xliff:g> kwenye Mipangilio"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> imeondolewa"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Ili urejeshe programu hii, utahitaji kusakinisha <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Endelea"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Futa data kwenye hifadhi"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Mipangilio"</string>
+    <string name="close" msgid="5214897374055647996">"Funga"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-ta/strings.xml b/packages/PackageInstaller/res/values-ta/strings.xml
index 322ce5c..3c98411 100644
--- a/packages/PackageInstaller/res/values-ta/strings.xml
+++ b/packages/PackageInstaller/res/values-ta/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"அறியப்படாத ஆப்ஸை இந்தப் பயனரால் நிறுவ இயலாது"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"ஆப்ஸை நிறுவ இந்தப் பயனருக்கு அனுமதியில்லை"</string>
     <string name="ok" msgid="7871959885003339302">"சரி"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"பரவாயில்லை, புதுப்பிக்கவும்"</string>
     <string name="manage_applications" msgid="5400164782453975580">"ஆப்ஸை நிர்வகி"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"போதுமான சேமிப்பிடம் இல்லை"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"புதுப்பிப்பை நிறுவல் நீக்குதல்"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> என்பது பின்வரும் ஆப்ஸின் பகுதியாகும்:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"இந்த ஆப்ஸை நிறுவல் நீக்க விரும்புகிறீர்களா?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"இந்த ஆப்ஸை "<b>"அனைத்துப்"</b>" பயனர்களுக்கும் நிறுவல் நீக்க விரும்புகிறீர்களா? ஆப்ஸும் அதன் தரவும் சாதனத்திலுள்ள "<b>"அனைத்துப்"</b>" பயனர்களிடமிருந்தும் அகற்றப்படும்."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"<xliff:g id="USERNAME">%1$s</xliff:g> என்ற பயனருக்கு இந்த ஆப்ஸை நிறுவல் நீக்க விரும்புகிறீர்களா?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"உங்கள் பணிக் கணக்கிலிருந்து இந்த ஆப்ஸை நிறுவல் நீக்க விரும்புகிறீர்களா?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"<xliff:g id="SIZE">%1$s</xliff:g> ஆப்ஸ் தரவை வைத்திரு."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"இந்த ஆப்ஸை நீக்க வேண்டுமா?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"இந்த ஆப்ஸை நிறுவல் நீக்க வேண்டுமா? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> குளோனும் நீக்கப்படும்."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"உங்கள் தனிப்பட்ட சேமிப்பிடத்திலிருந்து இந்த ஆப்ஸை நிறுவல் நீக்க வேண்டுமா?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"இயக்கத்திலுள்ள நிறுவல் நீக்கங்கள்"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"தோல்வியுற்ற நிறுவல் நீக்கங்கள்"</string>
     <string name="uninstalling" msgid="8709566347688966845">"நிறுவல் நீக்குகிறது…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"\'பயனர்களை\' நிர்வகி"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸை நிறுவல் நீக்க இயலவில்லை."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"தொகுப்பைப் பாகுபடுத்திப் பார்ப்பதில் சிக்கல் ஏற்பட்டது."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Wearரில் நிறுவல்கள்/நிறுவல் நீக்கங்கள் செய்ய இயலாது"</string>
     <string name="message_staging" msgid="8032722385658438567">"ஆப்ஸ் தயாராகிறது…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"அறியப்படாதது"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"உங்கள் பாதுகாப்புக்காக, இந்த மூலத்திலிருந்து அறியப்படாத ஆப்ஸை டேப்லெட்டில் நிறுவ தற்போது அனுமதியில்லை. இதை அமைப்புகளில் மாற்றலாம்."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"அறியப்படாத ஆப்ஸால் உங்கள் டேப்லெட்டும் தனிப்பட்ட தரவும் மிக எளிதாகப் பாதிப்புக்குள்ளாகலாம். இந்த ஆப்ஸை நிறுவுவதன் மூலம், இதைப் பயன்படுத்தும்போது டேப்லெட்டில் ஏதேனும் சிக்கல் ஏற்பட்டாலோ உங்களது தரவை இழந்தாலோ அதற்கு நீங்களே பொறுப்பாவீர்கள் என்பதை ஏற்கிறீர்கள்."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"அறியப்படாத ஆப்ஸால் உங்கள் டிவியும் தனிப்பட்ட தரவும் மிக எளிதாகப் பாதிப்புக்குள்ளாகலாம். இந்த ஆப்ஸை நிறுவுவதன் மூலம், இதைப் பயன்படுத்தும்போது டிவியில் ஏதேனும் சிக்கல் ஏற்பட்டாலோ உங்களது தரவை இழந்தாலோ அதற்கு நீங்களே பொறுப்பாவீர்கள் என்பதை ஏற்கிறீர்கள்."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> குளோன்"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"தொடர்க"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"அமைப்புகள்"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Wear ஆப்ஸை நிறுவுதல்/நிறுவல் நீக்குதல்"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g>ல் இருந்து <xliff:g id="APPNAME">%1$s</xliff:g> ஐ மீட்டெடுக்கவா?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"இந்த ஆப்ஸ் பின்னணியில் பதிவிறக்கத் தொடங்கும்"</string>
     <string name="restore" msgid="8460854736328970444">"மீட்டெடு"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"ஆஃப்லைனில் உள்ளீர்கள்"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"நீங்கள் இணையத்துடன் இணைக்கப்பட்டிருக்கும்போது இந்த ஆப்ஸ் தானாக மீட்டெடுக்கப்படும்"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"ஏதோ தவறாகிவிட்டது"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"இந்த ஆப்ஸை மீட்டெடுக்க முயலும்போது சிக்கல் ஏற்பட்டது"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"போதுமான சேமிப்பகம் இல்லை"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"இந்த ஆப்ஸை மீட்டெடுக்க, இந்தச் சாதனத்தில் உள்ள சேமிப்பகத்தை காலியாக்கலாம். தேவைப்படும் சேமிப்பகம்: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"நடவடிக்கை தேவை"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"இந்த ஆப்ஸை மீட்டெடுக்க அடுத்த வழிமுறைகளைப் பின்பற்றுங்கள்"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> முடக்கப்பட்டுள்ளது"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"இந்த ஆப்ஸை மீட்டெடுக்க அமைப்புகளில் <xliff:g id="INSTALLERNAME">%1$s</xliff:g> ஐ இயக்குங்கள்"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> நிறுவல் நீக்கப்பட்டது"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"இந்த ஆப்ஸை மீட்டெடுக்க <xliff:g id="INSTALLERNAME">%1$s</xliff:g> ஐ நிறுவ வேண்டும்"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"தொடர்க"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"சேமிப்பகத்தைக் காலியாக்கு"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"அமைப்புகள்"</string>
+    <string name="close" msgid="5214897374055647996">"மூடுக"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-te/strings.xml b/packages/PackageInstaller/res/values-te/strings.xml
index 9abc87e..ef00c9f 100644
--- a/packages/PackageInstaller/res/values-te/strings.xml
+++ b/packages/PackageInstaller/res/values-te/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"ఈ వినియోగదారు తెలియని యాప్‌లను ఇన్‌స్టాల్ చేయలేరు"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"యాప్‌లను ఇన్‌స్టాల్ చేయడానికి ఈ వినియోగదారుకు అనుమతి లేదు"</string>
     <string name="ok" msgid="7871959885003339302">"సరే"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"ఏదేమైనా అప్‌డేట్ చేయండి"</string>
     <string name="manage_applications" msgid="5400164782453975580">"యాప్‌లను నిర్వహించండి"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"ఖాళీ లేదు"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"అప్‌డేట్ అన్‌ఇన్‌స్టాల్ చేయి"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> అనేది కింది యాప్‌లో ఒక భాగం:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"మీరు ఈ యాప్‌ను అన్‌ఇన్‌స్టాల్ చేయాలనుకుంటున్నారా?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"మీరు ఈ యాప్‌ను "<b>"అందరు"</b>" వినియోగదారులకు అన్‌ఇన్‌స్టాల్ చేయాలనుకుంటున్నారా? అప్లికేషన్, దాని డేటా పరికరంలోని "<b>"అందరు"</b>" వినియోగదారుల నుండి తీసివేయబడుతుంది."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"మీరు వినియోగదారు <xliff:g id="USERNAME">%1$s</xliff:g> కోసం ఈ యాప్‌ను అన్‌ఇన్‌స్టాల్ చేయాలనుకుంటున్నారా?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"మీ వర్క్ ప్రొఫైల్ నుండి ఈ యాప్‌ను మీరు అన్‌ఇన్‌స్టాల్ చేయాలనుకుంటున్నారా?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"<xliff:g id="SIZE">%1$s</xliff:g> యాప్ డేటాను ఉంచండి."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"మీరు ఈ యాప్‌ను తొలగించాలనుకుంటున్నారా?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"మీరు ఈ యాప్‌ను అన్‌ఇన్‌స్టాల్ చేయాలనుకుంటున్నారా? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> క్లోన్ కూడా తొలగించబడుతుంది."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"మీరు మీ ప్రైవేట్ స్పేస్ నుండి ఈ యాప్‌ను అన్‌ఇన్‌స్టాల్ చేయాలనుకుంటున్నారా?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"అన్ఇన్‌స్టాల్ చేయబడుతున్నవి"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"విఫలమైన అన్‌ఇన్‌స్టాల్‌లు"</string>
     <string name="uninstalling" msgid="8709566347688966845">"అన్ఇన్‌స్టాల్ చేస్తోంది…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"వినియోగదారులను మేనేజ్ చేయండి"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g>ని అన్‌ఇన్‌స్టాల్ చేయడం సాధ్యపడలేదు."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"ప్యాకేజీని అన్వయించడంలో సమస్య ఏర్పడింది."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Wearలో ఇన్‌స్టాల్/అన్ఇన్‌స్టాల్ చర్యలకు మద్దతు లేదు."</string>
     <string name="message_staging" msgid="8032722385658438567">"యాప్‌ను సిద్ధం చేస్తుంది…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"తెలియదు"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"మీ సెక్యూరిటీ దృష్ట్యా, ఈ సోర్సు నుండి తెలియని యాప్‌లను ఇన్‌స్టాల్ చేయడానికి మీ టాబ్లెట్ ప్రస్తుతం అనుమతించబడదు. మీరు దీన్ని సెట్టింగ్‌లలో మార్చవచ్చు."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"మీ టాబ్లెట్ మరియు వ్యక్తిగత డేటాపై తెలియని యాప్‌లు దాడి చేయడానికి ఎక్కువ అవకాశం ఉంది. మీరు ఈ యాప్‌ను ఇన్‌స్టాల్ చేయడం ద్వారా, దీనిని ఉపయోగించడం వలన మీ టాబ్లెట్‌కు ఏదైనా హాని జరిగినా లేదా డేటా కోల్పోయినా బాధ్యత మీదేనని అంగీకరిస్తున్నారు."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"మీ టీవీ మరియు వ్యక్తిగత డేటాపై తెలియని యాప్‌లు దాడి చేయడానికి ఎక్కువ అవకాశం ఉంది. మీరు ఈ యాప్‌ను ఇన్‌స్టాల్ చేయడం ద్వారా, దీనిని ఉపయోగించడం వలన మీ టీవీకి ఏదైనా హాని జరిగినా లేదా డేటా కోల్పోయినా బాధ్యత మీదేనని అంగీకరిస్తున్నారు."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> క్లోన్"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"కొనసాగండి"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"సెట్టింగ్‌లు"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Wear యాప్‌లను ఇన్‌స్టాల్/అన్‌ఇన్‌స్టాల్ చేస్తోంది"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> నుండి <xliff:g id="APPNAME">%1$s</xliff:g>‌ను రీస్టోర్ చేయాలా?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"ఈ యాప్ బ్యాక్‌గ్రౌండ్‌లో డౌన్‌లోడ్ అవ్వడం ప్రారంభమవుతుంది"</string>
     <string name="restore" msgid="8460854736328970444">"రీస్టోర్ చేయండి"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"మీరు ఆఫ్‌లైన్‌లో ఉన్నారు"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"మీరు ఇంటర్నెట్‌కు కనెక్ట్ అయ్యి ఉన్నప్పుడు ఈ యాప్ ఆటోమేటిక్‌గా రీస్టోర్ చేయబడుతుంది"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"ఏదో పొరపాటు జరిగింది"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"ఈ యాప్‌ను రీస్టోర్ చేయడానికి ట్రై చేస్తున్నపుడు సమస్య ఏర్పడింది"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"తగినంత స్టోరేజ్ స్పేస్ లేదు"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"ఈ యాప్‌ను రీస్టోర్ చేయడానికి, మీరు ఈ పరికరంలో స్పేస్‌ను ఖాళీ చేయవచ్చు. స్టోరేజ్ అవసరం: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"మీరు పూర్తి చేయాల్సిన చర్య"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"ఈ యాప్‌ను రీస్టోర్ చేయడానికి తదుపరి దశలను ఫాలో అవ్వండి"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> డిజేబుల్ చేయబడింది"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"ఈ యాప్‌ను రీస్టోర్ చేయడానికి, సెట్టింగ్‌లలో <xliff:g id="INSTALLERNAME">%1$s</xliff:g>‌ను ఎనేబుల్ చేయండి"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> అన్‌ఇన్‌స్టాల్ చేయబడింది"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"ఈ యాప్‌ను రీస్టోర్ చేయడానికి, మీరు <xliff:g id="INSTALLERNAME">%1$s</xliff:g>‌ను ఇన్‌స్టాల్ చేయాలి"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"కొనసాగించండి"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"స్టోరేజ్‌ను క్లియర్ చేయండి"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"సెట్టింగ్‌లు"</string>
+    <string name="close" msgid="5214897374055647996">"మూసివేయండి"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-th/strings.xml b/packages/PackageInstaller/res/values-th/strings.xml
index b1faa1c..e330985 100644
--- a/packages/PackageInstaller/res/values-th/strings.xml
+++ b/packages/PackageInstaller/res/values-th/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"ผู้ใช้รายนี้ไม่สามารถติดตั้งแอปที่ไม่รู้จัก"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"ผู้ใช้รายนี้ไม่ได้รับอนุญาตให้ติดตั้งแอป"</string>
     <string name="ok" msgid="7871959885003339302">"ตกลง"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"อัปเดตเลย"</string>
     <string name="manage_applications" msgid="5400164782453975580">"จัดการแอป"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"ไม่มีพื้นที่"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"ถอนการติดตั้งการอัปเดต"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> เป็นส่วนหนึ่งของแอปต่อไปนี้"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"ต้องการถอนการติดตั้งแอปนี้ไหม"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"ต้องการถอนการติดตั้งแอปนี้สำหรับผู้ใช้"<b>"ทั้งหมด"</b>"ไหม ระบบจะนำแอปและข้อมูลในแอปออกจากผู้ใช้"<b>"ทั้งหมด"</b>"ที่อยู่ในอุปกรณ์"</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"ต้องการถอนการติดตั้งแอปนี้สำหรับผู้ใช้ <xliff:g id="USERNAME">%1$s</xliff:g> ไหม"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"คุณต้องการถอนการติดตั้งแอปนี้จากโปรไฟล์งานใช่ไหม"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"เก็บข้อมูลแอปไว้ <xliff:g id="SIZE">%1$s</xliff:g>"</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"ต้องการลบแอปนี้ไหม"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"ต้องการถอนการติดตั้งแอปนี้ไหม ระบบจะลบโคลนของ <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> ด้วย"</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"คุณต้องการถอนการติดตั้งแอปนี้จากพื้นที่ส่วนตัวไหม"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"กำลังเรียกใช้การถอนการติดตั้ง"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"ถอนการติดตั้งไม่สำเร็จ"</string>
     <string name="uninstalling" msgid="8709566347688966845">"กำลังถอนการติดตั้ง…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"จัดการผู้ใช้"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"ถอนการติดตั้ง <xliff:g id="APP_NAME">%1$s</xliff:g> ไม่ได้"</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"พบปัญหาในการแยกวิเคราะห์แพ็กเกจ"</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"ติดตั้ง/ถอนการติดตั้งใน Wear ไม่ได้"</string>
     <string name="message_staging" msgid="8032722385658438567">"กำลังปรับสภาพแวดล้อมของแอป…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"ไม่ทราบ"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"เพื่อความปลอดภัย ปัจจุบันไม่อนุญาตให้ติดตั้งแอปที่ไม่รู้จักจากแหล่งที่มานี้ในแท็บเล็ต คุณเปลี่ยนแปลงได้ในการตั้งค่า"</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"แท็บเล็ตและข้อมูลส่วนตัวของคุณมีความเสี่ยงมากขึ้นที่จะถูกโจมตีจากแอปที่ไม่รู้จัก การติดตั้งแอปนี้แสดงว่าคุณยอมรับว่าจะรับผิดชอบต่อความเสียหายใดๆ ที่จะเกิดขึ้นกับแท็บเล็ตหรือการสูญเสียข้อมูลที่อาจเกิดจากการใช้งานแอปดังกล่าว"</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"ทีวีและข้อมูลส่วนตัวของคุณมีความเสี่ยงมากขึ้นที่จะถูกโจมตีจากแอปที่ไม่รู้จัก การติดตั้งแอปนี้แสดงว่าคุณยอมรับว่าจะรับผิดชอบต่อความเสียหายใดๆ ที่จะเกิดขึ้นกับทีวีหรือการสูญเสียข้อมูลที่อาจเกิดจากการใช้งานแอปดังกล่าว"</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"โคลนของ <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"ดำเนินการต่อ"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"การตั้งค่า"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"กำลังติดตั้ง/ถอนการติดตั้งแอป Wear"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"กู้คืน <xliff:g id="APPNAME">%1$s</xliff:g> จาก <xliff:g id="INSTALLERNAME">%1$s</xliff:g> ใช่ไหม"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"แอปนี้จะเริ่มดาวน์โหลดในเบื้องหลัง"</string>
     <string name="restore" msgid="8460854736328970444">"กู้คืน"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"คุณออฟไลน์อยู่"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"แอปนี้จะคืนค่าโดยอัตโนมัติเมื่อคุณเชื่อมต่อกับอินเทอร์เน็ต"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"เกิดข้อผิดพลาด"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"เกิดปัญหาขณะพยายามคืนค่าแอปนี้"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"พื้นที่เก็บข้อมูลไม่เพียงพอ"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"หากต้องการคืนค่าแอปนี้ คุณสามารถเพิ่มพื้นที่ว่างในอุปกรณ์ โดยจะต้องใช้พื้นที่เก็บข้อมูล <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"ขอให้ดำเนินการ"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"ทำตามขั้นตอนถัดไปเพื่อคืนค่าแอปนี้"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> ถูกปิดใช้"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"หากต้องการคืนค่าแอปนี้ ให้เปิดใช้ <xliff:g id="INSTALLERNAME">%1$s</xliff:g> ในการตั้งค่า"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> ถูกถอนการติดตั้ง"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"หากต้องการคืนค่าแอปนี้ คุณจะต้องติดตั้ง <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"ต่อไป"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"ล้างพื้นที่เก็บข้อมูล"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"การตั้งค่า"</string>
+    <string name="close" msgid="5214897374055647996">"ปิด"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-tl/strings.xml b/packages/PackageInstaller/res/values-tl/strings.xml
index 8e6e2517..e7ef36b 100644
--- a/packages/PackageInstaller/res/values-tl/strings.xml
+++ b/packages/PackageInstaller/res/values-tl/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Hindi maaaring mag-install ang user na ito ng mga hindi kilalang app"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Hindi pinapayagan ang user na ito na mag-install ng mga app"</string>
     <string name="ok" msgid="7871959885003339302">"OK"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"I-update pa rin"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Pamahalaan ang app"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Wala nang espasyo"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"I-uninstall ang update"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"Bahagi ang <xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> ng sumusunod na app:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Gusto mo bang i-uninstall ang app na ito?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Gusto mo bang i-uninstall ang app na ito para sa "<b>"lahat"</b>" ng user? Aalisin ang application at ang data nito sa "<b>"lahat"</b>" ng user sa device."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Gusto mo bang i-uninstall ang app na ito para sa user na si <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Gusto mo bang i-uninstall ang app na ito sa iyong profile sa trabaho?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Panatilihin ang <xliff:g id="SIZE">%1$s</xliff:g> ng data ng app."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Gusto mo bang i-delete ang app na ito?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Gusto mo bang i-uninstall ang app na ito? Made-delete din ang clone ng <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Gusto mo bang i-uninstall ang app na ito sa iyong pribadong space?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Mga kasalukuyang pag-uninstall"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Mga hindi na-uninstall"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Ina-uninstall…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Pamahalaan ang mga user"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"Hindi ma-uninstall ang <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Nagkaroon ng problema sa pag-parse sa package."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Ang mga pagkilos na I-install/I-uninstall ay hindi sinusuportahan sa Wear."</string>
     <string name="message_staging" msgid="8032722385658438567">"Inihahanda ang app…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Hindi Kilala"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Para sa iyong seguridad, kasalukuyang hindi pinapayagan ang tablet mo na mag-install ng mga hindi kilalang app mula sa source na ito. Mababago mo ito sa Mga Setting."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Mas nanganganib ang iyong tablet at personal na data sa mga pag-atake mula sa mga hindi kilalang app. Sa pamamagitan ng pag-install ng app na ito, sumasang-ayon kang ikaw ang responsable sa anumang pinsala sa iyong tablet o pagkawala ng data na maaaring magresulta mula sa paggamit nito."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Mas nanganganib ang iyong TV at personal na data sa mga pag-atake mula sa mga hindi kilalang app. Sa pamamagitan ng pag-install ng app na ito, sumasang-ayon kang ikaw ang responsable sa anumang pinsala sa iyong TV o pagkawala ng data na maaaring magresulta mula sa paggamit nito."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Clone ng <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Magpatuloy"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Mga Setting"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Ini-install/ina-uninstall ang wear app"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"I-restore ang <xliff:g id="APPNAME">%1$s</xliff:g> mula sa <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Magsisimulang mag-download ang app na ito sa background"</string>
     <string name="restore" msgid="8460854736328970444">"I-restore"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Offline ka"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Awtomatikong mare-restore ang app na ito kapag nakakonekta ka sa internet"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Nagkaproblema"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Nagkaproblema sa pagsubok na i-restore ang app na ito"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Hindi sapat ang storage"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Para i-restore ang app na ito, puwede kang magbakante ng espasyo sa device na ito. Kinakailangang storage: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Nangangailangan ng pagkilos"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Sundin ang mga susunod na hakbang para i-restore ang app na ito"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"Naka-disable ang <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Para i-restore ang app na ito, i-enable ang <xliff:g id="INSTALLERNAME">%1$s</xliff:g> sa Mga Setting"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"Na-uninstall ang <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Para i-restore ang app na ito, kailangan mong i-install ang <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Magpatuloy"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"I-clear ang storage"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Mga Setting"</string>
+    <string name="close" msgid="5214897374055647996">"Isara"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-tr/strings.xml b/packages/PackageInstaller/res/values-tr/strings.xml
index dc84030..3a0e053 100644
--- a/packages/PackageInstaller/res/values-tr/strings.xml
+++ b/packages/PackageInstaller/res/values-tr/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Bilinmeyen uygulamalar bu kullanıcı tarafından yüklenemez"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Bu kullanıcının uygulama yüklemesine izin verilmiyor"</string>
     <string name="ok" msgid="7871959885003339302">"Tamam"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Yine de güncelle"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Uygulamaları yönet"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Yer kalmadı"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Güncelleme kaldırılsın mı?"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g>, şu uygulamanın bir parçasıdır:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Bu uygulamanın yüklemesini kaldırmak istiyor musunuz?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Bu uygulamanın yüklemesini "<b>"tüm"</b>" kullanıcılar için kaldırmak istiyor musunuz? Uygulama ve verileri cihazdan "<b>"tüm"</b>" kullanıcılar için kaldırılacaktır."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"<xliff:g id="USERNAME">%1$s</xliff:g> adlı kullanıcı için bu uygulamanın yüklemesini kaldırmak istiyor musunuz?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Bu uygulamanın iş profilinizdeki yüklemesini kaldırmak istiyor musunuz?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Uygulama verilerinin <xliff:g id="SIZE">%1$s</xliff:g> kadarını sakla."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Bu uygulamayı silmek istiyor musunuz?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Bu uygulamanın yüklemesini kaldırmak istiyor musunuz? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> klonu da silinecektir."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Bu uygulamanın gizli alanınızdaki yüklemesini kaldırmak istiyor musunuz?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Devam eden yükleme kaldırma işlemleri"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Başarısız yükleme kaldırma işlemleri"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Yükleme kaldırılıyor…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Kullanıcıları yönet"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> kaldırılamadı."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Paketin ayrıştırılmasında bir sorun oluştu."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Yükleme/Yüklemeyi kaldırma işlemleri Wear\'da desteklenmiyor."</string>
     <string name="message_staging" msgid="8032722385658438567">"Uygulama hazırlanıyor…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Bilinmiyor"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Güvenlik nedeniyle şu anda tabletinizin bu kaynaktan bilinmeyen uygulamalar yüklemesine izin verilmemektedir. Bunu Ayarlar\'da değiştirebilirsiniz."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Tabletiniz ve kişisel verileriniz, bilinmeyen uygulamaların saldırılarına karşı daha savunmasızdır. Bu uygulamayı yükleyerek, uygulama kullanımından dolayı tabletinizde oluşabilecek hasarın veya uğrayabileceğiniz veri kaybının sorumluluğunu kabul etmiş olursunuz."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"TV\'niz ve kişisel verileriniz, bilinmeyen uygulamaların saldırılarına karşı daha savunmasızdır. Bu uygulamayı yükleyerek, uygulama kullanımından dolayı TV\'nizde oluşabilecek hasarın veya uğrayabileceğiniz veri kaybının sorumluluğunu kabul etmiş olursunuz."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> Klonu"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Devam"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Ayarlar"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Wear uygulamalarını yükleme/kaldırma"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"<xliff:g id="APPNAME">%1$s</xliff:g> uygulaması <xliff:g id="INSTALLERNAME">%1$s</xliff:g> üzerinden geri yüklensin mi?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Bu uygulama arka planda indirilmeye başlanacak"</string>
     <string name="restore" msgid="8460854736328970444">"Geri yükle"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"İnternete bağlı değilsiniz"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Bu uygulama, internete bağlandığınızda otomatik olarak geri yüklenecek"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Bir hata oluştu"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Bu uygulamayı geri yüklemeye çalışırken bir sorun oluştu"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Yeterli depolama alanı yok"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Bu uygulamayı geri yüklemek için bu cihazda yer açabilirsiniz. Bunun için <xliff:g id="BYTES">%1$s</xliff:g> depolama alanı gerekiyor"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"İşlem gerekli"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Bu uygulamayı geri yüklemek için sonraki adımları uygulayın"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> devre dışı bırakıldı"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Bu uygulamayı geri yüklemek için Ayarlar\'da <xliff:g id="INSTALLERNAME">%1$s</xliff:g> yükleyicisini etkinleştirin"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> yüklemesi kaldırılmış"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Bu uygulamayı geri yüklemek için <xliff:g id="INSTALLERNAME">%1$s</xliff:g> yükleyicisini yüklemeniz gerekiyor"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Devam"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Depolama alanını temizle"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Ayarlar"</string>
+    <string name="close" msgid="5214897374055647996">"Kapat"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-uk/strings.xml b/packages/PackageInstaller/res/values-uk/strings.xml
index 3d7083f..4ac9185 100644
--- a/packages/PackageInstaller/res/values-uk/strings.xml
+++ b/packages/PackageInstaller/res/values-uk/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Цей користувач не може встановлювати невідомі додатки"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Цей користувач не може встановлювати додатки"</string>
     <string name="ok" msgid="7871959885003339302">"OK"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Усе одно оновити"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Керувати додатками"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Недостат. місця"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Видалити оновлення"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"Дія <xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> є частиною такої програми:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Видалити цей додаток?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Хочете видалити цю програму для "<b>"всіх"</b>" користувачів? Програму та її дані буде видалено для "<b>"всіх"</b>" користувачів цього пристрою."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Видалити цей додаток для користувача <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Видалити цей додаток із вашого робочого профілю?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Залишити <xliff:g id="SIZE">%1$s</xliff:g> даних додатка."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Видалити цей додаток?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Видалити цей додаток? Копію <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> також буде видалено."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Видалити цей додаток із вашого приватного простору?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Активні видалення"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Невиконані видалення"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Видалення..."</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Керувати користувачами"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"Програму <xliff:g id="APP_NAME">%1$s</xliff:g> неможливо видалити."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Під час аналізу пакету виникла помилка."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Встановлення й видалення не підтримуються на пристроях Android Wear."</string>
     <string name="message_staging" msgid="8032722385658438567">"Підготовка додатка…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Невідомо"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"З міркувань безпеки на вашому планшеті зараз заборонено встановлювати невідомі додатки з цього джерела. Ви можете змінити це в налаштуваннях."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Ваш планшет і особисті дані більш уразливі до атак невідомих додатків. Установлюючи цей додаток, ви берете на себе відповідальність за пошкодження планшета чи втрату даних унаслідок використання додатка."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Ваш телевізор і особисті дані більш уразливі до атак невідомих додатків. Установлюючи цей додаток, ви берете на себе відповідальність за пошкодження телевізора чи втрату даних унаслідок використання додатка."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Копія додатка <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Продовжити"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Налаштування"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Встановлення або видалення додатків Wear"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Відновити додаток <xliff:g id="APPNAME">%1$s</xliff:g> з <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Цей додаток почне завантажуватись у фоновому режимі"</string>
     <string name="restore" msgid="8460854736328970444">"Відновити"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Пристрій не в мережі"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Додаток автоматично відновиться, коли пристрій підключиться до Інтернету"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Помилка"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Під час спроби відновити цей додаток сталася помилка"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Недостатньо пам’яті"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Щоб відновити цей додаток, ви можете звільнити місце на пристрої. Потрібний обсяг пам’яті: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Потрібна дія"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Виконайте подальші вказівки, щоб відновити цей додаток"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> вимкнено"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Щоб відновити цей додаток, увімкніть <xliff:g id="INSTALLERNAME">%1$s</xliff:g> у налаштуваннях"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> видалено"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Щоб відновити цей додаток, установіть <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Продовжити"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Очистити пам’ять"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Налаштування"</string>
+    <string name="close" msgid="5214897374055647996">"Закрити"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-ur/strings.xml b/packages/PackageInstaller/res/values-ur/strings.xml
index 08a8315..6730574 100644
--- a/packages/PackageInstaller/res/values-ur/strings.xml
+++ b/packages/PackageInstaller/res/values-ur/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"یہ صارف نامعلوم ایپس کو انسٹال نہیں کر سکتا"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"اس صارف کو ایپس انسٹال کرنے کی اجازت نہیں ہے"</string>
     <string name="ok" msgid="7871959885003339302">"ٹھیک ہے"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"بہر حال اپ ڈیٹ کریں"</string>
     <string name="manage_applications" msgid="5400164782453975580">"ایپس منظم کریں"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"جگہ نہیں ہے"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"اپ ڈیٹ اَن انسٹال کریں"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> درج ذیل ایپ کا حصہ ہے:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"کیا آپ اس ایپ کو اَن انسٹال کرنا چاہتے ہیں؟"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"کیا آپ "<b>"سبھی"</b>" صارفین کیلئے اس ایپ کو اَن انسٹال کرنا چاہتے ہیں؟ ایپلیکیشن اور اس کا ڈیٹا آلہ پر موجود "<b>"سبھی"</b>" صارفین سے ہٹا دیا جائے گا۔"</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"کیا آپ اس ایپ کو صارف <xliff:g id="USERNAME">%1$s</xliff:g> کیلئے اَن انسٹال کرنا چاہتے ہیں؟"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"کیا آپ اپنے دفتری پروفائل سے یہ ایپ اَن انسٹال کرنا چاہتے ہیں؟"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"ایپ ڈیٹا کا <xliff:g id="SIZE">%1$s</xliff:g> رکھیں۔"</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"کیا آپ یہ ایپ حذف کرنا چاہتے ہیں؟"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"کیا آپ یہ ایپ اَن انسٹال کرنا چاہتے ہیں؟ <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> کلون کو بھی حذف کر دیا جائے گا۔"</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"کیا آپ اس ایپ کو اپنی نجی جگہ سے اَن انسٹال کرنا چاہتے ہیں؟"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"چل رہے اَن انسٹالز"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"ناکام اَن انسٹالز"</string>
     <string name="uninstalling" msgid="8709566347688966845">"اَن انسٹال ہو رہا ہے…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"صارفین کا نظم کریں"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> کو اَن انسٹال نہیں کیا جا سکا۔"</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"پیکیج کو پارس کرنے میں ایک مسئلہ تھا۔"</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"‏\'انسٹال/اَن انسٹال کی کارروائیاں\' Wear پر تعاون یافتہ نہیں ہیں۔"</string>
     <string name="message_staging" msgid="8032722385658438567">"ایپ کی ٹیسٹنگ ہو رہی ہے…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"نامعلوم"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"آپ کی سیکیورٹی کی خاطر فی الحال آپ کے ٹیبلیٹ کو اس ماخذ سے نامعلوم ایپس انسٹال کرنے کی اجازت نہیں ہے۔ آپ ترتیبات میں اسے تبدیل کر سکتے ہیں۔"</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"آپ کے ٹیبلیٹ اور ذاتی ڈیٹا کو نامعلوم ایپس کی جانب سے حملے کا زیادہ خطرہ ہے۔ اس ایپ کو انسٹال کر کے، آپ اس بات سے اتفاق کرتے ہیں کہ آپ اس سے اپنے ٹیبلیٹ کو ہونے والے کسی بھی نقصان یا ڈیٹا کے نقصان کے لئے خود ذمہ دار ہیں۔"</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"‏آپ کے TV اور ذاتی ڈیٹا کو نامعلوم ایپس کی جانب سے حملے کا زیادہ خطرہ ہے۔ اس ایپ کو انسٹال کر کے، آپ اس بات سے اتفاق کرتے ہیں کہ آپ اس سے اپنے TV کو ہونے والے کسی بھی نقصان یا ڈیٹا کے نقصان کے لئے خود ذمہ دار ہیں۔"</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> کلون"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"جاری رکھیں"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"ترتیبات"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"‏wear ایپس کو انسٹال/اَن انسٹال کرنا"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"<xliff:g id="APPNAME">%1$s</xliff:g> کو <xliff:g id="INSTALLERNAME">%1$s</xliff:g> سے بحال کریں"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"یہ ایپ پس منظر میں ڈاؤن لوڈ ہونا شروع ہو جائے گی"</string>
     <string name="restore" msgid="8460854736328970444">"بحال کریں"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"آپ آف لائن ہیں"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"جب آپ انٹرنیٹ سے منسلک ہوں گے تو یہ ایپ خودکار طور پر بحال ہو جائے گی"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"کچھ غلط ہو گیا"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"اس ایپ کو بحال کرنے کی کوشش میں ایک مسئلہ تھا"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"کافی اسٹوریج نہیں ہے"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"اس ایپ کو بحال کرنے کے لیے، آپ اس آلہ پر اسپیس خالی کر سکتے ہیں۔ درکار اسٹوریج: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"کارروائی درکار ہے"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"اس ایپ کو بحال کرنے کے لیے اگلے مراحل کی پیروی کریں"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> غیر فعال ہے"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"اس ایپ کو بحال کرنے کے لیے، ترتیبات میں <xliff:g id="INSTALLERNAME">%1$s</xliff:g> کو فعال کریں"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> اَن انسٹال ہو گیا ہے"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"اس ایپ کو بحال کرنے کے لیے، آپ کو <xliff:g id="INSTALLERNAME">%1$s</xliff:g> انسٹال کرنا ہوگا"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"جاری رکھیں"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"اسٹوریج صاف کریں"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"ترتیبات"</string>
+    <string name="close" msgid="5214897374055647996">"بند کریں"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-uz/strings.xml b/packages/PackageInstaller/res/values-uz/strings.xml
index 894e867..cc5f6bdd 100644
--- a/packages/PackageInstaller/res/values-uz/strings.xml
+++ b/packages/PackageInstaller/res/values-uz/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Notanish ilovalarni bu foydalanuvchi tomonidan o‘rnatib bo‘lmaydi"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Bu foydalanuvchiga ilovalarni o‘rnatish uchun ruxsat berilmagan"</string>
     <string name="ok" msgid="7871959885003339302">"OK"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Baribir yangilansin"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Ilovalarni boshqarish"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Joy qolmadi"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Yangilanishni o‘chirish"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> quyidagi ilovaning bir qismidir:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Bu ilovani o‘chirib tashlamoqchimisiz?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Ushbu ilova "<b>"barcha"</b>" foydalanuvchilar uchun o‘chirilsinmi? Ilova va uning axborotlari qurilmadagi "<b>"barcha"</b>" foydalanuvchilardan o‘chib ketadi."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Haqiqatdan ham <xliff:g id="USERNAME">%1$s</xliff:g> foydalanuvchi uchun ushbu ilovani olib tashlamoqchimisiz?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Bu ilova ish profilidan olib tashlansinmi?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"<xliff:g id="SIZE">%1$s</xliff:g> hajmdagi ilova axborotlari saqlab qolinsin"</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Bu ilova oʻchirilsinmi?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Bu ilovani oʻchirib tashlamoqchimisiz? <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> nusxasi ham oʻchib ketadi."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Bu ilovani maxfiy joydan olib tashlamoqchimisiz?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Davom etayotganlar"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Amalga oshmaganlar"</string>
     <string name="uninstalling" msgid="8709566347688966845">"O‘chirilmoqda…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Foydalanuvchilarni boshqarish"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"<xliff:g id="APP_NAME">%1$s</xliff:g> o‘chirilmadi."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Paketni tahlil qilishda muammo yuz berdi."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Wear qurilmasi o‘rnatish/o‘chirish amallarini qo‘llab-quvvatlamaydi."</string>
     <string name="message_staging" msgid="8032722385658438567">"Kutib turing…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Noaniq"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Xavfsizlik yuzasidan, planshetingizga hozirda bu manbadan notanish ilovalarni o‘rnatishga ruxsat berilmagan. Buni sozlamalardan oʻzgartirish mumkin."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Planshetingiz va shaxsiy axborotlaringiz notanish ilovalar hujumiga zaif bo‘ladi. Bu ilovani o‘rnatish bilan planshetingizga yetkaziladigan shikast va axborotlaringizni o‘chirib yuborilishiga javobgarlikni o‘z zimmangizga olasiz."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"TV va shaxsiy axborotlaringiz notanish ilovalar hujumiga zaif bo‘ladi. Bu ilovani o‘rnatish bilan televizoringizga yetkaziladigan shikast va axborotlaringizni o‘chirib yuborilishiga javobgarlikni o‘z zimmangizga olasiz."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> nusxasi"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Davom etish"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Sozlamalar"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Wear ilovalarini o‘rnatish/o‘chirish"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"<xliff:g id="APPNAME">%1$s</xliff:g> ilovasi <xliff:g id="INSTALLERNAME">%1$s</xliff:g> orqali tiklansinmi?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Bu ilova orqa fonda yuklab olinishi boshlanadi"</string>
     <string name="restore" msgid="8460854736328970444">"Tiklash"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Siz internetga ulanmagansiz"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Internetga ulanganingizda bu ilova avtomatik ravishda tiklanadi"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Nimadir xato ketdi"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Bu ilovani tiklashda muammo chiqdi"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Xotirada yetarli boʻsh joy yoʻq"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Bu ilovani tiklash uchun ushbu qurilmada joy ochishingiz mumkin. Kerakli joy: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Amal bajarish zarur"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Bu ilovani tiklash uchun keyingi qadamlarga rioya qiling"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> faolsizlantirilgan"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Bu ilovani tiklash uchun Sozlamalar orqali <xliff:g id="INSTALLERNAME">%1$s</xliff:g> xizmatini yoqing"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> oʻchirib tashlandi"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Bu ilovani tiklash uchun <xliff:g id="INSTALLERNAME">%1$s</xliff:g> oʻrnatilishi kerak"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Davom etish"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Xotirani tozalash"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Sozlamalar"</string>
+    <string name="close" msgid="5214897374055647996">"Yopish"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-vi/strings.xml b/packages/PackageInstaller/res/values-vi/strings.xml
index 14959da..6af9b82 100644
--- a/packages/PackageInstaller/res/values-vi/strings.xml
+++ b/packages/PackageInstaller/res/values-vi/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Người dùng này không thể cài đặt ứng dụng không xác định"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Người dùng này không được phép cài đặt ứng dụng"</string>
     <string name="ok" msgid="7871959885003339302">"OK"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Vẫn cập nhật"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Quản lý ứng dụng"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Hết dung lượng"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Gỡ cài đặt bản cập nhật"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> là một phần của ứng dụng sau:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Bạn có muốn gỡ cài đặt ứng dụng này không?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Bạn có muốn gỡ cài đặt ứng dụng này cho "<b>"tất cả"</b>" người dùng không? Ứng dụng và dữ liệu của ứng dụng sẽ bị xóa khỏi "<b>"tất cả"</b>" người dùng trên thiết bị."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Bạn có muốn gỡ cài đặt ứng dụng này cho người dùng <xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Bạn có muốn gỡ cài đặt ứng dụng này khỏi hồ sơ công việc của mình không?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Giữ lại <xliff:g id="SIZE">%1$s</xliff:g> dữ liệu ứng dụng."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Bạn có muốn xoá ứng dụng này không?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Bạn có muốn gỡ cài đặt ứng dụng này không? Bản sao của <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> cũng sẽ bị xoá."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Bạn có muốn gỡ cài đặt ứng dụng này khỏi không gian riêng tư của mình không?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Các quá trình gỡ cài đặt đang chạy"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Gỡ cài đặt không thành công"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Đang gỡ cài đặt..."</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Quản lý người dùng"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"Không thể gỡ cài đặt <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Đã xảy ra sự cố khi phân tích cú pháp gói."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Không hỗ trợ thao tác Cài đặt/Gỡ cài đặt trên ứng dụng Wear."</string>
     <string name="message_staging" msgid="8032722385658438567">"Đang thử nghiệm ứng dụng…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Không xác định"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Để bảo mật, máy tính bảng của bạn hiện không được phép cài đặt các ứng dụng không xác định từ nguồn này. Bạn có thể thay đổi chế độ này trong phần Cài đặt."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Máy tính bảng và dữ liệu cá nhân của bạn dễ bị các ứng dụng không xác định tấn công hơn. Bằng cách cài đặt ứng dụng này, bạn đồng ý tự chịu trách nhiệm cho mọi hỏng hóc đối với máy tính bảng của mình hoặc mất mát dữ liệu có thể phát sinh do sử dụng ứng dụng này."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"TV và dữ liệu cá nhân của bạn dễ bị các ứng dụng không xác định tấn công hơn. Bằng cách cài đặt ứng dụng này, bạn đồng ý tự chịu trách nhiệm cho mọi hỏng hóc đối với TV của mình hoặc mất mát dữ liệu có thể phát sinh do sử dụng ứng dụng này."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Bản sao của <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Tiếp tục"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Cài đặt"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Cài đặt/gỡ cài đặt ứng dụng Wear"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Khôi phục <xliff:g id="APPNAME">%1$s</xliff:g> từ <xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Ứng dụng này sẽ bắt đầu tải xuống ở chế độ nền"</string>
     <string name="restore" msgid="8460854736328970444">"Khôi phục"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Không có kết nối mạng"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Ứng dụng này sẽ tự động khôi phục khi bạn kết nối với Internet"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Đã xảy ra lỗi"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Đã xảy ra vấn đề khi tìm cách khôi phục ứng dụng này"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Không đủ dung lượng lưu trữ"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Để khôi phục ứng dụng này, bạn có thể giải phóng dung lượng trên thiết bị này. Dung lượng lưu trữ cần thiết: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Việc cần làm"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Hãy làm theo các bước tiếp theo để khôi phục ứng dụng này"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> đã bị tắt"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Để khôi phục ứng dụng này, hãy bật <xliff:g id="INSTALLERNAME">%1$s</xliff:g> trong phần Cài đặt"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> đã bị gỡ cài đặt"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Để khôi phục ứng dụng này, bạn sẽ phải cài đặt <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Tiếp tục"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Xoá bộ nhớ"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Cài đặt"</string>
+    <string name="close" msgid="5214897374055647996">"Đóng"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-zh-rCN/strings.xml b/packages/PackageInstaller/res/values-zh-rCN/strings.xml
index ae12559..3e77d7f 100644
--- a/packages/PackageInstaller/res/values-zh-rCN/strings.xml
+++ b/packages/PackageInstaller/res/values-zh-rCN/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"该用户无法安装未知应用"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"此用户无权安装应用"</string>
     <string name="ok" msgid="7871959885003339302">"确定"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"仍然更新"</string>
     <string name="manage_applications" msgid="5400164782453975580">"管理应用"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"空间不足"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"卸载更新"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g>属于以下应用:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"要卸载此应用吗?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"要为"<b>"所有"</b>"用户卸载此应用吗?系统将为设备上的"<b>"所有"</b>"用户移除此应用及其数据。"</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"要为用户<xliff:g id="USERNAME">%1$s</xliff:g>卸载此应用吗?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"您想从您的工作资料中卸载此应用吗?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"保留 <xliff:g id="SIZE">%1$s</xliff:g> 的应用数据。"</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"要删除此应用吗?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"要卸载此应用吗?<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> 克隆应用也会被删除。"</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"要从私密空间卸载此应用吗?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"正在进行卸载操作"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"卸载操作失败"</string>
     <string name="uninstalling" msgid="8709566347688966845">"正在卸载…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"管理用户"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"无法卸载<xliff:g id="APP_NAME">%1$s</xliff:g>。"</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"解析软件包时出现问题。"</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Wear 不支持安装/卸载操作。"</string>
     <string name="message_staging" msgid="8032722385658438567">"正在准备安装应用…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"未知"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"出于安全考虑,目前已禁止您的平板电脑安装来自此来源的未知应用。您可以在“设置”中对此进行更改。"</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"来历不明的应用很可能会损害您的平板电脑和个人数据。安装该应用即表示,您同意对于因使用该应用可能导致的任何平板电脑损坏或数据丢失情况,您负有全部责任。"</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"来历不明的应用很可能会损害您的电视和个人数据。安装该应用即表示,您同意对于因使用该应用可能导致的任何电视损坏或数据丢失情况,您负有全部责任。"</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> 克隆应用"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"继续"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"设置"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"正在安装/卸载 Wear 应用"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"要从 <xliff:g id="INSTALLERNAME">%1$s</xliff:g> 中恢复 <xliff:g id="APPNAME">%1$s</xliff:g> 吗?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"系统将开始在后台下载此应用"</string>
     <string name="restore" msgid="8460854736328970444">"恢复"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"您没有联网"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"当您联网后,此应用将自动恢复"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"出了点问题"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"尝试恢复此应用时出现问题"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"存储空间不足"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"若要恢复此应用,您需要释放此设备上的空间。所需的存储空间为:<xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"请采取行动"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"请按照后续步骤恢复此应用"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> 已停用"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"若要恢复此应用,请在“设置”中启用 <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> 已卸载"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"若要恢复此应用,您需要安装 <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"继续"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"清空存储空间"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"设置"</string>
+    <string name="close" msgid="5214897374055647996">"关闭"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-zh-rHK/strings.xml b/packages/PackageInstaller/res/values-zh-rHK/strings.xml
index 5a79817..4d2edea 100644
--- a/packages/PackageInstaller/res/values-zh-rHK/strings.xml
+++ b/packages/PackageInstaller/res/values-zh-rHK/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"此使用者無法安裝來源不明的應用程式"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"此使用者無法安裝應用程式"</string>
     <string name="ok" msgid="7871959885003339302">"確定"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"仍要更新"</string>
     <string name="manage_applications" msgid="5400164782453975580">"管理應用程式"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"儲存空間不足"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"解除安裝更新"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"「<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g>」屬於以下應用程式:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"你要解除安裝此應用程式嗎?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"你要為"<b>"所有"</b>"使用者解除安裝這個應用程式嗎?應用程式及其資料會從裝置上的"<b>"所有"</b>"使用者設定檔中移除。"</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"你要為使用者<xliff:g id="USERNAME">%1$s</xliff:g>解除安裝此應用程式嗎?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"要從工作設定檔解除安裝此應用程式嗎?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"保留應用程式資料 (<xliff:g id="SIZE">%1$s</xliff:g>)。"</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"要刪除此應用程式嗎?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"要解除安裝此應用程式嗎?「<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>」複製本亦將被刪除。"</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"要從私人空間解除安裝此應用程式嗎?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"正在執行的解除安裝操作"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"失敗的解除安裝操作"</string>
     <string name="uninstalling" msgid="8709566347688966845">"正在解除安裝…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"管理使用者"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"無法解除安裝「<xliff:g id="APP_NAME">%1$s</xliff:g>」。"</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"剖析套件時發生問題。"</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Wear 不支援安裝/解除安裝操作。"</string>
     <string name="message_staging" msgid="8032722385658438567">"正在準備安裝應用程式…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"不明"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"為安全起見,你的平板電腦目前不得安裝此來源的不明應用程式。你可以在「設定」中變更這項設定。"</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"來源不明的應用程式可能會侵害你的平板電腦和個人資料。安裝此應用程式,即表示你同意承擔因使用這個應用程式而導致平板電腦損壞或資料遺失的責任。"</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"來源不明的應用程式可能會侵害你的電視和個人資料。安裝此應用程式,即表示你同意承擔因使用這個應用程式而導致電視損壞或資料遺失的責任。"</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"「<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>」複製本"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"繼續"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"設定"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"正在安裝/解除安裝 Wear 應用程式"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"要從「<xliff:g id="INSTALLERNAME">%1$s</xliff:g>」還原「<xliff:g id="APPNAME">%1$s</xliff:g>」嗎?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"此應用程式將開始在背景下載"</string>
     <string name="restore" msgid="8460854736328970444">"還原"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"你已離線"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"連接互聯網後,系統就會自動還原此應用程式"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"發生問題"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"嘗試還原此應用程式時發生問題"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"儲存空間不足"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"如要還原此應用程式,請騰出此裝置的儲存空間。需要的儲存空間大小:<xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"請即行動"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"按照後續步驟還原此應用程式"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"已停用 <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"如要還原此應用程式,請前往「設定」啟用 <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"已解除安裝 <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"如要還原此應用程式,你必須安裝 <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"繼續"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"清除儲存空間"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"設定"</string>
+    <string name="close" msgid="5214897374055647996">"關閉"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-zh-rTW/strings.xml b/packages/PackageInstaller/res/values-zh-rTW/strings.xml
index 873392b..30e66a0 100644
--- a/packages/PackageInstaller/res/values-zh-rTW/strings.xml
+++ b/packages/PackageInstaller/res/values-zh-rTW/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"這位使用者無法安裝不明的應用程式"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"這位使用者無法安裝應用程式"</string>
     <string name="ok" msgid="7871959885003339302">"確定"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"仍要更新"</string>
     <string name="manage_applications" msgid="5400164782453975580">"管理應用程式"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"空間不足"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"解除安裝更新"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"「<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g>」屬於下列應用程式:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"要解除安裝這個應用程式嗎?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"要為"<b>"所有"</b>"使用者解除安裝這個應用程式嗎?該應用程式及其資料會從裝置上的"<b>"所有"</b>"使用者設定檔移除。"</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"要為使用者 <xliff:g id="USERNAME">%1$s</xliff:g> 解除安裝這個應用程式嗎?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"要從工作資料夾解除安裝這個應用程式嗎?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"保留 <xliff:g id="SIZE">%1$s</xliff:g> 的應用程式資料。"</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"要刪除這個應用程式嗎?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"要解除安裝這個應用程式嗎?系統也會一併刪除「<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>」副本。"</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"想要從私人空間解除安裝這個應用程式嗎?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"執行中的解除安裝作業"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"失敗的解除安裝作業"</string>
     <string name="uninstalling" msgid="8709566347688966845">"解除安裝中…"</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"管理使用者"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"無法解除安裝「<xliff:g id="APP_NAME">%1$s</xliff:g>」。"</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"剖析套件時發生問題。"</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Wear 不支援安裝及解除安裝操作。"</string>
     <string name="message_staging" msgid="8032722385658438567">"正在準備應用程式安裝程序…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"不明"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"為了安全起見,你的平板電腦目前禁止安裝這個來源提供的不明應用程式。如要進行變更,請前往「設定」。"</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"來歷不明的應用程式可能會損害你的平板電腦和個人資料。如因安裝及使用這個應用程式,導致你的平板電腦受損或資料遺失,請自行負責。"</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"來歷不明的應用程式可能會損害你的電視和個人資料。如因安裝及使用這個應用程式,導致你的電視受損或資料遺失,請自行負責。"</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"「<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>」副本"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"繼續"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"設定"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"安裝/解除安裝中的 Wear 應用程式"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"要從「<xliff:g id="INSTALLERNAME">%1$s</xliff:g>」還原「<xliff:g id="APPNAME">%1$s</xliff:g>」嗎?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"系統將開始在背景下載這個應用程式"</string>
     <string name="restore" msgid="8460854736328970444">"還原"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"裝置目前離線"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"連上網際網路後,系統就會自動還原這個應用程式"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"發生錯誤"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"嘗試還原這個應用程式時發生問題"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"儲存空間不足"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"如要還原這個應用程式,請釋出這部裝置的儲存空間。需要的儲存空間大小:<xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"敬請採取行動"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"請按照後續步驟還原這個應用程式"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"「<xliff:g id="INSTALLERNAME">%1$s</xliff:g>」已停用"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"如要還原這個應用程式,請前往「設定」啟用「<xliff:g id="INSTALLERNAME">%1$s</xliff:g>」"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"「<xliff:g id="INSTALLERNAME">%1$s</xliff:g>」已解除安裝"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"如要還原這個應用程式,請安裝「<xliff:g id="INSTALLERNAME">%1$s</xliff:g>」"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"繼續"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"清除儲存空間"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"設定"</string>
+    <string name="close" msgid="5214897374055647996">"關閉"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values-zu/strings.xml b/packages/PackageInstaller/res/values-zu/strings.xml
index 8ff1e38..0bfc9b7 100644
--- a/packages/PackageInstaller/res/values-zu/strings.xml
+++ b/packages/PackageInstaller/res/values-zu/strings.xml
@@ -44,6 +44,8 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Izinhlelo zokusebenza ezingaziwa azikwazi ukufakwa ilo msebenzisi"</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Lo msebenzisi akavunyelwe ukufaka izinhlelo zokusebenza"</string>
     <string name="ok" msgid="7871959885003339302">"KULUNGILE"</string>
+    <!-- no translation found for archive (4447791830199354721) -->
+    <skip />
     <string name="update_anyway" msgid="8792432341346261969">"Buyekeza noma kunjalo"</string>
     <string name="manage_applications" msgid="5400164782453975580">"Phatha izinhlelo zokusebenza"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Iphelelwe yisikhala"</string>
@@ -58,6 +60,16 @@
     <string name="uninstall_update_title" msgid="824411791011583031">"Khipha isibuyekezo"</string>
     <string name="uninstall_activity_text" msgid="1928194674397770771">"I-<xliff:g id="ACTIVITY_NAME">%1$s</xliff:g> ingxenye yohlelo lokusebenza olulandelayo:"</string>
     <string name="uninstall_application_text" msgid="3816830743706143980">"Ufuna ukukhipha le app?"</string>
+    <!-- no translation found for archive_application_text (8482325710714386348) -->
+    <skip />
+    <!-- no translation found for archive_application_text_all_users (3151229641681672580) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_work_profile (1450487362134779752) -->
+    <skip />
+    <!-- no translation found for archive_application_text_user (2586558895535581451) -->
+    <skip />
+    <!-- no translation found for archive_application_text_current_user_private_profile (1958423158655599132) -->
+    <skip />
     <string name="uninstall_application_text_all_users" msgid="575491774380227119">"Ingabe ufuna ukukhipha lolu hlelo lokusebenza kubo "<b>"bonke"</b>" abasebenzisi? Uhlelo lokusebenza nedatha yalo kuzosuswa kubo "<b>"bonke"</b>" abasebenzisi kudivayisi."</string>
     <string name="uninstall_application_text_user" msgid="498072714173920526">"Ingabe ufuna ukukhiphela lolu hlelo lokusebenza kumsebenzisi ongu-<xliff:g id="USERNAME">%1$s</xliff:g>?"</string>
     <string name="uninstall_application_text_current_user_work_profile" msgid="8788387739022366193">"Ingabe ufuna ukukhipha le app kusukela kuphrofayela yakho yokusebenza?"</string>
@@ -66,6 +78,7 @@
     <string name="uninstall_keep_data" msgid="7002379587465487550">"Gcina u-<xliff:g id="SIZE">%1$s</xliff:g> wedatha yohlelo lokusebenza."</string>
     <string name="uninstall_application_text_current_user_clone_profile" msgid="835170400160011636">"Ingabe ufuna ukusula le app?"</string>
     <string name="uninstall_application_text_with_clone_instance" msgid="6944473334273349036">"Ufuna ukukhipha le app? I-clone ye-<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> nayo izosulwa."</string>
+    <string name="uninstall_application_text_current_user_private_profile" msgid="867004464945674674">"Ingabe ufuna ukukhipha le app endaweni yakho egodliwe?"</string>
     <string name="uninstalling_notification_channel" msgid="840153394325714653">"Ukukhishwa okuqhubekayo"</string>
     <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"Ukukhishwa okuhlulekile"</string>
     <string name="uninstalling" msgid="8709566347688966845">"Iyakhipha..."</string>
@@ -85,8 +98,6 @@
     <string name="manage_users" msgid="1243995386982560813">"Phatha abasebenzisi"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> ayikwazanga ukukhishwa"</string>
     <string name="Parse_error_dlg_text" msgid="1661404001063076789">"Kube nenkinga yokwehlukanisa iphakheji."</string>
-    <string name="wear_not_allowed_dlg_title" msgid="8664785993465117517">"I-Android Wear"</string>
-    <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Izenzo zokufaka/ukukhipha azisekelwe ku-Wear."</string>
     <string name="message_staging" msgid="8032722385658438567">"Ifaka kusiteji uhlelo lokusebenza…"</string>
     <string name="app_name_unknown" msgid="6881210203354323926">"Akwaziwa"</string>
     <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"Mayelana nokuphepha kwakho, ithebulethi yakho okwamanje ayivumelekanga ukufaka ama-app angaziwa avela kulo mthombo. Ungashintsha lokhu kumaSethingi."</string>
@@ -97,6 +108,8 @@
     <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Ithebulethi yakho nedatha yomuntu siqu zisengcupheni kakhulu ekuhlaselweni izinhlelo zokusebenza ezingaziwa. Ngokufaka lolu hlelo lokusebenza, uyavuma ukuthi unesibopho sanoma ikuphi ukonakala kuthebulethi yakho noma ukulahleka kwedatha okungabangelwa ukusetshenziswa kwayo."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Idatha yakho ye-TV neyomuntu siqu isengcupheni kakhulu ekuhlaselweni izinhlelo zokusebenza ezingaziwa. Ngokufaka lolu hlelo lokusebenza, uyavuma ukuthi unesibopho sanoma ikuphi ukonakala ku-TV yakho noma ukulahlekelwa kwedatha okungabangelwa ukusetshenziswa kwayo."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"I-Clone ye-<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for archiving_app_label (1127085259724124725) -->
+    <skip />
     <string name="anonymous_source_continue" msgid="4375745439457209366">"Qhubeka"</string>
     <string name="external_sources_settings" msgid="4046964413071713807">"Amasethingi"</string>
     <string name="wear_app_channel" msgid="1960809674709107850">"Ifaka/ikhipha izinhlelo zokusebenza ze-wear"</string>
@@ -106,4 +119,20 @@
     <string name="unarchive_application_title" msgid="7958278328280721421">"Buyisela i-<xliff:g id="APPNAME">%1$s</xliff:g> ukusuka ku-<xliff:g id="INSTALLERNAME">%1$s</xliff:g>?"</string>
     <string name="unarchive_body_text" msgid="8244155079861708964">"Le app izoqala ukudawuniloda ingemuva"</string>
     <string name="restore" msgid="8460854736328970444">"Buyisela"</string>
+    <string name="unarchive_error_offline_title" msgid="4021785324565678605">"Awuxhunyiwe ku-inthanethi"</string>
+    <string name="unarchive_error_offline_body" msgid="255717000519772755">"Le app izobuyiswa ngokuzenzakalelayo uma usuxhume ku-inthanethi"</string>
+    <string name="unarchive_error_generic_title" msgid="7123457671482449992">"Kukhona okungahambanga kahle"</string>
+    <string name="unarchive_error_generic_body" msgid="4486803312463813079">"Kube nenkinga ekuzameni ukubuyisa le app"</string>
+    <string name="unarchive_error_storage_title" msgid="5080723357273852630">"Indawo yokubeka ayanele"</string>
+    <string name="unarchive_error_storage_body" msgid="6879544407568780524">"Ukuze ubuyise le app, ungavula isikhala kule divayisi. Isitoreji esidingekayo: <xliff:g id="BYTES">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_title" msgid="4971245740162604619">"Kudingeka isenzo"</string>
+    <string name="unarchive_action_required_body" msgid="1679431572983989231">"Landela izinyathelo ezilandelayo ukuze ubuyise le app"</string>
+    <string name="unarchive_error_installer_disabled_title" msgid="4815715617014985605">"<xliff:g id="INSTALLERNAME">%1$s</xliff:g> ivimbelwe"</string>
+    <string name="unarchive_error_installer_disabled_body" msgid="4820821285907011729">"Ukuze ubuyise i-app, vula okuthi <xliff:g id="INSTALLERNAME">%1$s</xliff:g> kokuthi Amasethingi"</string>
+    <string name="unarchive_error_installer_uninstalled_title" msgid="3748354109176326489">"Okuthi <xliff:g id="INSTALLERNAME">%1$s</xliff:g> kukhishiwe"</string>
+    <string name="unarchive_error_installer_uninstalled_body" msgid="944733542444183204">"Ukuze ubuyise le app, kuzodingeka ufake okuthi <xliff:g id="INSTALLERNAME">%1$s</xliff:g>"</string>
+    <string name="unarchive_action_required_continue" msgid="5711202111224184257">"Qhubeka"</string>
+    <string name="unarchive_clear_storage_button" msgid="1549537154535608744">"Sula isitoreji"</string>
+    <string name="unarchive_settings_button" msgid="3504171760009177425">"Amasethingi"</string>
+    <string name="close" msgid="5214897374055647996">"Vala"</string>
 </resources>
diff --git a/packages/PackageInstaller/res/values/strings.xml b/packages/PackageInstaller/res/values/strings.xml
index 1c8a8d5..f4641b9 100644
--- a/packages/PackageInstaller/res/values/strings.xml
+++ b/packages/PackageInstaller/res/values/strings.xml
@@ -85,6 +85,8 @@
 
     <!-- [CHAR LIMIT=15] -->
     <string name="ok">OK</string>
+    <!-- Confirmation text label for button to archive an application. Archiving means uninstalling the app without deleting user's personal data and replacing the app with a stub app with minimum size. So, the user can unarchive the app later and not lose any personal data. -->
+    <string name="archive">Archive</string>
     <!-- [CHAR LIMIT=30] -->
     <string name="update_anyway">Update anyway</string>
     <!-- [CHAR LIMIT=15] -->
@@ -115,6 +117,16 @@
     <!--  [CHAR LIMIT=none] -->
     <string name="uninstall_application_text">Do you want to uninstall this app?</string>
     <!--  [CHAR LIMIT=none] -->
+    <string name="archive_application_text">Your personal data will be saved</string>
+    <!--  [CHAR LIMIT=none] -->
+    <string name="archive_application_text_all_users">Archive this app for all users? Your personal data will be saved</string>
+    <!--  [CHAR LIMIT=none] -->
+    <string name="archive_application_text_current_user_work_profile">Archive this app on your work profile? Your personal data will be saved</string>
+    <!--  [CHAR LIMIT=none] -->
+    <string name="archive_application_text_user">Archive this app for <xliff:g id="username">%1$s</xliff:g>? Your personal data will be saved</string>
+    <!--  [CHAR LIMIT=none] -->
+    <string name="archive_application_text_current_user_private_profile">Do you want to archive this app from your private space? Your personal data will be saved</string>
+    <!--  [CHAR LIMIT=none] -->
     <string name="uninstall_application_text_all_users">Do you want to uninstall this app for <b>all</b>
         users?  The application and its data will be removed from <b>all</b> users on the device.</string>
     <!--  [CHAR LIMIT=none] -->
@@ -190,11 +202,6 @@
     <!-- Dialog attributes to indicate parse errors -->
     <string name="Parse_error_dlg_text">There was a problem parsing the package.</string>
 
-    <!-- Title of dialog telling users that Install/Uninstall action is not supported on Android Wear. [CHAR LIMIT=30] -->
-    <string name="wear_not_allowed_dlg_title">Android Wear</string>
-    <!-- Title of dialog telling users that Install/Uninstall action is not supported on Android Wear. [CHAR LIMIT=none] -->
-    <string name="wear_not_allowed_dlg_text">Install/Uninstall actions not supported on Wear.</string>
-
     <!-- Message that the app to be installed is being staged [CHAR LIMIT=50] -->
     <string name="message_staging">Staging app&#8230;</string>
 
@@ -239,6 +246,8 @@
 
     <!-- Label for cloned app in uninstall dialogue [CHAR LIMIT=40] -->
     <string name="cloned_app_label"><xliff:g id="package_label">%1$s</xliff:g> Clone</string>
+    <!-- Label for archiving an app in uninstall dialogue -->
+    <string name="archiving_app_label">Archive <xliff:g id="package_label">%1$s</xliff:g>?</string>
 
     <!-- Label for button to continue install of an app whose source cannot be identified [CHAR LIMIT=40] -->
     <string name="anonymous_source_continue">Continue</string>
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java
index e889050..2da8c8c 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java
@@ -130,6 +130,9 @@
 
         final boolean isUpdate =
                 ((dialogInfo.appInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0);
+        final boolean isArchive =
+                android.content.pm.Flags.archiving() && (
+                        (dialogInfo.deleteFlags & PackageManager.DELETE_ARCHIVE) != 0);
         final UserHandle myUserHandle = Process.myUserHandle();
         UserManager userManager = getContext().getSystemService(UserManager.class);
         if (isUpdate) {
@@ -140,7 +143,9 @@
             }
         } else {
             if (dialogInfo.allUsers && !isSingleUser(userManager)) {
-                messageBuilder.append(getString(R.string.uninstall_application_text_all_users));
+                messageBuilder.append(
+                        isArchive ? getString(R.string.archive_application_text_all_users)
+                                : getString(R.string.uninstall_application_text_all_users));
             } else if (!dialogInfo.user.equals(myUserHandle)) {
                 int userId = dialogInfo.user.getIdentifier();
                 UserManager customUserManager = getContext()
@@ -150,9 +155,10 @@
 
                 if (customUserManager.isUserOfType(USER_TYPE_PROFILE_MANAGED)
                         && customUserManager.isSameProfileGroup(dialogInfo.user, myUserHandle)) {
-                    messageBuilder.append(
-                            getString(R.string.uninstall_application_text_current_user_work_profile,
-                                    userName));
+                    messageBuilder.append(isArchive
+                            ? getString(R.string.archive_application_text_current_user_work_profile)
+                            : getString(
+                                    R.string.uninstall_application_text_current_user_work_profile));
                 } else if (customUserManager.isUserOfType(USER_TYPE_PROFILE_CLONE)
                         && customUserManager.isSameProfileGroup(dialogInfo.user, myUserHandle)) {
                     mIsClonedApp = true;
@@ -161,9 +167,14 @@
                 } else if (Flags.allowPrivateProfile()
                         && customUserManager.isPrivateProfile()
                         && customUserManager.isSameProfileGroup(dialogInfo.user, myUserHandle)) {
-                    messageBuilder.append(getString(
-                            R.string.uninstall_application_text_current_user_private_profile,
-                            userName));
+                    messageBuilder.append(
+                            isArchive ? getString(
+                                    R.string.archive_application_text_current_user_private_profile)
+                            : getString(
+                                R.string.uninstall_application_text_current_user_private_profile));
+                } else if (isArchive) {
+                    messageBuilder.append(
+                            getString(R.string.archive_application_text_user, userName));
                 } else {
                     messageBuilder.append(
                             getString(R.string.uninstall_application_text_user, userName));
@@ -172,24 +183,27 @@
                 mIsClonedApp = true;
                 messageBuilder.append(getString(
                         R.string.uninstall_application_text_current_user_clone_profile));
+            } else if (Process.myUserHandle().equals(UserHandle.SYSTEM)
+                    && hasClonedInstance(dialogInfo.appInfo.packageName)) {
+                messageBuilder.append(getString(
+                        R.string.uninstall_application_text_with_clone_instance,
+                        appLabel));
+            } else if (isArchive) {
+                messageBuilder.append(getString(R.string.archive_application_text));
             } else {
-                if (Process.myUserHandle().equals(UserHandle.SYSTEM)
-                        && hasClonedInstance(dialogInfo.appInfo.packageName)) {
-                    messageBuilder.append(getString(
-                            R.string.uninstall_application_text_with_clone_instance,
-                            appLabel));
-                } else {
-                    messageBuilder.append(getString(R.string.uninstall_application_text));
-                }
+                messageBuilder.append(getString(R.string.uninstall_application_text));
             }
         }
 
         if (mIsClonedApp) {
             dialogBuilder.setTitle(getString(R.string.cloned_app_label, appLabel));
+        } else if (isArchive) {
+            dialogBuilder.setTitle(getString(R.string.archiving_app_label, appLabel));
         } else {
             dialogBuilder.setTitle(appLabel);
         }
-        dialogBuilder.setPositiveButton(android.R.string.ok, this);
+        dialogBuilder.setPositiveButton(isArchive ? R.string.archive : android.R.string.ok,
+                this);
         dialogBuilder.setNegativeButton(android.R.string.cancel, this);
 
         String pkg = dialogInfo.appInfo.packageName;
@@ -199,7 +213,7 @@
             PackageInfo pkgInfo = pm.getPackageInfo(pkg,
                     PackageManager.PackageInfoFlags.of(PackageManager.MATCH_ARCHIVED_PACKAGES));
 
-            suggestToKeepAppData = pkgInfo.applicationInfo.hasFragileUserData();
+            suggestToKeepAppData = pkgInfo.applicationInfo.hasFragileUserData() && !isArchive;
         } catch (PackageManager.NameNotFoundException e) {
             Log.e(LOG_TAG, "Cannot check hasFragileUserData for " + pkg, e);
             suggestToKeepAppData = false;
diff --git a/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java b/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java
index 96a11ee..5b39f4e 100644
--- a/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java
+++ b/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java
@@ -112,26 +112,6 @@
     }
 
     /**
-     * Shows restricted setting dialog.
-     */
-    @RequiresApi(Build.VERSION_CODES.TIRAMISU)
-    public static void sendShowRestrictedSettingDialogIntent(Context context,
-            String packageName, int uid) {
-        final Intent intent = getShowRestrictedSettingsIntent(packageName, uid);
-        context.startActivity(intent);
-    }
-
-    /**
-     * Gets restricted settings dialog intent.
-     */
-    private static Intent getShowRestrictedSettingsIntent(String packageName, int uid) {
-        final Intent intent = new Intent(Settings.ACTION_SHOW_RESTRICTED_SETTING_DIALOG);
-        intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
-        intent.putExtra(Intent.EXTRA_UID, uid);
-        return intent;
-    }
-
-    /**
      * Checks if current user is profile or not
      */
     @RequiresApi(Build.VERSION_CODES.M)
@@ -238,4 +218,35 @@
                     + '}';
         }
     }
+
+
+    /**
+     * Shows restricted setting dialog.
+     *
+     * @deprecated TODO(b/308921175): This will be deleted with the
+     * {@link android.security.Flags#extendEcmToAllSettings} feature flag. Do not use for any new
+     * code.
+     */
+    @Deprecated
+    @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+    public static void sendShowRestrictedSettingDialogIntent(Context context,
+                                                             String packageName, int uid) {
+        final Intent intent = getShowRestrictedSettingsIntent(packageName, uid);
+        context.startActivity(intent);
+    }
+
+    /**
+     * Gets restricted settings dialog intent.
+     *
+     * @deprecated TODO(b/308921175): This will be deleted with the
+     * {@link android.security.Flags#extendEcmToAllSettings} feature flag. Do not use for any new
+     * code.
+     */
+    @Deprecated
+    private static Intent getShowRestrictedSettingsIntent(String packageName, int uid) {
+        final Intent intent = new Intent(Settings.ACTION_SHOW_RESTRICTED_SETTING_DIALOG);
+        intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
+        intent.putExtra(Intent.EXTRA_UID, uid);
+        return intent;
+    }
 }
diff --git a/packages/SettingsLib/Spa/build.gradle.kts b/packages/SettingsLib/Spa/build.gradle.kts
index 60bf48c..8b136da 100644
--- a/packages/SettingsLib/Spa/build.gradle.kts
+++ b/packages/SettingsLib/Spa/build.gradle.kts
@@ -29,7 +29,7 @@
 
 allprojects {
     extra["androidTop"] = androidTop
-    extra["jetpackComposeVersion"] = "1.6.0-beta01"
+    extra["jetpackComposeVersion"] = "1.6.0-beta02"
 }
 
 subprojects {
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GallerySpaEnvironment.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GallerySpaEnvironment.kt
index 90c7d46..f4edb36 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GallerySpaEnvironment.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/GallerySpaEnvironment.kt
@@ -48,6 +48,7 @@
 import com.android.settingslib.spa.gallery.preference.SwitchPreferencePageProvider
 import com.android.settingslib.spa.gallery.preference.TwoTargetSwitchPreferencePageProvider
 import com.android.settingslib.spa.gallery.scaffold.SearchScaffoldPageProvider
+import com.android.settingslib.spa.gallery.scaffold.SuwScaffoldPageProvider
 import com.android.settingslib.spa.gallery.ui.CategoryPageProvider
 import com.android.settingslib.spa.gallery.ui.CopyablePageProvider
 import com.android.settingslib.spa.gallery.ui.SpinnerPageProvider
@@ -100,6 +101,7 @@
                 SettingsExposedDropdownMenuCheckBoxProvider,
                 SettingsTextFieldPasswordPageProvider,
                 SearchScaffoldPageProvider,
+                SuwScaffoldPageProvider,
                 CardPageProvider,
                 CopyablePageProvider,
             ),
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/card/CardPageProvider.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/card/CardPageProvider.kt
index f216abb..66bd6f5 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/card/CardPageProvider.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/card/CardPageProvider.kt
@@ -28,7 +28,14 @@
 import androidx.compose.material.icons.outlined.WarningAmber
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateListOf
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.tooling.preview.Preview
 import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
@@ -41,14 +48,14 @@
 import com.android.settingslib.spa.widget.card.CardButton
 import com.android.settingslib.spa.widget.card.CardModel
 import com.android.settingslib.spa.widget.card.SettingsCard
-import com.android.settingslib.spa.widget.card.SettingsCollapsibleCard
 import com.android.settingslib.spa.widget.card.SettingsCardContent
+import com.android.settingslib.spa.widget.card.SettingsCollapsibleCard
 import com.android.settingslib.spa.widget.preference.Preference
 import com.android.settingslib.spa.widget.preference.PreferenceModel
 import com.android.settingslib.spa.widget.scaffold.RegularScaffold
 
 object CardPageProvider : SettingsPageProvider {
-    override val name = "CardPage"
+    override val name = "Card"
 
     override fun getTitle(arguments: Bundle?) = TITLE
 
@@ -79,10 +86,13 @@
 
     @Composable
     private fun SettingsCardWithoutIcon() {
+        var isVisible by rememberSaveable { mutableStateOf(true) }
         SettingsCard(
             CardModel(
                 title = stringResource(R.string.sample_title),
                 text = stringResource(R.string.sample_text),
+                isVisible = { isVisible },
+                onDismiss = { isVisible = false },
                 buttons = listOf(
                     CardButton(text = "Action") {},
                 ),
@@ -92,21 +102,23 @@
 
     @Composable
     fun SampleSettingsCollapsibleCard() {
-        SettingsCollapsibleCard(
-            title = "More alerts",
-            imageVector = Icons.Outlined.Error,
-            models = listOf(
+        val context = LocalContext.current
+        var isVisible0 by rememberSaveable { mutableStateOf(true) }
+        val cards = remember {
+            mutableStateListOf(
                 CardModel(
-                    title = stringResource(R.string.sample_title),
-                    text = stringResource(R.string.sample_text),
+                    title = context.getString(R.string.sample_title),
+                    text = context.getString(R.string.sample_text),
                     imageVector = Icons.Outlined.PowerOff,
+                    isVisible = { isVisible0 },
+                    onDismiss = { isVisible0 = false },
                     buttons = listOf(
                         CardButton(text = "Action") {},
                     )
                 ),
                 CardModel(
-                    title = stringResource(R.string.sample_title),
-                    text = stringResource(R.string.sample_text),
+                    title = context.getString(R.string.sample_title),
+                    text = context.getString(R.string.sample_text),
                     imageVector = Icons.Outlined.Shield,
                     buttons = listOf(
                         CardButton(text = "Action") {},
@@ -114,6 +126,11 @@
                     )
                 )
             )
+        }
+        SettingsCollapsibleCard(
+            title = "More alerts",
+            imageVector = Icons.Outlined.Error,
+            models = cards.toList()
         )
     }
 
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePageProvider.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePageProvider.kt
index 1d897f7..6a2e598 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePageProvider.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePageProvider.kt
@@ -43,6 +43,7 @@
 import com.android.settingslib.spa.gallery.page.SliderPageProvider
 import com.android.settingslib.spa.gallery.preference.PreferenceMainPageProvider
 import com.android.settingslib.spa.gallery.scaffold.SearchScaffoldPageProvider
+import com.android.settingslib.spa.gallery.scaffold.SuwScaffoldPageProvider
 import com.android.settingslib.spa.gallery.ui.CategoryPageProvider
 import com.android.settingslib.spa.gallery.ui.CopyablePageProvider
 import com.android.settingslib.spa.gallery.ui.SpinnerPageProvider
@@ -59,6 +60,7 @@
             OperateListPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
             ArgumentPageProvider.buildInjectEntry("foo")!!.setLink(fromPage = owner).build(),
             SearchScaffoldPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
+            SuwScaffoldPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
             SliderPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
             SpinnerPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
             SettingsPagerPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/scaffold/SuwScaffoldPageProvider.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/scaffold/SuwScaffoldPageProvider.kt
new file mode 100644
index 0000000..6fc8de3
--- /dev/null
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/scaffold/SuwScaffoldPageProvider.kt
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.spa.gallery.scaffold
+
+import android.os.Bundle
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.outlined.SignalCellularAlt
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
+import com.android.settingslib.spa.framework.common.SettingsPageProvider
+import com.android.settingslib.spa.framework.common.createSettingsPage
+import com.android.settingslib.spa.framework.compose.navigator
+import com.android.settingslib.spa.framework.theme.SettingsDimension
+import com.android.settingslib.spa.gallery.R
+import com.android.settingslib.spa.widget.illustration.Illustration
+import com.android.settingslib.spa.widget.illustration.IllustrationModel
+import com.android.settingslib.spa.widget.illustration.ResourceType
+import com.android.settingslib.spa.widget.preference.Preference
+import com.android.settingslib.spa.widget.preference.PreferenceModel
+import com.android.settingslib.spa.widget.scaffold.BottomAppBarButton
+import com.android.settingslib.spa.widget.scaffold.SuwScaffold
+import com.android.settingslib.spa.widget.ui.SettingsBody
+
+private const val TITLE = "Sample SuwScaffold"
+
+object SuwScaffoldPageProvider : SettingsPageProvider {
+    override val name = "SuwScaffold"
+
+    private val owner = createSettingsPage()
+
+    fun buildInjectEntry() = SettingsEntryBuilder.createInject(owner = owner)
+        .setUiLayoutFn {
+            Preference(object : PreferenceModel {
+                override val title = TITLE
+                override val onClick = navigator(name)
+            })
+        }
+
+    @Composable
+    override fun Page(arguments: Bundle?) {
+        Page()
+    }
+}
+
+@Composable
+private fun Page() {
+    SuwScaffold(
+        imageVector = Icons.Outlined.SignalCellularAlt,
+        title = "Connect to mobile network",
+        actionButton = BottomAppBarButton("Next") {},
+        dismissButton = BottomAppBarButton("Cancel") {},
+    ) {
+        Column(Modifier.padding(SettingsDimension.itemPadding)) {
+            SettingsBody("To add another SIM, download a new eSIM.")
+        }
+        Illustration(object : IllustrationModel {
+            override val resId = R.drawable.accessibility_captioning_banner
+            override val resourceType = ResourceType.IMAGE
+        })
+        Column(Modifier.padding(SettingsDimension.itemPadding)) {
+            SettingsBody("To add another SIM, download a new eSIM.")
+        }
+        Illustration(object : IllustrationModel {
+            override val resId = R.drawable.accessibility_captioning_banner
+            override val resourceType = ResourceType.IMAGE
+        })
+    }
+}
diff --git a/packages/SettingsLib/Spa/spa/build.gradle.kts b/packages/SettingsLib/Spa/spa/build.gradle.kts
index acd90f3..7eccfe5 100644
--- a/packages/SettingsLib/Spa/spa/build.gradle.kts
+++ b/packages/SettingsLib/Spa/spa/build.gradle.kts
@@ -57,7 +57,7 @@
     api("androidx.slice:slice-builders:1.1.0-alpha02")
     api("androidx.slice:slice-core:1.1.0-alpha02")
     api("androidx.slice:slice-view:1.1.0-alpha02")
-    api("androidx.compose.material3:material3:1.2.0-alpha11")
+    api("androidx.compose.material3:material3:1.2.0-alpha12")
     api("androidx.compose.material:material-icons-extended:$jetpackComposeVersion")
     api("androidx.compose.runtime:runtime-livedata:$jetpackComposeVersion")
     api("androidx.compose.ui:ui-tooling-preview:$jetpackComposeVersion")
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 5a1120e..993cb4a 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
@@ -37,11 +37,14 @@
     val itemPaddingAround = 8.dp
     val itemDividerHeight = 32.dp
 
+    val iconSmall = 16.dp
+    val iconLarge = 48.dp
+
     /** The size when app icon is displayed in list. */
     val appIconItemSize = 32.dp
 
     /** The size when app icon is displayed in App info page. */
-    val appIconInfoSize = 48.dp
+    val appIconInfoSize = iconLarge
 
     /** The vertical padding for buttons. */
     val buttonPaddingVertical = 12.dp
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/card/CardModel.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/card/CardModel.kt
index c113f43..b18a1bc 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/card/CardModel.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/card/CardModel.kt
@@ -28,5 +28,14 @@
     val title: String,
     val text: String,
     val imageVector: ImageVector? = null,
+    val isVisible: () -> Boolean = { true },
+
+    /**
+     * A dismiss button will be displayed if this is not null.
+     *
+     * And this callback will be called when user clicks the button.
+     */
+    val onDismiss: (() -> Unit)? = null,
+
     val buttons: List<CardButton> = emptyList(),
 )
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/card/SettingsCard.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/card/SettingsCard.kt
index 4379278..7eec888 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/card/SettingsCard.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/card/SettingsCard.kt
@@ -16,28 +16,35 @@
 
 package com.android.settingslib.spa.widget.card
 
+import androidx.compose.animation.AnimatedVisibility
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.ColumnScope
 import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.shape.CircleShape
 import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.outlined.Close
 import androidx.compose.material.icons.outlined.WarningAmber
 import androidx.compose.material3.Button
 import androidx.compose.material3.ButtonDefaults
 import androidx.compose.material3.Card
 import androidx.compose.material3.CardDefaults
 import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.OutlinedButton
+import androidx.compose.material3.Surface
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.unit.dp
 import com.android.settingslib.spa.debug.UiModePreviews
 import com.android.settingslib.spa.framework.theme.SettingsDimension
@@ -87,20 +94,31 @@
 
 @Composable
 internal fun SettingsCardImpl(model: CardModel) {
-    SettingsCardContent {
-        Column(
-            modifier = Modifier.padding(SettingsDimension.itemPaddingStart),
-            verticalArrangement = Arrangement.spacedBy(SettingsDimension.itemPaddingAround)
-        ) {
-            CardIcon(model.imageVector)
-            SettingsTitle(model.title)
-            SettingsBody(model.text)
-            Buttons(model.buttons)
+    AnimatedVisibility(visible = model.isVisible()) {
+        SettingsCardContent {
+            Column(
+                modifier = Modifier.padding(SettingsDimension.itemPaddingStart),
+                verticalArrangement = Arrangement.spacedBy(SettingsDimension.itemPaddingAround)
+            ) {
+                CardHeader(model.imageVector, model.onDismiss)
+                SettingsTitle(model.title)
+                SettingsBody(model.text)
+                Buttons(model.buttons)
+            }
         }
     }
 }
 
 @Composable
+fun CardHeader(imageVector: ImageVector?, onDismiss: (() -> Unit)? = null) {
+    Row(Modifier.fillMaxWidth()) {
+        CardIcon(imageVector)
+        Spacer(modifier = Modifier.weight(1f))
+        DismissButton(onDismiss)
+    }
+}
+
+@Composable
 private fun CardIcon(imageVector: ImageVector?) {
     if (imageVector != null) {
         Icon(
@@ -113,6 +131,28 @@
 }
 
 @Composable
+private fun DismissButton(onDismiss: (() -> Unit)?) {
+    if (onDismiss == null) return
+    Surface(
+        shape = CircleShape,
+        color = MaterialTheme.colorScheme.secondaryContainer,
+    ) {
+        IconButton(
+            onClick = onDismiss,
+            modifier = Modifier.size(SettingsDimension.itemIconSize)
+        ) {
+            Icon(
+                imageVector = Icons.Outlined.Close,
+                contentDescription = stringResource(
+                    androidx.compose.material3.R.string.m3c_snackbar_dismiss
+                ),
+                modifier = Modifier.size(SettingsDimension.iconSmall),
+            )
+        }
+    }
+}
+
+@Composable
 private fun Buttons(buttons: List<CardButton>) {
     if (buttons.isNotEmpty()) {
         Row(
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/card/SettingsCollapsibleCard.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/card/SettingsCollapsibleCard.kt
index bf192a1..6e36490 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/card/SettingsCollapsibleCard.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/card/SettingsCollapsibleCard.kt
@@ -58,7 +58,7 @@
     var expanded by rememberSaveable { mutableStateOf(false) }
     SettingsCard {
         SettingsCardContent {
-            Header(title, imageVector, models.size, expanded) { expanded = it }
+            Header(title, imageVector, models.count { it.isVisible() }, expanded) { expanded = it }
         }
         AnimatedVisibility(expanded) {
             Column {
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/chart/BarChart.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/chart/BarChart.kt
index e761a33..caceb6f 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/chart/BarChart.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/chart/BarChart.kt
@@ -38,6 +38,8 @@
 import com.android.settingslib.spa.framework.theme.divider
 import com.github.mikephil.charting.charts.BarChart
 import com.github.mikephil.charting.components.XAxis
+import com.github.mikephil.charting.components.YAxis
+import com.github.mikephil.charting.components.YAxis.AxisDependency
 import com.github.mikephil.charting.data.BarData
 import com.github.mikephil.charting.data.BarDataSet
 import com.github.mikephil.charting.data.BarEntry
@@ -90,6 +92,10 @@
     /** If set to true, touch gestures are enabled on the [BarChart]. */
     val enableBarchartTouch: Boolean
         get() = true
+
+    /** The renderer provider for x-axis. */
+    val xAxisRendererProvider: XAxisRendererProvider?
+        get() = null
 }
 
 data class BarChartData(
@@ -143,6 +149,16 @@
                                 yOffset = 10f
                             }
 
+                            barChartModel.xAxisRendererProvider?.let {
+                                setXAxisRenderer(
+                                    it.provideXAxisRenderer(
+                                        getViewPortHandler(),
+                                        getXAxis(),
+                                        getTransformer(YAxis.AxisDependency.LEFT)
+                                    )
+                                )
+                            }
+
                             axisLeft.apply {
                                 axisMaximum = barChartModel.yAxisMaxValue
                                 axisMinimum = barChartModel.yAxisMinValue
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/chart/XAxisRendererProvider.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/chart/XAxisRendererProvider.kt
new file mode 100644
index 0000000..6569d25
--- /dev/null
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/chart/XAxisRendererProvider.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.spa.widget.chart
+
+import com.github.mikephil.charting.components.XAxis
+import com.github.mikephil.charting.renderer.XAxisRenderer
+import com.github.mikephil.charting.utils.Transformer
+import com.github.mikephil.charting.utils.ViewPortHandler
+
+/** A provider for [XAxisRenderer] objects. */
+fun interface XAxisRendererProvider {
+
+  /** Provides an object of [XAxisRenderer] type. */
+  fun provideXAxisRenderer(
+    viewPortHandler: ViewPortHandler,
+    xAxis: XAxis,
+    transformer: Transformer
+  ): XAxisRenderer
+}
\ No newline at end of file
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/editor/SettingsOutlinedTextField.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/editor/SettingsOutlinedTextField.kt
index 3819a10..e0dd4e1 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/editor/SettingsOutlinedTextField.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/editor/SettingsOutlinedTextField.kt
@@ -34,6 +34,7 @@
 fun SettingsOutlinedTextField(
     value: String,
     label: String,
+    errorMessage: String? = null,
     singleLine: Boolean = true,
     enabled: Boolean = true,
     onTextChange: (String) -> Unit,
@@ -49,6 +50,12 @@
         },
         singleLine = singleLine,
         enabled = enabled,
+        isError = errorMessage != null,
+        supportingText = {
+            if (errorMessage != null) {
+                Text(text = errorMessage)
+            }
+        }
     )
 }
 
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SuwScaffold.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SuwScaffold.kt
new file mode 100644
index 0000000..354b95d
--- /dev/null
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SuwScaffold.kt
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.spa.widget.scaffold
+
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.BoxWithConstraints
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.ColumnScope
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.material3.Button
+import androidx.compose.material3.Icon
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.Text
+import androidx.compose.material3.TextButton
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.vector.ImageVector
+import com.android.settingslib.spa.framework.theme.SettingsDimension
+import com.android.settingslib.spa.framework.theme.toMediumWeight
+
+data class BottomAppBarButton(
+    val text: String,
+    val onClick: () -> Unit,
+)
+
+@Composable
+fun SuwScaffold(
+    imageVector: ImageVector,
+    title: String,
+    actionButton: BottomAppBarButton? = null,
+    dismissButton: BottomAppBarButton? = null,
+    content: @Composable ColumnScope.() -> Unit,
+) {
+    ActivityTitle(title)
+    Scaffold { innerPadding ->
+        BoxWithConstraints(
+            Modifier
+                .padding(innerPadding)
+                .padding(top = SettingsDimension.itemPaddingAround)
+        ) {
+            // Use single column layout in portrait, two columns in landscape.
+            val useSingleColumn = maxWidth < maxHeight
+            if (useSingleColumn) {
+                Column {
+                    Column(
+                        Modifier
+                            .weight(1f)
+                            .verticalScroll(rememberScrollState())
+                    ) {
+                        Header(imageVector, title)
+                        content()
+                    }
+                    BottomBar(actionButton, dismissButton)
+                }
+            } else {
+                Column(Modifier.padding(horizontal = SettingsDimension.itemPaddingAround)) {
+                    Row((Modifier.weight(1f))) {
+                        Box(Modifier.weight(1f)) {
+                            Header(imageVector, title)
+                        }
+                        Column(
+                            Modifier
+                                .weight(1f)
+                                .verticalScroll(rememberScrollState())) {
+                            content()
+                        }
+                    }
+                    BottomBar(actionButton, dismissButton)
+                }
+            }
+        }
+    }
+}
+
+@Composable
+private fun Header(
+    imageVector: ImageVector,
+    title: String
+) {
+    Column(Modifier.padding(SettingsDimension.itemPadding)) {
+        Icon(
+            imageVector = imageVector,
+            contentDescription = null,
+            modifier = Modifier
+                .padding(vertical = SettingsDimension.itemPaddingAround)
+                .size(SettingsDimension.iconLarge),
+            tint = MaterialTheme.colorScheme.primary,
+        )
+        Text(
+            text = title,
+            modifier = Modifier.padding(vertical = SettingsDimension.itemPaddingVertical),
+            color = MaterialTheme.colorScheme.onSurface,
+            style = MaterialTheme.typography.displaySmall,
+        )
+    }
+}
+
+@Composable
+private fun BottomBar(
+    actionButton: BottomAppBarButton?,
+    dismissButton: BottomAppBarButton?,
+) {
+    Row(modifier = Modifier.padding(SettingsDimension.itemPaddingAround)) {
+        dismissButton?.apply {
+            TextButton(onClick) {
+                ActionText(text)
+            }
+        }
+        Spacer(modifier = Modifier.weight(1f))
+        actionButton?.apply {
+            Button(onClick) {
+                ActionText(text)
+            }
+        }
+    }
+}
+
+@Composable
+private fun ActionText(text: String) {
+    Text(
+        text = text,
+        style = MaterialTheme.typography.bodyMedium.toMediumWeight(),
+    )
+}
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/card/SettingsCardTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/card/SettingsCardTest.kt
index fd3ae49..beb9433 100644
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/card/SettingsCardTest.kt
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/card/SettingsCardTest.kt
@@ -16,10 +16,18 @@
 
 package com.android.settingslib.spa.widget.card
 
+import android.content.Context
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
 import androidx.compose.ui.test.assertIsDisplayed
+import androidx.compose.ui.test.isNotDisplayed
 import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithContentDescription
 import androidx.compose.ui.test.onNodeWithText
 import androidx.compose.ui.test.performClick
+import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
@@ -31,6 +39,8 @@
     @get:Rule
     val composeTestRule = createComposeRule()
 
+    private val context: Context = ApplicationProvider.getApplicationContext()
+
     @Test
     fun settingsCard_titleDisplayed() {
         composeTestRule.setContent {
@@ -96,6 +106,27 @@
         assertThat(buttonClicked).isTrue()
     }
 
+    @Test
+    fun settingsCard_dismiss() {
+        composeTestRule.setContent {
+            var isVisible by remember { mutableStateOf(true) }
+            SettingsCard(
+                CardModel(
+                    title = TITLE,
+                    text = "",
+                    isVisible = { isVisible },
+                    onDismiss = { isVisible = false },
+                )
+            )
+        }
+
+        composeTestRule.onNodeWithContentDescription(
+            context.getString(androidx.compose.material3.R.string.m3c_snackbar_dismiss)
+        ).performClick()
+
+        composeTestRule.onNodeWithText(TEXT).isNotDisplayed()
+    }
+
     private companion object {
         const val TITLE = "Title"
         const val TEXT = "Text"
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/card/SettingsCollapsibleCardTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/card/SettingsCollapsibleCardTest.kt
index efe1c70..aba9d7b 100644
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/card/SettingsCollapsibleCardTest.kt
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/card/SettingsCollapsibleCardTest.kt
@@ -16,12 +16,20 @@
 
 package com.android.settingslib.spa.widget.card
 
+import android.content.Context
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.outlined.Error
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
 import androidx.compose.ui.test.assertIsDisplayed
+import androidx.compose.ui.test.isNotDisplayed
 import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithContentDescription
 import androidx.compose.ui.test.onNodeWithText
 import androidx.compose.ui.test.performClick
+import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import org.junit.Rule
 import org.junit.Test
@@ -32,6 +40,8 @@
     @get:Rule
     val composeTestRule = createComposeRule()
 
+    private val context: Context = ApplicationProvider.getApplicationContext()
+
     @Test
     fun settingsCollapsibleCard_titleDisplayed() {
         setContent()
@@ -62,8 +72,22 @@
         composeTestRule.onNodeWithText(CARD_TEXT).assertIsDisplayed()
     }
 
+    @Test
+    fun settingsCollapsibleCard_dismiss() {
+        setContent()
+        composeTestRule.onNodeWithText(TITLE).performClick()
+
+        composeTestRule.onNodeWithContentDescription(
+            context.getString(androidx.compose.material3.R.string.m3c_snackbar_dismiss)
+        ).performClick()
+
+        composeTestRule.onNodeWithText(CARD_TEXT).isNotDisplayed()
+        composeTestRule.onNodeWithText("0").assertIsDisplayed()
+    }
+
     private fun setContent() {
         composeTestRule.setContent {
+            var isVisible by rememberSaveable { mutableStateOf(true) }
             SettingsCollapsibleCard(
                 title = TITLE,
                 imageVector = Icons.Outlined.Error,
@@ -71,6 +95,8 @@
                     CardModel(
                         title = "",
                         text = CARD_TEXT,
+                        isVisible = { isVisible },
+                        onDismiss = { isVisible = false },
                     )
                 ),
             )
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/scaffold/SuwScaffoldTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/scaffold/SuwScaffoldTest.kt
new file mode 100644
index 0000000..35c9f78
--- /dev/null
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/scaffold/SuwScaffoldTest.kt
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.spa.widget.scaffold
+
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.outlined.SignalCellularAlt
+import androidx.compose.material3.Text
+import androidx.compose.ui.test.assertIsDisplayed
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithText
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class SuwScaffoldTest {
+    @get:Rule
+    val composeTestRule = createComposeRule()
+
+    @Test
+    fun suwScaffold_titleIsDisplayed() {
+        composeTestRule.setContent {
+            SuwScaffold(imageVector = Icons.Outlined.SignalCellularAlt, title = TITLE) {
+                Text(text = "AAA")
+                Text(text = "BBB")
+            }
+        }
+
+        composeTestRule.onNodeWithText(TITLE).assertIsDisplayed()
+    }
+
+    @Test
+    fun suwScaffold_itemsAreDisplayed() {
+        composeTestRule.setContent {
+            SuwScaffold(imageVector = Icons.Outlined.SignalCellularAlt, title = TITLE) {
+                Text(text = "AAA")
+                Text(text = "BBB")
+            }
+        }
+
+        composeTestRule.onNodeWithText("AAA").assertIsDisplayed()
+        composeTestRule.onNodeWithText("BBB").assertIsDisplayed()
+    }
+
+    @Test
+    fun suwScaffold_actionButtonDisplayed() {
+        composeTestRule.setContent {
+            SuwScaffold(
+                imageVector = Icons.Outlined.SignalCellularAlt,
+                title = TITLE,
+                actionButton = BottomAppBarButton(TEXT) {},
+            ) {}
+        }
+
+        composeTestRule.onNodeWithText(TEXT).assertIsDisplayed()
+    }
+
+    @Test
+    fun suwScaffold_dismissButtonDisplayed() {
+        composeTestRule.setContent {
+            SuwScaffold(
+                imageVector = Icons.Outlined.SignalCellularAlt,
+                title = TITLE,
+                dismissButton = BottomAppBarButton(TEXT) {},
+            ) {}
+        }
+
+        composeTestRule.onNodeWithText(TEXT).assertIsDisplayed()
+    }
+
+    private companion object {
+        const val TITLE = "Title"
+        const val TEXT = "Text"
+    }
+}
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/common/BroadcastReceiverFlow.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/common/BroadcastReceiverFlow.kt
index d0d2dc0..e099f11 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/common/BroadcastReceiverFlow.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/framework/common/BroadcastReceiverFlow.kt
@@ -20,13 +20,17 @@
 import android.content.Context
 import android.content.Intent
 import android.content.IntentFilter
+import android.util.Log
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.callbackFlow
+import kotlinx.coroutines.flow.catch
 import kotlinx.coroutines.flow.conflate
 import kotlinx.coroutines.flow.flowOn
 
+private const val TAG = "BroadcastReceiverFlow"
+
 /**
  * A [BroadcastReceiver] flow for the given [intentFilter].
  */
@@ -39,4 +43,6 @@
     registerReceiver(broadcastReceiver, intentFilter, Context.RECEIVER_NOT_EXPORTED)
 
     awaitClose { unregisterReceiver(broadcastReceiver) }
+}.catch { e ->
+    Log.e(TAG, "Error while broadcastReceiverFlow", e)
 }.conflate().flowOn(Dispatchers.Default)
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/enterprise/RestrictedMode.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/enterprise/RestrictedMode.kt
index 3acc9ad..b6d9242 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/enterprise/RestrictedMode.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/enterprise/RestrictedMode.kt
@@ -18,6 +18,7 @@
 
 import android.app.admin.DevicePolicyResources.Strings.Settings
 import android.content.Context
+import android.content.Intent
 import com.android.settingslib.RestrictedLockUtils
 import com.android.settingslib.widget.restricted.R
 
@@ -32,6 +33,11 @@
     fun sendShowAdminSupportDetailsIntent()
 }
 
+interface BlockedByEcm : RestrictedMode {
+    fun showRestrictedSettingsDetails()
+}
+
+
 internal data class BlockedByAdminImpl(
     private val context: Context,
     private val enforcedAdmin: RestrictedLockUtils.EnforcedAdmin,
@@ -55,3 +61,13 @@
         RestrictedLockUtils.sendShowAdminSupportDetailsIntent(context, enforcedAdmin)
     }
 }
+
+internal data class BlockedByEcmImpl(
+    private val context: Context,
+    private val intent: Intent,
+) : BlockedByEcm {
+
+    override fun showRestrictedSettingsDetails() {
+        context.startActivity(intent)
+    }
+}
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/enterprise/RestrictionsProvider.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/enterprise/RestrictionsProvider.kt
index 550966b..9432d59 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/enterprise/RestrictionsProvider.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/enterprise/RestrictionsProvider.kt
@@ -29,10 +29,20 @@
 import kotlinx.coroutines.flow.flow
 import kotlinx.coroutines.flow.flowOn
 
+data class EnhancedConfirmation(
+    val key: String,
+    val uid: Int,
+    val packageName: String,
+)
 data class Restrictions(
     val userId: Int = UserHandle.myUserId(),
     val keys: List<String>,
-)
+    val enhancedConfirmation: EnhancedConfirmation? = null,
+) {
+    fun isEmpty(): Boolean {
+        return keys.isEmpty() && enhancedConfirmation == null
+    }
+}
 
 interface RestrictionsProvider {
     @Composable
@@ -77,6 +87,14 @@
                 .checkIfRestrictionEnforced(context, key, restrictions.userId)
                 ?.let { return BlockedByAdminImpl(context = context, enforcedAdmin = it) }
         }
+
+        restrictions.enhancedConfirmation?.let { ec ->
+            RestrictedLockUtilsInternal
+                    .checkIfRequiresEnhancedConfirmation(context, ec.key,
+                        ec.uid, ec.packageName)
+                    ?.let { intent -> return BlockedByEcmImpl(context = context, intent = intent) }
+        }
+
         return NoRestricted
     }
 }
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppList.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppList.kt
index 06b3eab..25c3bc5 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppList.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppList.kt
@@ -47,6 +47,9 @@
     abstract val appOp: Int
     abstract val permission: String
 
+    override val enhancedConfirmationKey: String?
+        get() = AppOpsManager.opToPublicName(appOp)
+
     /**
      * When set, specifies the broader permission who trumps the [permission].
      *
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt
index 5655436..1c830c1 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt
@@ -41,6 +41,7 @@
 import com.android.settingslib.spaprivileged.model.app.IPackageManagers
 import com.android.settingslib.spaprivileged.model.app.PackageManagers
 import com.android.settingslib.spaprivileged.model.app.toRoute
+import com.android.settingslib.spaprivileged.model.enterprise.EnhancedConfirmation
 import com.android.settingslib.spaprivileged.model.enterprise.Restrictions
 import com.android.settingslib.spaprivileged.model.enterprise.RestrictionsProviderFactory
 import com.android.settingslib.spaprivileged.model.enterprise.RestrictionsProviderImpl
@@ -154,7 +155,12 @@
             override val changeable = { isChangeable }
             override val onCheckedChange: (Boolean) -> Unit = { setAllowed(record, it) }
         }
-        val restrictions = Restrictions(userId, switchRestrictionKeys)
+        val restrictions = Restrictions(userId = userId,
+            keys = switchRestrictionKeys,
+            enhancedConfirmation = enhancedConfirmationKey?.let { EnhancedConfirmation(
+                key = it,
+                uid = checkNotNull(applicationInfo).uid,
+                packageName = packageName) })
         RestrictedSwitchPreference(switchModel, restrictions, restrictionsProviderFactory)
     }
 }
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppList.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppList.kt
index 8704f20..916d83a 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppList.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppList.kt
@@ -36,6 +36,9 @@
     val switchRestrictionKeys: List<String>
         get() = emptyList()
 
+    val enhancedConfirmationKey: String?
+        get() = null
+
     /**
      * Loads the extra info for the App List, and generates the [AppRecord] List.
      *
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt
index 36c91f4..4b47437 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt
@@ -41,6 +41,7 @@
 import com.android.settingslib.spaprivileged.model.app.AppListModel
 import com.android.settingslib.spaprivileged.model.app.AppRecord
 import com.android.settingslib.spaprivileged.model.app.userId
+import com.android.settingslib.spaprivileged.model.enterprise.EnhancedConfirmation
 import com.android.settingslib.spaprivileged.model.enterprise.Restrictions
 import com.android.settingslib.spaprivileged.model.enterprise.RestrictionsProviderFactory
 import com.android.settingslib.spaprivileged.model.enterprise.RestrictionsProviderImpl
@@ -149,11 +150,17 @@
 
     @Composable
     fun getSummary(record: T): () -> String {
-        val restrictions = remember(record.app.userId) {
+        val restrictions = remember(record.app.userId,
+                record.app.uid, record.app.packageName) {
             Restrictions(
                 userId = record.app.userId,
                 keys = listModel.switchRestrictionKeys,
-            )
+                enhancedConfirmation = listModel.enhancedConfirmationKey?.let {
+                    EnhancedConfirmation(
+                        key = it,
+                        uid = record.app.uid,
+                        packageName = record.app.packageName)
+                })
         }
         val restrictedMode by restrictionsProviderFactory.rememberRestrictedMode(restrictions)
         val allowed = listModel.isAllowed(record)
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreference.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreference.kt
index d5c5574..cd72025 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreference.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreference.kt
@@ -40,7 +40,7 @@
     restrictions: Restrictions,
     restrictionsProviderFactory: RestrictionsProviderFactory,
 ) {
-    if (restrictions.keys.isEmpty()) {
+    if (restrictions.isEmpty()) {
         SwitchPreference(model)
         return
     }
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreferenceModel.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreferenceModel.kt
index fa44ecb..aba3460 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreferenceModel.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreferenceModel.kt
@@ -31,6 +31,7 @@
 import com.android.settingslib.spaprivileged.framework.compose.getPlaceholder
 import com.android.settingslib.spaprivileged.model.enterprise.BaseUserRestricted
 import com.android.settingslib.spaprivileged.model.enterprise.BlockedByAdmin
+import com.android.settingslib.spaprivileged.model.enterprise.BlockedByEcm
 import com.android.settingslib.spaprivileged.model.enterprise.NoRestricted
 import com.android.settingslib.spaprivileged.model.enterprise.RestrictedMode
 import com.android.settingslib.spaprivileged.model.enterprise.Restrictions
@@ -56,6 +57,7 @@
         is NoRestricted -> model.checked
         is BaseUserRestricted -> ({ false })
         is BlockedByAdmin -> model.checked
+        is BlockedByEcm -> model.checked
     }
 
     override val changeable = if (restrictedMode is NoRestricted) model.changeable else ({ false })
@@ -68,24 +70,42 @@
         is BaseUserRestricted -> model.onCheckedChange
         // Pass null since semantics ToggleableState is provided in RestrictionWrapper.
         is BlockedByAdmin -> null
+        is BlockedByEcm -> null
     }
 
     @Composable
     fun RestrictionWrapper(content: @Composable () -> Unit) {
-        if (restrictedMode !is BlockedByAdmin) {
-            content()
-            return
+        when (restrictedMode) {
+            is BlockedByAdmin -> {
+                Box(
+                    Modifier
+                            .clickable(
+                                role = Role.Switch,
+                                onClick = { restrictedMode.sendShowAdminSupportDetailsIntent() },
+                            )
+                            .semantics {
+                                this.toggleableState = ToggleableState(checked())
+                            },
+                ) { content() }
+            }
+
+            is BlockedByEcm -> {
+                Box(
+                    Modifier
+                            .clickable(
+                                role = Role.Switch,
+                                onClick = { restrictedMode.showRestrictedSettingsDetails() },
+                            )
+                            .semantics {
+                                this.toggleableState = ToggleableState(checked())
+                            },
+                ) { content() }
+            }
+
+            else -> {
+                content()
+            }
         }
-        Box(
-            Modifier
-                .clickable(
-                    role = Role.Switch,
-                    onClick = { restrictedMode.sendShowAdminSupportDetailsIntent() },
-                )
-                .semantics {
-                    this.toggleableState = ToggleableState(checked())
-                },
-        ) { content() }
     }
 
     private fun ToggleableState(value: Boolean?) = when (value) {
@@ -123,6 +143,9 @@
                     context.getString(com.android.settingslib.R.string.disabled)
 
                 is BlockedByAdmin -> restrictedMode.getSummary(checked())
+                is BlockedByEcm ->
+                    context.getString(com.android.settingslib.R.string.disabled)
+
                 null -> context.getPlaceholder()
             }
         }
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/scaffold/RestrictedMenuItem.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/scaffold/RestrictedMenuItem.kt
index f9abefc..977615b 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/scaffold/RestrictedMenuItem.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/scaffold/RestrictedMenuItem.kt
@@ -21,6 +21,7 @@
 import com.android.settingslib.spa.widget.scaffold.MoreOptionsScope
 import com.android.settingslib.spaprivileged.model.enterprise.BaseUserRestricted
 import com.android.settingslib.spaprivileged.model.enterprise.BlockedByAdmin
+import com.android.settingslib.spaprivileged.model.enterprise.BlockedByEcm
 import com.android.settingslib.spaprivileged.model.enterprise.Restrictions
 import com.android.settingslib.spaprivileged.model.enterprise.RestrictionsProviderFactory
 import com.android.settingslib.spaprivileged.model.enterprise.RestrictionsProviderImpl
@@ -47,6 +48,7 @@
     MenuItem(text = text, enabled = restrictedMode !== BaseUserRestricted) {
         when (restrictedMode) {
             is BlockedByAdmin -> restrictedMode.sendShowAdminSupportDetailsIntent()
+            is BlockedByEcm -> restrictedMode.showRestrictedSettingsDetails()
             else -> onClick()
         }
     }
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/framework/common/BroadcastReceiverFlowTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/framework/common/BroadcastReceiverFlowTest.kt
index dfaf3c6..eef5225 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/framework/common/BroadcastReceiverFlowTest.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/framework/common/BroadcastReceiverFlowTest.kt
@@ -31,8 +31,10 @@
 import org.junit.runner.RunWith
 import org.mockito.kotlin.any
 import org.mockito.kotlin.doAnswer
+import org.mockito.kotlin.doThrow
 import org.mockito.kotlin.eq
 import org.mockito.kotlin.mock
+import org.mockito.kotlin.stub
 
 @RunWith(AndroidJUnit4::class)
 class BroadcastReceiverFlowTest {
@@ -74,6 +76,18 @@
         assertThat(onReceiveIsCalled).isTrue()
     }
 
+    @Test
+    fun broadcastReceiverFlow_unregisterReceiverThrowException_noCrash() = runBlocking {
+        context.stub {
+            on { unregisterReceiver(any()) } doThrow IllegalArgumentException()
+        }
+        val flow = context.broadcastReceiverFlow(INTENT_FILTER)
+
+        flow.firstWithTimeoutOrNull()
+
+        assertThat(registeredBroadcastReceiver).isNotNull()
+    }
+
     private companion object {
         val INTENT_FILTER = IntentFilter()
     }
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 3a25838..9ae4d0c 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Gekoppel deur ARC"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Gekoppel deur eARC"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"TV-verstek"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI-uitset"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Interne luidsprekers"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Kan nie koppel nie. Skakel toestel af en weer aan"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Bedrade oudiotoestel"</string>
     <string name="help_label" msgid="3528360748637781274">"Hulp en terugvoer"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 6dd70fa..6c31c76 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"‏متّصل من خلال ARC"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"‏متّصل من خلال eARC"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"الجهاز التلقائي لإخراج صوت التلفزيون"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"‏إخراج الصوت من خلال HDMI"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"مكبّرات الصوت الداخلية"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"حدثت مشكلة أثناء الاتصال. يُرجى إيقاف الجهاز ثم إعادة تشغيله."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"جهاز سماعي سلكي"</string>
     <string name="help_label" msgid="3528360748637781274">"المساعدة والملاحظات"</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index c8eeee3..8b06f5d 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"ARCৰ জৰিয়তে সংযুক্ত"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"eARCৰ জৰিয়তে সংযুক্ত"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"টিভি ডিফ’ল্ট"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI আউটপুট"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"অভ্যন্তৰীণ স্পীকাৰ"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"সংযোগ হোৱাত সমস্যা হৈছে। ডিভাইচটো অফ কৰি পুনৰ অন কৰক"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"তাঁৰযুক্ত অডিঅ’ ডিভাইচ"</string>
     <string name="help_label" msgid="3528360748637781274">"সহায় আৰু মতামত"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 34f506e..a36ab27 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Chrome-da Tətbiqin İşləmə Müddəti vasitəsilə qoşulub"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"eARC vasitəsilə qoşulub"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"TV defoltu"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI çıxışı"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Daxili dinamiklər"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Qoşulmaqla bağlı problem. Cihazı deaktiv edin, sonra yenidən aktiv edin"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Simli audio cihaz"</string>
     <string name="help_label" msgid="3528360748637781274">"Yardım və rəy"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index ee75df2..83f7c05 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Povezano preko ARC-a"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Povezano preko eARC-a"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"Podrazumevana vrednost za TV"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI izlaz"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Unutrašnji zvučnici"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem pri povezivanju. Isključite uređaj, pa ga ponovo uključite"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Žičani audio uređaj"</string>
     <string name="help_label" msgid="3528360748637781274">"Pomoć i povratne informacije"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index c17d7236..7e8cd8b 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Падключана праз ARC"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Падключана праз eARC"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"Стандартны аўдыявыхад тэлевізара"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"Выхад HDMI"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Унутраныя дынамікі"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Праблема з падключэннем. Выключыце і зноў уключыце прыладу"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Правадная аўдыяпрылада"</string>
     <string name="help_label" msgid="3528360748637781274">"Даведка і водгукі"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 222e758..d279349 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Свързано посредством ARC"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Свързано посредством eARC"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"Стандартното за телевизора"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI изход"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Вградени високоговорители"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"При свързването възникна проблем. Изключете устройството и го включете отново"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Аудиоустройство с кабел"</string>
     <string name="help_label" msgid="3528360748637781274">"Помощ и отзиви"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index a7c95df..3ac3a3b 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"ARC-এর মাধ্যমে কানেক্ট করা হয়েছে"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"eARC-এর মাধ্যমে কানেক্ট করা হয়েছে"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"টিভির ডিফল্ট সেটিং"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI আউটপুট"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"ইন্টার্নাল স্পিকার"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"কানেক্ট করতে সমস্যা হচ্ছে। ডিভাইস বন্ধ করে আবার চালু করুন"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ওয়্যার অডিও ডিভাইস"</string>
     <string name="help_label" msgid="3528360748637781274">"সহায়তা ও মতামত"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 31ea4d4..f84ccb0 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Povezano je putem ARC-a"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Povezano je putem eARC-a"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"Zadano za TV"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI izlaz"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Interni zvučnici"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Došlo je do problema prilikom povezivanja. Isključite, pa ponovo uključite uređaj"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Žičani audio uređaj"</string>
     <string name="help_label" msgid="3528360748637781274">"Pomoć i povratne informacije"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 1bb02c2..c205f74 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Connectat mitjançant ARC"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Connectat mitjançant eARC"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"Televisor predeterminat"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"Sortida HDMI"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Altaveus interns"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Hi ha hagut un problema amb la connexió. Apaga el dispositiu i torna\'l a encendre."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositiu d\'àudio amb cable"</string>
     <string name="help_label" msgid="3528360748637781274">"Ajuda i suggeriments"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 7ab6669..2a6a247 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Forbundet via ARC"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Forbundet via eARC"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"Standardindstillinger for fjernsyn"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI-udgang"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Interne højttalere"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Der kunne ikke oprettes forbindelse. Sluk og tænd enheden"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Lydenhed med ledning"</string>
     <string name="help_label" msgid="3528360748637781274">"Hjælp og feedback"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 29038bc..a5f089a 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Connected via ARC"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Connected via eARC"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"TV default"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI output"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Internal speakers"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem connecting. Turn device off and back on"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Wired audio device"</string>
     <string name="help_label" msgid="3528360748637781274">"Help and feedback"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 29038bc..a5f089a 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Connected via ARC"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Connected via eARC"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"TV default"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI output"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Internal speakers"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem connecting. Turn device off and back on"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Wired audio device"</string>
     <string name="help_label" msgid="3528360748637781274">"Help and feedback"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 29038bc..a5f089a 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Connected via ARC"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Connected via eARC"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"TV default"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI output"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Internal speakers"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem connecting. Turn device off and back on"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Wired audio device"</string>
     <string name="help_label" msgid="3528360748637781274">"Help and feedback"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 82cd2bf..c07e1fd 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Conectado mediante ARC"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Conectado mediante eARC"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"Predeterminada de la televisión"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"Salida HDMI"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Altavoces internos"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"No se ha podido conectar; reinicia el dispositivo"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de audio con cable"</string>
     <string name="help_label" msgid="3528360748637781274">"Ayuda y comentarios"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 35ae73e..ddc16b0 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Ühendatud ARC-i kaudu"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Ühendatud eARC-i kaudu"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"Teleri vaikeväljund"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI-väljund"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Sisemised kõlarid"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Probleem ühendamisel. Lülitage seade välja ja uuesti sisse"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Juhtmega heliseade"</string>
     <string name="help_label" msgid="3528360748637781274">"Abi ja tagasiside"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 7ebad68..364ba54 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -352,7 +352,7 @@
     <string name="wait_for_debugger_summary" msgid="6846330006113363286">"Araztutako aplikazioak araztailea erantsi arte itxaroten du exekutatu aurretik"</string>
     <string name="debug_input_category" msgid="7349460906970849771">"Sarrera"</string>
     <string name="debug_drawing_category" msgid="5066171112313666619">"Marrazketa"</string>
-    <string name="debug_hw_drawing_category" msgid="5830815169336975162">"Hardware bidez bizkortutako errendatzea"</string>
+    <string name="debug_hw_drawing_category" msgid="5830815169336975162">"Hardware bidez azeleratutako errendatzea"</string>
     <string name="media_category" msgid="8122076702526144053">"Multimedia-edukia"</string>
     <string name="debug_monitoring_category" msgid="1597387133765424994">"Kontrola"</string>
     <string name="strict_mode" msgid="889864762140862437">"Modu zorrotza gaituta"</string>
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"ARC bidez konektatuta"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"eARC bidez konektatuta"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"Telebistaren audio-erreproduzigailu lehenetsia"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI irteera"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Barneko bozgorailuak"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Arazo bat izan da konektatzean. Itzali gailua eta pitz ezazu berriro."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Audio-gailu kableduna"</string>
     <string name="help_label" msgid="3528360748637781274">"Laguntza eta iritziak"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 51fd626..d73571e 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"‏متصل ازطریق ARC"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"‏متصل ازطریق eARC"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"پیش‌فرض تلویزیون"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"‏خروجی HDMI"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"بلندگوهای داخلی"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"مشکل در اتصال. دستگاه را خاموش و دوباره روشن کنید"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"دستگاه صوتی سیمی"</string>
     <string name="help_label" msgid="3528360748637781274">"راهنما و بازخورد"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index f8c9054..3533d77 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Yhdistetty ARC:n kautta"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Yhdistetty eARC:n kautta"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"TV:n oletusasetus"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI-toisto"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Sisäiset kaiuttimet"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Yhteysvirhe. Sammuta laite ja käynnistä se uudelleen."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Langallinen äänilaite"</string>
     <string name="help_label" msgid="3528360748637781274">"Ohje ja palaute"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 2a7266d..06eeae0 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Connecté par ARC"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Connecté par eARC"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"Sortie audio par défaut de la télévision"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"Sortie HDMI"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Haut-parleurs internes"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problème de connexion. Éteingez et rallumez l\'appareil"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Appareil audio à câble"</string>
     <string name="help_label" msgid="3528360748637781274">"Aide et commentaires"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 7b79386..f896d16 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Conectado mediante ARC"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Conectado mediante eARC"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"Opción predeterminada da televisión"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"Saída HDMI"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Altofalantes internos"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Produciuse un problema coa conexión. Apaga e acende o dispositivo."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de audio con cable"</string>
     <string name="help_label" msgid="3528360748637781274">"Axuda e comentarios"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index ec534da..50741dd 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"ARC મારફતે કનેક્ટેડ"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"eARC મારફતે કનેક્ટેડ"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"ડિવાઇસનું ડિફૉલ્ટ ઑડિયો આઉટપુટ, ટીવી"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI આઉટપુટ"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"આંતરિક સ્પીકર"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"કનેક્ટ કરવામાં સમસ્યા આવી રહી છે. ડિવાઇસને બંધ કરીને ફરી ચાલુ કરો"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"વાયરવાળો ઑડિયો ડિવાઇસ"</string>
     <string name="help_label" msgid="3528360748637781274">"સહાય અને પ્રતિસાદ"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 092c729..0a29b6a 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"एचडीएमआई eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"ARC से कनेक्ट किए गए डिवाइस"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"eARC से कनेक्ट किए गए डिवाइस"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"टीवी की डिफ़ॉल्ट सेटिंग"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"एचडीएमआई आउटपुट"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"इंटरनल स्पीकर"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"कनेक्ट करने में समस्या हो रही है. डिवाइस को बंद करके चालू करें"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"वायर वाला ऑडियो डिवाइस"</string>
     <string name="help_label" msgid="3528360748637781274">"सहायता और सुझाव"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index eaebfc9..b206ac0 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Povezano putem ARC-a"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Povezano putem eARC-a"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"Zadano za TV"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI izlaz"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Unutarnji zvučnici"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem s povezivanjem. Isključite i ponovo uključite uređaj"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Žičani audiouređaj"</string>
     <string name="help_label" msgid="3528360748637781274">"Pomoć i povratne informacije"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index d287ce3..68ff9ae 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Csatlakoztatva ARC-n keresztül"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Csatlakoztatva eARC-n keresztül"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"Tévé alapértelmezett eszköze"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI-kimenet"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Belső hangszórók"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Sikertelen csatlakozás. Kapcsolja ki az eszközt, majd kapcsolja be újra."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Vezetékes audioeszköz"</string>
     <string name="help_label" msgid="3528360748637781274">"Súgó és visszajelzés"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 4d27099..f3061a7 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Միացված է ARC-ի միջոցով"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Միացված է eARC-ի միջոցով"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"Հեռուստացույցի կանխադրված կարգավորումներ"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI ելք"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Ներքին բարձրախոսներ"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Կապի խնդիր կա: Սարքն անջատեք և նորից միացրեք:"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Լարով աուդիո սարք"</string>
     <string name="help_label" msgid="3528360748637781274">"Օգնություն և հետադարձ կապ"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index ce770af..2c16603 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Terhubung melalui ARC"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Terhubung melalui eARC"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"TV sebagai default"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"Output HDMI"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Speaker internal"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ada masalah saat menghubungkan. Nonaktifkan perangkat &amp; aktifkan kembali"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Perangkat audio berkabel"</string>
     <string name="help_label" msgid="3528360748637781274">"Bantuan &amp; masukan"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index fd68d14..98b2bd3 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -527,7 +527,7 @@
     <string name="next" msgid="2699398661093607009">"Avanti"</string>
     <string name="back" msgid="5554327870352703710">"Indietro"</string>
     <string name="save" msgid="3745809743277153149">"Salva"</string>
-    <string name="okay" msgid="949938843324579502">"OK"</string>
+    <string name="okay" msgid="949938843324579502">"Ok"</string>
     <string name="done" msgid="381184316122520313">"Fine"</string>
     <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Sveglie e promemoria"</string>
     <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Consenti l\'impostazione di sveglie e promemoria"</string>
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"eARC HDMI"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Connessione tramite ARC"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Connessione tramite eARC"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"TV predefinita"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"Uscita HDMI"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Speaker interni"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problema di connessione. Spegni e riaccendi il dispositivo"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo audio cablato"</string>
     <string name="help_label" msgid="3528360748637781274">"Guida e feedback"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 58d4f0e..5d57843 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"ARC 経由で接続済み"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"eARC 経由で接続済み"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"テレビのデフォルト"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI 出力"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"内蔵スピーカー"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"接続エラーです。デバイスを OFF にしてから ON に戻してください"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"有線オーディオ デバイス"</string>
     <string name="help_label" msgid="3528360748637781274">"ヘルプとフィードバック"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 0d31dde..a8fb9aa 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"ARC арқылы жалғанған."</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"eARC арқылы жалғанған."</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"Теледидардың әдепкі шығысы"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI шығыс интерфейсі"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Ішкі динамиктер"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Байланыс орнату қатесі шығуып жатыр. Құрылғыны өшіріп, қайта қосыңыз."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Сымды аудио құрылғысы"</string>
     <string name="help_label" msgid="3528360748637781274">"Анықтама және пікір"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 8ee7987..16f14ff 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"បានភ្ជាប់តាមរយៈ ARC"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"បានភ្ជាប់តាមរយៈ eARC"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"លំនាំដើម​ទូរទស្សន៍"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"ធាតុចេញ HDMI"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"ឧបករណ៍បំពងសំឡេងខាងក្នុង"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"មាន​បញ្ហា​ក្នុងការ​ភ្ជាប់។ បិទ រួច​បើក​ឧបករណ៍​វិញ"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ឧបករណ៍​សំឡេងប្រើខ្សែ"</string>
     <string name="help_label" msgid="3528360748637781274">"ជំនួយ និងមតិកែលម្អ"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 73f7a20..640d4e9 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"ARC ಮೂಲಕ ಕನೆಕ್ಟ್ ಮಾಡಲಾಗಿದೆ"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"eARC ಮೂಲಕ ಕನೆಕ್ಟ್ ಮಾಡಲಾಗಿದೆ"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"ಟಿವಿ ಡೀಫಾಲ್ಟ್"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI ಔಟ್‌‌ಪುಟ್"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"ಆಂತರಿಕ ಸ್ಪೀಕರ್‌ಗಳು"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ಕನೆಕ್ಟ್ ಮಾಡುವಾಗ ಸಮಸ್ಯೆ ಎದುರಾಗಿದೆ ಸಾಧನವನ್ನು ಆಫ್ ಮಾಡಿ ಹಾಗೂ ನಂತರ ಪುನಃ ಆನ್ ಮಾಡಿ"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ವೈರ್ ಹೊಂದಿರುವ ಆಡಿಯೋ ಸಾಧನ"</string>
     <string name="help_label" msgid="3528360748637781274">"ಸಹಾಯ ಮತ್ತು ಪ್ರತಿಕ್ರಿಯೆ"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 418e47e..1bf0a51 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"ARC를 통해 연결됨"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"eARC를 통해 연결됨"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"TV 기본값"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI 출력"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"내부 스피커"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"연결 중에 문제가 발생했습니다. 기기를 껐다가 다시 켜 보세요."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"유선 오디오 기기"</string>
     <string name="help_label" msgid="3528360748637781274">"고객센터"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 182e912..9565fb0 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"ARC аркылуу туташты"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"eARC аркылуу туташты"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"Cыналгыдагы демейки түзмөк"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI аудио түзмөгү"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Ички динамиктер"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Туташууда маселе келип чыкты. Түзмөктү өчүрүп, кайра күйгүзүп көрүңүз"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Зымдуу аудио түзмөк"</string>
     <string name="help_label" msgid="3528360748637781274">"Жардам/Пикир билдирүү"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 5f8ba5f..23f249a0d 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"ເຊື່ອມຕໍ່ຜ່ານ ARC ແລ້ວ"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"ເຊື່ອມຕໍ່ຜ່ານ eARC ແລ້ວ"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"ຄ່າເລີ່ມຕົ້ນສຳລັບໂທລະທັດ"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"ເອົ້າພຸດ HDMI"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"ລຳໂພງຂອງເຄື່ອງ"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ເກີດບັນຫາໃນການເຊື່ອມຕໍ່. ປິດອຸປະກອນແລ້ວເປີດກັບຄືນມາໃໝ່"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ອຸປະກອນສຽງແບບມີສາຍ"</string>
     <string name="help_label" msgid="3528360748637781274">"ຊ່ວຍເຫຼືອ ແລະ ຕິຊົມ"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 5294f4a..f529ca4 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI „eARC“"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Prisijungta per ARC"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Prisijungta per „eARC“"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"TV numatytoji išvestis"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI išvestis"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Vidiniai garsiakalbiai"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Prisijungiant kilo problema. Išjunkite įrenginį ir vėl jį įjunkite"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Laidinis garso įrenginys"</string>
     <string name="help_label" msgid="3528360748637781274">"Pagalba ir atsiliepimai"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 7ea01e7..24be0aa 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Savienojums izveidots, izmantojot ARC"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Savienojums izveidots, izmantojot eARC"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"Noklusējuma iestatījums televizorā"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI izvade"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Iekšējie skaļruņi"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Radās problēma ar savienojuma izveidi. Izslēdziet un atkal ieslēdziet ierīci."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Vadu audioierīce"</string>
     <string name="help_label" msgid="3528360748637781274">"Palīdzība un atsauksmes"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index d38f42c..030a438 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Поврзано преку ARC"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Поврзано преку eARC"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"Стандарден излез на телевизор"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"Излез за HDMI"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Внатрешни звучници"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Проблем со поврзување. Исклучете го уредот и повторно вклучете го"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Жичен аудиоуред"</string>
     <string name="help_label" msgid="3528360748637781274">"Помош и повратни информации"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 8b6150d..9a01b53 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"ARC വഴി കണക്റ്റ് ചെയ്തിരിക്കുന്നു"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"eARC വഴി കണക്റ്റ് ചെയ്തിരിക്കുന്നു"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"ടിവി ഡിഫോൾട്ട്"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI ഔട്ട്പുട്ട്"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"ആന്തരിക സ്‌പീക്കറുകൾ"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"കണക്‌റ്റ് ചെയ്യുന്നതിൽ പ്രശ്‌നമുണ്ടായി. ഉപകരണം ഓഫാക്കി വീണ്ടും ഓണാക്കുക"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"വയർ മുഖേന ബന്ധിപ്പിച്ച ഓഡിയോ ഉപകരണം"</string>
     <string name="help_label" msgid="3528360748637781274">"സഹായവും ഫീഡ്‌ബാക്കും"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index e7c83a8..03fecc4 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"ARC-р холбогдсон"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"eARC-р холбогдсон"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"ТВ-ийн өгөгдмөл"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI гаралт"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Дотоод чанга яригч"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Холбогдоход асуудал гарлаа. Төхөөрөмжийг унтраагаад дахин асаана уу"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Утастай аудио төхөөрөмж"</string>
     <string name="help_label" msgid="3528360748637781274">"Тусламж, санал хүсэлт"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 381d0b8..e4edf08 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"ARC द्वारे कनेक्ट केलेली"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"eARC द्वारे कनेक्ट केलेली"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"टीव्ही डीफॉल्ट"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI आउटपुट"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"अंतर्गत स्पीकर"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"कनेक्‍ट करण्‍यात समस्‍या आली. डिव्हाइस बंद करा आणि नंतर सुरू करा"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"वायर असलेले ऑडिओ डिव्हाइस"</string>
     <string name="help_label" msgid="3528360748637781274">"मदत आणि फीडबॅक"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 3e7d901..88f13f6f 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Disambungkan melalui ARC"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Disambungkan melalui eARC"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"Tetapan lalai TV"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"Output HDMI"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Pembesar suara dalaman"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Masalah penyambungan. Matikan &amp; hidupkan kembali peranti"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Peranti audio berwayar"</string>
     <string name="help_label" msgid="3528360748637781274">"Bantuan &amp; maklum balas"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 68ae549..58e2cf4 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"ARC မှတစ်ဆင့် ချိတ်ဆက်ထားသည်"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"eARC မှတစ်ဆင့် ချိတ်ဆက်ထားသည်"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"TV မူရင်း"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI အထွက်"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"စက်ရှိ စပီကာများ"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ချိတ်ဆက်ရာတွင် ပြဿနာရှိပါသည်။ စက်ကိုပိတ်ပြီး ပြန်ဖွင့်ပါ"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ကြိုးတပ် အသံစက်ပစ္စည်း"</string>
     <string name="help_label" msgid="3528360748637781274">"အကူအညီနှင့် အကြံပြုချက်"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index a11bfff..a5bfe5e 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Tilkoblet via ARC"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Tilkoblet via eARC"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"TV-ens standardinnstilling"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI-utgang"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Interne høyttalere"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Tilkoblingsproblemer. Slå enheten av og på igjen"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Lydenhet med kabel"</string>
     <string name="help_label" msgid="3528360748637781274">"Hjelp og tilbakemelding"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index b833c14..d8e1152 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"ARC मार्फत कनेक्ट गरिएका"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"eARC मार्फत कनेक्ट गरिएका"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"टिभीको डिफल्ट अडियो आउटपुट"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI आउटपुट"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"आन्तरिक स्पिकरहरू"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"जोड्ने क्रममा समस्या भयो। यन्त्रलाई निष्क्रिय पारेर फेरि अन गर्नुहोस्"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"तारयुक्त अडियो यन्त्र"</string>
     <string name="help_label" msgid="3528360748637781274">"मद्दत र प्रतिक्रिया"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index f9215e5..a65ff730 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Verbonden via ARC"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Verbonden via eARC"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"Tv-standaard"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI-uitvoer"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Interne speakers"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Probleem bij verbinding maken. Zet het apparaat uit en weer aan."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Bedraad audioapparaat"</string>
     <string name="help_label" msgid="3528360748637781274">"Hulp en feedback"</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index c4ed005..add9ff7 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"ARC ମାଧ୍ୟମରେ କନେକ୍ଟ କରାଯାଇଛି"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"eARC ମାଧ୍ୟମରେ କନେକ୍ଟ କରାଯାଇଛି"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"ଟିଭିର ଡିଫଲ୍ଟ ଅଡିଓ ଆଉଟପୁଟ"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI ଆଉଟପୁଟ"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"ଇଣ୍ଟର୍ନଲ ସ୍ପିକର"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ସଂଯୋଗ କରିବାରେ ସମସ୍ୟା ହେଉଛି। ଡିଭାଇସ୍ ବନ୍ଦ କରି ପୁଣି ଚାଲୁ କରନ୍ତୁ"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ତାରଯୁକ୍ତ ଅଡିଓ ଡିଭାଇସ୍"</string>
     <string name="help_label" msgid="3528360748637781274">"ସାହାଯ୍ୟ ଓ ମତାମତ"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index b7a67fd..42d47f6 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -528,7 +528,7 @@
     <string name="back" msgid="5554327870352703710">"ਪਿੱਛੇ ਜਾਓ"</string>
     <string name="save" msgid="3745809743277153149">"ਰੱਖਿਅਤ ਕਰੋ"</string>
     <string name="okay" msgid="949938843324579502">"ਠੀਕ ਹੈ"</string>
-    <string name="done" msgid="381184316122520313">"ਹੋ ਗਿਆ"</string>
+    <string name="done" msgid="381184316122520313">"ਸਮਝ ਲਿਆ"</string>
     <string name="alarms_and_reminders_label" msgid="6918395649731424294">"ਅਲਾਰਮ ਅਤੇ ਰਿਮਾਈਂਡਰ"</string>
     <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"ਅਲਾਰਮ ਅਤੇ ਰਿਮਾਈਂਡਰ ਸੈੱਟ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿਓ"</string>
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"ਅਲਾਰਮ ਅਤੇ ਰਿਮਾਈਂਡਰ"</string>
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"ARC ਰਾਹੀਂ ਕਨੈਕਟ ਕੀਤੇ ਗਏ ਡੀਵਾਈਸ"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"eARC ਰਾਹੀਂ ਕਨੈਕਟ ਕੀਤੇ ਗਏ ਡੀਵਾਈਸ"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"ਟੀਵੀ ਦਾ ਪੂਰਵ-ਨਿਰਧਾਰਿਤ ਆਊਟਪੁੱਟ"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI ਆਊਟਪੁੱਟ"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"ਅੰਦਰੂਨੀ ਸਪੀਕਰ"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ਕਨੈਕਟ ਕਰਨ ਵਿੱਚ ਸਮੱਸਿਆ ਆਈ। ਡੀਵਾਈਸ ਨੂੰ ਬੰਦ ਕਰਕੇ ਵਾਪਸ ਚਾਲੂ ਕਰੋ"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ਤਾਰ ਵਾਲਾ ਆਡੀਓ ਡੀਵਾਈਸ"</string>
     <string name="help_label" msgid="3528360748637781274">"ਮਦਦ ਅਤੇ ਵਿਚਾਰ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 3ef8fd7e..b319cab 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Połączono przez ARC"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Połączono przez eARC"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"Ustawienie domyślne telewizora"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"Wyjście HDMI"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Głośniki wewnętrzne"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem z połączeniem. Wyłącz i ponownie włącz urządzenie"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Przewodowe urządzenie audio"</string>
     <string name="help_label" msgid="3528360748637781274">"Pomoc i opinie"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index b76b37b..32fa1b6 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -237,8 +237,8 @@
     <string name="adb_wireless_error" msgid="721958772149779856">"Erro"</string>
     <string name="adb_wireless_settings" msgid="2295017847215680229">"Depuração por Wi-Fi"</string>
     <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Para acessar e usar dispositivos disponíveis, ative a depuração por Wi-Fi."</string>
-    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Parear o dispositivo com um código QR"</string>
-    <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"Parear novos dispositivos usando um leitor de código QR"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Parear o dispositivo com um QR code"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"Parear novos dispositivos usando um leitor de QR code"</string>
     <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Parear o dispositivo com um código de pareamento"</string>
     <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Parear novos dispositivos usando um código de seis dígitos"</string>
     <string name="adb_paired_devices_title" msgid="5268997341526217362">"Dispositivos pareados"</string>
@@ -252,12 +252,12 @@
     <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Código de pareamento por Wi‑Fi"</string>
     <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Falha no pareamento"</string>
     <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Verifique se o dispositivo está conectado à mesma rede."</string>
-    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Parear dispositivo na rede Wi‑Fi fazendo a leitura do código QR"</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Parear dispositivo na rede Wi‑Fi fazendo a leitura do QR code"</string>
     <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Pareando dispositivo…"</string>
-    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Falha ao parear o dispositivo. O código QR está incorreto ou o dispositivo não está conectado à mesma rede."</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Falha ao parear o dispositivo. O QR code está incorreto ou o dispositivo não está conectado à mesma rede."</string>
     <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Endereço IP e porta"</string>
-    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Ler código QR"</string>
-    <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"Parear dispositivo na rede Wi‑Fi fazendo a leitura do código QR"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Ler QR code"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"Parear dispositivo na rede Wi‑Fi fazendo a leitura do QR code"</string>
     <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Conecte-se a uma rede Wi-Fi"</string>
     <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Atalho para relatório de bugs"</string>
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Conectado via ARC"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Conectado via eARC"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"Padrão da TV"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"Saída HDMI"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Alto-falantes internos"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ocorreu um problema na conexão. Desligue o dispositivo e ligue-o novamente"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de áudio com fio"</string>
     <string name="help_label" msgid="3528360748637781274">"Ajuda e feedback"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index b76b37b..32fa1b6 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -237,8 +237,8 @@
     <string name="adb_wireless_error" msgid="721958772149779856">"Erro"</string>
     <string name="adb_wireless_settings" msgid="2295017847215680229">"Depuração por Wi-Fi"</string>
     <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Para acessar e usar dispositivos disponíveis, ative a depuração por Wi-Fi."</string>
-    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Parear o dispositivo com um código QR"</string>
-    <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"Parear novos dispositivos usando um leitor de código QR"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Parear o dispositivo com um QR code"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"Parear novos dispositivos usando um leitor de QR code"</string>
     <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Parear o dispositivo com um código de pareamento"</string>
     <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Parear novos dispositivos usando um código de seis dígitos"</string>
     <string name="adb_paired_devices_title" msgid="5268997341526217362">"Dispositivos pareados"</string>
@@ -252,12 +252,12 @@
     <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Código de pareamento por Wi‑Fi"</string>
     <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Falha no pareamento"</string>
     <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Verifique se o dispositivo está conectado à mesma rede."</string>
-    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Parear dispositivo na rede Wi‑Fi fazendo a leitura do código QR"</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Parear dispositivo na rede Wi‑Fi fazendo a leitura do QR code"</string>
     <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Pareando dispositivo…"</string>
-    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Falha ao parear o dispositivo. O código QR está incorreto ou o dispositivo não está conectado à mesma rede."</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Falha ao parear o dispositivo. O QR code está incorreto ou o dispositivo não está conectado à mesma rede."</string>
     <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Endereço IP e porta"</string>
-    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Ler código QR"</string>
-    <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"Parear dispositivo na rede Wi‑Fi fazendo a leitura do código QR"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Ler QR code"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"Parear dispositivo na rede Wi‑Fi fazendo a leitura do QR code"</string>
     <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Conecte-se a uma rede Wi-Fi"</string>
     <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Atalho para relatório de bugs"</string>
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Conectado via ARC"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Conectado via eARC"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"Padrão da TV"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"Saída HDMI"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Alto-falantes internos"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ocorreu um problema na conexão. Desligue o dispositivo e ligue-o novamente"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de áudio com fio"</string>
     <string name="help_label" msgid="3528360748637781274">"Ajuda e feedback"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 862e3d4..fe65be5 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Подключено через ARC"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Подключено через eARC"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"Стандартный выход на телевизоре"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"Выход HDMI"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Внутренние динамики"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ошибка подключения. Выключите и снова включите устройство."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Проводное аудиоустройство"</string>
     <string name="help_label" msgid="3528360748637781274">"Справка/отзыв"</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 795abec..55e0778 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"ARC හරහා සම්බන්ධ කර ඇත"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"eARC හරහා සම්බන්ධ කර ඇත"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"රූපවාහිනී පෙරනිමිය"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI ප්‍රතිදානය"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"අභ්‍යන්තර ස්පීකර්"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"සම්බන්ධ කිරීමේ ගැටලුවකි උපාංගය ක්‍රියාවිරහිත කර &amp; ආපසු ක්‍රියාත්මක කරන්න"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"රැහැන්ගත කළ ඕඩියෝ උපාංගය"</string>
     <string name="help_label" msgid="3528360748637781274">"උදවු &amp; ප්‍රතිපෝෂණ"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 00c0bc1..4d03ddd 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Pripojené prostredníctvom rozhrania ARC"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Pripojené prostredníctvom rozhrania eARC"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"Predvolené nastavenie televízora"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"Výstup HDMI"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Interné reproduktory"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Pri pripájaní sa vyskytol problém. Zariadenie vypnite a znova zapnite."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Audio zariadenie s káblom"</string>
     <string name="help_label" msgid="3528360748637781274">"Pomocník a spätná väzba"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index f204017..b627d09 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Lidhur përmes ARC-së"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Lidhur përmes eARC-së"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"Parazgjedhja e televizorit"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"Dalja HDMI"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Altoparlantët e brendshëm"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem me lidhjen. Fike dhe ndize përsëri pajisjen"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Pajisja audio me tel"</string>
     <string name="help_label" msgid="3528360748637781274">"Ndihma dhe komentet"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index b83986a..224be52 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Повезано преко ARC-а"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Повезано преко eARC-а"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"Подразумевана вредност за ТВ"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI излаз"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Унутрашњи звучници"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Проблем при повезивању. Искључите уређај, па га поново укључите"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Жичани аудио уређај"</string>
     <string name="help_label" msgid="3528360748637781274">"Помоћ и повратне информације"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 58e3705..7ffad7c 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Ansluten via ARC"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Ansluten via eARC"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"Standardutgång för tv:n"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI-utgång"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Interna högtalare"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Det gick inte att ansluta. Stäng av enheten och slå på den igen"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Ljudenhet med kabelanslutning"</string>
     <string name="help_label" msgid="3528360748637781274">"Hjälp och feedback"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 5870cde..1cdb69c 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -513,7 +513,7 @@
     <string name="active_input_method_subtypes" msgid="4232680535471633046">"Mbinu zinazotumika"</string>
     <string name="use_system_language_to_select_input_method_subtypes" msgid="4865195835541387040">"Tumia lugha za mfumo"</string>
     <string name="failed_to_open_app_settings_toast" msgid="764897252657692092">"Imeshindwa kufungua mipangilio ya <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
-    <string name="ime_security_warning" msgid="6547562217880551450">"Huenda mbinu hii ya kuingiza ikakusanya maandishi yote unayoandika, pamoja na data ya kibinafsi kama vile manenosiri na nambari za kadi za mkopo. Inatoka kwa programu <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Je, ungependa kutumia mbinu hii ya kingiza?"</string>
+    <string name="ime_security_warning" msgid="6547562217880551450">"Huenda mbinu hii ya kuingiza ikakusanya maandishi yote unayoandika, pamoja na data ya kibinafsi kama vile manenosiri na namba za kadi za mkopo. Inatoka kwa programu <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Je, ungependa kutumia mbinu hii ya kingiza?"</string>
     <string name="direct_boot_unaware_dialog_message" msgid="7845398276735021548">"Kumbuka: Baada ya kuwasha tena programu hii, hutaweza kuitumia hadi utakapofungua simu yako"</string>
     <string name="ims_reg_title" msgid="8197592958123671062">"Hali ya usajili wa IMS"</string>
     <string name="ims_reg_status_registered" msgid="884916398194885457">"Imesajiliwa"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 2a2536b..b76f7e3 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"ARC மூலம் இணைக்கப்பட்டுள்ளவை"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"eARC மூலம் இணைக்கப்பட்டுள்ளவை"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"டிவி இயல்புநிலை"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI அவுட்புட்"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"உட்புற ஸ்பீக்கர்கள்"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"இணைப்பதில் சிக்கல். சாதனத்தை ஆஃப் செய்து மீண்டும் ஆன் செய்யவும்"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"வயருடன்கூடிய ஆடியோ சாதனம்"</string>
     <string name="help_label" msgid="3528360748637781274">"உதவியும் கருத்தும்"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 303d310..23c00c1 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"ARC ద్వారా కనెక్ట్ చేయబడింది"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"eARC ద్వారా కనెక్ట్ చేయబడింది"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"టీవీ ఆటోమేటిక్ సెట్టింగ్"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI అవుట్‌పుట్"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"అంతర్గత స్పీకర్‌లు"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"కనెక్ట్ చేయడంలో సమస్య ఉంది. పరికరాన్ని ఆఫ్ చేసి, ఆపై తిరిగి ఆన్ చేయండి"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"వైర్ గల ఆడియో పరికరం"</string>
     <string name="help_label" msgid="3528360748637781274">"సహాయం &amp; ఫీడ్‌బ్యాక్"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 0ac8cb8..4d9d382 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"เชื่อมต่อผ่าน ARC"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"เชื่อมต่อผ่าน eARC"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"ค่าเริ่มต้นของทีวี"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"เอาต์พุต HDMI"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"ลำโพงของเครื่อง"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"เกิดปัญหาในการเชื่อมต่อ ปิดอุปกรณ์แล้วเปิดใหม่อีกครั้ง"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"อุปกรณ์เสียงแบบมีสาย"</string>
     <string name="help_label" msgid="3528360748637781274">"ความช่วยเหลือและความคิดเห็น"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 4f92e1d..c9e3494 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Nakakonekta sa pamamagitan ng ARC"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Nakakonekta sa pamamagitan ng eARC"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"Default ng TV"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI output"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Mga internal speaker"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Nagkaproblema sa pagkonekta. I-off at pagkatapos ay i-on ang device"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Wired na audio device"</string>
     <string name="help_label" msgid="3528360748637781274">"Tulong at feedback"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 795bb30..0f628b4 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"ARC ile bağlandı"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"eARC ile bağlandı"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"TV varsayılanı"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI çıkışı"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Dahili hoparlörler"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Bağlanırken sorun oluştu. Cihazı kapatıp tekrar açın"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Kablolu ses cihazı"</string>
     <string name="help_label" msgid="3528360748637781274">"Yardım ve geri bildirim"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index beb2c91..e00fbc9 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Підключено через ARC"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Підключено через eARC"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"Стандартний вихід телевізора"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"Вихід HDMI"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Внутрішні динаміки"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Не вдається підключитися. Перезавантажте пристрій."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Дротовий аудіопристрій"</string>
     <string name="help_label" msgid="3528360748637781274">"Довідка й відгуки"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 13718d9..0dcb12f 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"‏ARC کے ذریعے منسلک ہے"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"‏eARC کے ذریعے منسلک ہے"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"‏TV ڈیفالٹ"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"‏HDMI آؤٹ پٹ"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"اندرونی اسپیکرز"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"منسلک کرنے میں مسئلہ پیش آ گیا۔ آلہ کو آف اور بیک آن کریں"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"وائرڈ آڈیو آلہ"</string>
     <string name="help_label" msgid="3528360748637781274">"مدد اور تاثرات"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 7559a3d..c94ff4d 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"ARC orqali ulangan"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"eARC orqali ulangan"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"Televizorda birlamchi"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI chiqishi"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Ichki karnaylar"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ulanishda muammo yuz berdi. Qurilmani oʻchiring va yoqing"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Simli audio qurilma"</string>
     <string name="help_label" msgid="3528360748637781274">"Yordam/fikr-mulohaza"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index ccdc0bc..03f0770 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Đã kết nối qua ARC"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Đã kết nối qua eARC"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"Chế độ mặc định của TV"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"Đầu ra HDMI"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Các loa trong"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Sự cố kết nối. Hãy tắt thiết bị rồi bật lại"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Thiết bị âm thanh có dây"</string>
     <string name="help_label" msgid="3528360748637781274">"Trợ giúp và phản hồi"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 6b3e061..30db033 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"已通过 ARC 连接"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"已通过 eARC 连接"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"电视默认设置"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI 输出"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"内置扬声器"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"连接时遇到问题。请关闭并重新开启设备"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"有线音频设备"</string>
     <string name="help_label" msgid="3528360748637781274">"帮助和反馈"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 3517109..2ce4de9 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"已透過 ARC 連接"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"已透過 eARC 連接"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"電視預設的音訊輸出"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI 輸出"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"內置喇叭"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"無法連接,請關閉裝置然後重新開機"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"有線音響裝置"</string>
     <string name="help_label" msgid="3528360748637781274">"說明與意見反映"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index eeed9f3..2fac076 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"透過 ARC 連線"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"透過 eARC 連線"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"電視預設的音訊輸出裝置"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"HDMI 輸出裝置"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"內建揚聲器"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"無法連線,請關閉裝置後再重新開啟"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"有線音訊裝置"</string>
     <string name="help_label" msgid="3528360748637781274">"說明與意見回饋"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index e94b929..9a81808 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -567,12 +567,9 @@
     <string name="tv_media_transfer_earc_fallback_title" msgid="3098685494578519940">"I-HDMI eARC"</string>
     <string name="tv_media_transfer_arc_subtitle" msgid="1040017851325069082">"Ixhunywe nge-ARC"</string>
     <string name="tv_media_transfer_earc_subtitle" msgid="645191413103303077">"Ixhunywe nge-eARC"</string>
-    <!-- no translation found for tv_media_transfer_default (5403053145185843843) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_hdmi (692569220956829921) -->
-    <skip />
-    <!-- no translation found for tv_media_transfer_internal_speakers (8181494402866565865) -->
-    <skip />
+    <string name="tv_media_transfer_default" msgid="5403053145185843843">"I-TV ezenzakalelayo"</string>
+    <string name="tv_media_transfer_hdmi" msgid="692569220956829921">"umphumela we-HDMI"</string>
+    <string name="tv_media_transfer_internal_speakers" msgid="8181494402866565865">"Izipikha zangaphakathi"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Inkinga yokuxhumeka. Vala idivayisi futhi uphinde uyivule"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Idivayisi yomsindo enentambo"</string>
     <string name="help_label" msgid="3528360748637781274">"Usizo nempendulo"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java
index e77964c..c51a9a0 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java
@@ -22,13 +22,16 @@
 
 import static com.android.settingslib.Utils.getColorAttrDefaultColor;
 
+import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.AppGlobals;
+import android.app.AppOpsManager;
 import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
@@ -39,10 +42,12 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.UserManager.EnforcingUser;
+import android.provider.Settings;
 import android.text.SpannableStringBuilder;
 import android.text.Spanned;
 import android.text.style.ForegroundColorSpan;
 import android.text.style.ImageSpan;
+import android.util.ArraySet;
 import android.util.Log;
 import android.view.MenuItem;
 import android.widget.TextView;
@@ -53,6 +58,7 @@
 import com.android.internal.widget.LockPatternUtils;
 
 import java.util.List;
+import java.util.Set;
 
 /**
  * Utility class to host methods usable in adding a restricted padlock icon and showing admin
@@ -62,6 +68,19 @@
 
     private static final String LOG_TAG = "RestrictedLockUtils";
     private static final boolean DEBUG = Log.isLoggable(LOG_TAG, Log.DEBUG);
+    private static final Set<String> ECM_KEYS = new ArraySet<>();
+
+    static {
+        if (android.security.Flags.extendEcmToAllSettings()) {
+            ECM_KEYS.add(AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW);
+            ECM_KEYS.add(AppOpsManager.OPSTR_GET_USAGE_STATS);
+            ECM_KEYS.add(AppOpsManager.OPSTR_LOADER_USAGE_STATS);
+            ECM_KEYS.add(Manifest.permission.BIND_DEVICE_ADMIN);
+        }
+
+        ECM_KEYS.add(AppOpsManager.OPSTR_ACCESS_NOTIFICATIONS);
+        ECM_KEYS.add(AppOpsManager.OPSTR_BIND_ACCESSIBILITY_SERVICE);
+    }
 
     /**
      * @return drawables for displaying with settings that are locked by a device admin.
@@ -81,6 +100,38 @@
     }
 
     /**
+     * Checks if a given permission requires additional confirmation for the given package
+     *
+     * @return An intent to show the user if additional confirmation is required, null otherwise
+     */
+    @Nullable
+    public static Intent checkIfRequiresEnhancedConfirmation(@NonNull Context context,
+                                                             @NonNull String restriction,
+                                                             int uid,
+                                                             @Nullable String packageName) {
+        // TODO(b/297372999): Replace with call to mainline module once ready
+
+        if (!ECM_KEYS.contains(restriction)) {
+            return null;
+        }
+
+        final AppOpsManager appOps = (AppOpsManager) context
+                .getSystemService(Context.APP_OPS_SERVICE);
+        final int mode = appOps.noteOpNoThrow(AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS,
+                uid, packageName, null, null);
+        final boolean ecmEnabled = context.getResources().getBoolean(
+                com.android.internal.R.bool.config_enhancedConfirmationModeEnabled);
+        if (ecmEnabled && mode != AppOpsManager.MODE_ALLOWED) {
+            final Intent intent = new Intent(Settings.ACTION_SHOW_RESTRICTED_SETTING_DIALOG);
+            intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
+            intent.putExtra(Intent.EXTRA_UID, uid);
+            return intent;
+        }
+
+        return null;
+    }
+
+    /**
      * Checks if a restriction is enforced on a user and returns the enforced admin and
      * admin userId.
      *
@@ -243,32 +294,6 @@
     }
 
     /**
-     * Checks whether add user is disabled on the device
-     *
-     * @param context {@link Context} for the calling user.
-     *
-     *
-     * @param userId User to check enforced admin status for.
-     *
-     * @return EnforcedAdmin Object containing the enforced admin component and admin user details,
-     * or {@code null} If adding user is not disabled.
-     */
-    public static EnforcedAdmin checkIfAddUserDisallowed(Context context, int userId) {
-        final UserManager um = UserManager.get(context);
-        if (!um.hasUserRestriction(UserManager.DISALLOW_ADD_USER, UserHandle.of(userId))) {
-            // Restriction is not enforced.
-            return null;
-        }
-        EnforcedAdmin enforcedAdmin = checkIfRestrictionEnforced(context,
-                UserManager.DISALLOW_ADD_USER, userId);
-        if (enforcedAdmin != null) {
-            return enforcedAdmin;
-        }
-        return EnforcedAdmin.createDefaultEnforcedAdminWithRestriction(
-                UserManager.DISALLOW_ADD_USER);
-    }
-
-    /**
      * Check if an application is suspended.
      *
      * @return EnforcedAdmin Object containing the enforced admin component and admin user details,
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreference.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreference.java
index db2a6ec..50e3bd0 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreference.java
@@ -96,12 +96,29 @@
         mHelper.checkRestrictionAndSetDisabled(userRestriction, userId);
     }
 
+    /**
+     * Checks if the given setting is subject to Enhanced Confirmation Mode restrictions for this
+     * package. Marks the preference as disabled if so.
+     * @param restriction The key identifying the setting
+     * @param packageName the package to check the restriction for
+     * @param uid the uid of the package
+     */
+    public void checkEcmRestrictionAndSetDisabled(String restriction, String packageName, int uid) {
+        mHelper.checkEcmRestrictionAndSetDisabled(restriction, packageName, uid);
+    }
+
     @Override
     public void setEnabled(boolean enabled) {
         if (enabled && isDisabledByAdmin()) {
             mHelper.setDisabledByAdmin(null);
             return;
         }
+
+        if (enabled && isDisabledByEcm()) {
+            mHelper.setDisabledByEcm(null);
+            return;
+        }
+
         super.setEnabled(enabled);
     }
 
@@ -111,16 +128,14 @@
         }
     }
 
-    public void setDisabledByAppOps(boolean disabled) {
-        if (mHelper.setDisabledByAppOps(disabled)) {
-            notifyChanged();
-        }
-    }
-
     public boolean isDisabledByAdmin() {
         return mHelper.isDisabledByAdmin();
     }
 
+    public boolean isDisabledByEcm() {
+        return mHelper.isDisabledByEcm();
+    }
+
     public int getUid() {
         return mHelper != null ? mHelper.uid : Process.INVALID_UID;
     }
@@ -128,4 +143,16 @@
     public String getPackageName() {
         return mHelper != null ? mHelper.packageName : null;
     }
+
+    /**
+     * @deprecated TODO(b/308921175): This will be deleted with the
+     * {@link android.security.Flags#extendEcmToAllSettings} feature flag. Do not use for any new
+     * code.
+     */
+    @Deprecated
+    public void setDisabledByAppOps(boolean disabled) {
+        if (mHelper.setDisabledByAppOps(disabled)) {
+            notifyChanged();
+        }
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
index 29ea25e..a479269 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
@@ -17,10 +17,12 @@
 package com.android.settingslib;
 
 import static android.app.admin.DevicePolicyResources.Strings.Settings.CONTROLLED_BY_ADMIN_SUMMARY;
+
 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 
 import android.app.admin.DevicePolicyManager;
 import android.content.Context;
+import android.content.Intent;
 import android.content.res.TypedArray;
 import android.os.Build;
 import android.os.UserHandle;
@@ -52,7 +54,8 @@
     private String mAttrUserRestriction = null;
     private boolean mDisabledSummary = false;
 
-    private boolean mDisabledByAppOps;
+    private boolean mDisabledByEcm;
+    private Intent mDisabledByEcmIntent = null;
 
     public RestrictedPreferenceHelper(Context context, Preference preference,
             AttributeSet attrs, String packageName, int uid) {
@@ -101,7 +104,7 @@
      * Modify PreferenceViewHolder to add padlock if restriction is disabled.
      */
     public void onBindViewHolder(PreferenceViewHolder holder) {
-        if (mDisabledByAdmin || mDisabledByAppOps) {
+        if (mDisabledByAdmin || mDisabledByEcm) {
             holder.itemView.setEnabled(true);
         }
         if (mDisabledSummary) {
@@ -112,7 +115,7 @@
                         : mContext.getString(R.string.disabled_by_admin_summary_text);
                 if (mDisabledByAdmin) {
                     summaryView.setText(disabledText);
-                } else if (mDisabledByAppOps) {
+                } else if (mDisabledByEcm) {
                     summaryView.setText(R.string.disabled_by_app_ops_text);
                 } else if (TextUtils.equals(disabledText, summaryView.getText())) {
                     // It's previously set to disabled text, clear it.
@@ -144,7 +147,12 @@
             RestrictedLockUtils.sendShowAdminSupportDetailsIntent(mContext, mEnforcedAdmin);
             return true;
         }
-        if (mDisabledByAppOps) {
+        if (mDisabledByEcm) {
+            if (android.security.Flags.extendEcmToAllSettings()) {
+                mContext.startActivity(mDisabledByEcmIntent);
+                return true;
+            }
+
             RestrictedLockUtilsInternal.sendShowRestrictedSettingDialogIntent(mContext, packageName,
                     uid);
             return true;
@@ -174,6 +182,20 @@
     }
 
     /**
+     * Checks if the given setting is subject to Enhanced Confirmation Mode restrictions for this
+     * package. Marks the preference as disabled if so.
+     * @param restriction The key identifying the setting
+     * @param packageName the package to check the restriction for
+     * @param uid the uid of the package
+     */
+    public void checkEcmRestrictionAndSetDisabled(String restriction, String packageName, int uid) {
+        updatePackageDetails(packageName, uid);
+        Intent intent = RestrictedLockUtilsInternal.checkIfRequiresEnhancedConfirmation(
+                mContext, restriction, uid, packageName);
+        setDisabledByEcm(intent);
+    }
+
+    /**
      * @return EnforcedAdmin if we have been passed the restriction in the xml.
      */
     public EnforcedAdmin checkRestrictionEnforced() {
@@ -211,10 +233,19 @@
         return changed;
     }
 
-    public boolean setDisabledByAppOps(boolean disabled) {
+    /**
+     * Disable the preference based on the passed in Intent
+     * @param disabledIntent The intent which is started when the user clicks the disabled
+     * preference. If it is {@code null}, then this preference will be enabled. Otherwise, it will
+     * be disabled.
+     * @return true if the disabled state was changed.
+     */
+    public boolean setDisabledByEcm(Intent disabledIntent) {
+        boolean disabled = disabledIntent != null;
         boolean changed = false;
-        if (mDisabledByAppOps != disabled) {
-            mDisabledByAppOps = disabled;
+        if (mDisabledByEcm != disabled) {
+            mDisabledByEcmIntent = disabledIntent;
+            mDisabledByEcm = disabled;
             changed = true;
             updateDisabledState();
         }
@@ -226,8 +257,8 @@
         return mDisabledByAdmin;
     }
 
-    public boolean isDisabledByAppOps() {
-        return mDisabledByAppOps;
+    public boolean isDisabledByEcm() {
+        return mDisabledByEcm;
     }
 
     public void updatePackageDetails(String packageName, int uid) {
@@ -236,13 +267,31 @@
     }
 
     private void updateDisabledState() {
+        boolean isEnabled = !(mDisabledByAdmin || mDisabledByEcm);
         if (!(mPreference instanceof RestrictedTopLevelPreference)) {
-            mPreference.setEnabled(!(mDisabledByAdmin || mDisabledByAppOps));
+            mPreference.setEnabled(isEnabled);
         }
 
         if (mPreference instanceof PrimarySwitchPreference) {
-            ((PrimarySwitchPreference) mPreference)
-                    .setSwitchEnabled(!(mDisabledByAdmin || mDisabledByAppOps));
+            ((PrimarySwitchPreference) mPreference).setSwitchEnabled(isEnabled);
         }
     }
+
+
+    /**
+     * @deprecated TODO(b/308921175): This will be deleted with the
+     * {@link android.security.Flags#extendEcmToAllSettings} feature flag. Do not use for any new
+     * code.
+     */
+    @Deprecated
+    public boolean setDisabledByAppOps(boolean disabled) {
+        boolean changed = false;
+        if (mDisabledByEcm != disabled) {
+            mDisabledByEcm = disabled;
+            changed = true;
+            updateDisabledState();
+        }
+
+        return changed;
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
index 60321eb..3b8f665 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
@@ -197,6 +197,17 @@
         mHelper.checkRestrictionAndSetDisabled(userRestriction, userId);
     }
 
+    /**
+     * Checks if the given setting is subject to Enhanced Confirmation Mode restrictions for this
+     * package. Marks the preference as disabled if so.
+     * @param restriction The key identifying the setting
+     * @param packageName the package to check the restriction for
+     * @param uid the uid of the package
+     */
+    public void checkEcmRestrictionAndSetDisabled(String restriction, String packageName, int uid) {
+        mHelper.checkEcmRestrictionAndSetDisabled(restriction, packageName, uid);
+    }
+
     @Override
     public void setEnabled(boolean enabled) {
         boolean changed = false;
@@ -204,8 +215,8 @@
             mHelper.setDisabledByAdmin(null);
             changed = true;
         }
-        if (enabled && isDisabledByAppOps()) {
-            mHelper.setDisabledByAppOps(false);
+        if (enabled && isDisabledByEcm()) {
+            mHelper.setDisabledByEcm(null);
             changed = true;
         }
         if (!changed) {
@@ -223,25 +234,50 @@
         return mHelper.isDisabledByAdmin();
     }
 
+    public boolean isDisabledByEcm() {
+        return mHelper.isDisabledByEcm();
+    }
+
+    /**
+     * @deprecated TODO(b/308921175): This will be deleted with the
+     * {@link android.security.Flags#extendEcmToAllSettings} feature flag. Do not use for any new
+     * code.
+     */
+    @Deprecated
     private void setDisabledByAppOps(boolean disabled) {
         if (mHelper.setDisabledByAppOps(disabled)) {
             notifyChanged();
         }
     }
 
-    public boolean isDisabledByAppOps() {
-        return mHelper.isDisabledByAppOps();
-    }
-
+    /**
+     * @deprecated TODO(b/308921175): This will be deleted with the
+     * {@link android.security.Flags#extendEcmToAllSettings} feature flag. Do not use for any new
+     * code.
+     */
+    @Deprecated
     public int getUid() {
         return mHelper != null ? mHelper.uid : Process.INVALID_UID;
     }
 
+    /**
+     * @deprecated TODO(b/308921175): This will be deleted with the
+     * {@link android.security.Flags#extendEcmToAllSettings} feature flag. Do not use for any new
+     * code.
+     */
+    @Deprecated
     public String getPackageName() {
         return mHelper != null ? mHelper.packageName : null;
     }
 
-    /** Updates enabled state based on associated package. */
+    /**
+     * Updates enabled state based on associated package
+     *
+     * @deprecated TODO(b/308921175): This will be deleted with the
+     * {@link android.security.Flags#extendEcmToAllSettings} feature flag. Do not use for any new
+     * code.
+     */
+    @Deprecated
     public void updateState(
             @NonNull String packageName, int uid, boolean isEnableAllowed, boolean isEnabled) {
         mHelper.updatePackageDetails(packageName, uid);
@@ -258,7 +294,7 @@
             setEnabled(false);
         } else if (isEnabled) {
             setEnabled(true);
-        } else if (appOpsAllowed && isDisabledByAppOps()) {
+        } else if (appOpsAllowed && isDisabledByEcm()) {
             setEnabled(true);
         } else if (!appOpsAllowed){
             setDisabledByAppOps(true);
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java
index 69b61c7..49ac0f8 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java
@@ -28,10 +28,11 @@
 import android.bluetooth.BluetoothLeBroadcastAssistant;
 import android.bluetooth.BluetoothLeBroadcastMetadata;
 import android.bluetooth.BluetoothLeBroadcastReceiveState;
+import android.bluetooth.BluetoothLeBroadcastSettings;
 import android.bluetooth.BluetoothLeBroadcastSubgroup;
+import android.bluetooth.BluetoothLeBroadcastSubgroupSettings;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothProfile.ServiceListener;
-import android.bluetooth.BluetoothStatusCodes;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.database.ContentObserver;
@@ -42,26 +43,30 @@
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.Log;
-import android.util.Pair;
 
+import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
 
 import com.android.settingslib.R;
 
+import com.google.common.collect.ImmutableList;
+
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ThreadLocalRandom;
 
 /**
- * LocalBluetoothLeBroadcast provides an interface between the Settings app
- * and the functionality of the local {@link BluetoothLeBroadcast}.
- * Use the {@link BluetoothLeBroadcast.Callback} to get the result callback.
+ * LocalBluetoothLeBroadcast provides an interface between the Settings app and the functionality of
+ * the local {@link BluetoothLeBroadcast}. Use the {@link BluetoothLeBroadcast.Callback} to get the
+ * result callback.
  */
 public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile {
     private static final String TAG = "LocalBluetoothLeBroadcast";
@@ -74,11 +79,12 @@
     // Order of this profile in device profiles list
     private static final int ORDINAL = 1;
     private static final int UNKNOWN_VALUE_PLACEHOLDER = -1;
-    private static final Uri[] SETTINGS_URIS = new Uri[]{
-            Settings.Secure.getUriFor(Settings.Secure.BLUETOOTH_LE_BROADCAST_PROGRAM_INFO),
-            Settings.Secure.getUriFor(Settings.Secure.BLUETOOTH_LE_BROADCAST_CODE),
-            Settings.Secure.getUriFor(Settings.Secure.BLUETOOTH_LE_BROADCAST_APP_SOURCE_NAME),
-    };
+    private static final Uri[] SETTINGS_URIS =
+            new Uri[] {
+                Settings.Secure.getUriFor(Settings.Secure.BLUETOOTH_LE_BROADCAST_PROGRAM_INFO),
+                Settings.Secure.getUriFor(Settings.Secure.BLUETOOTH_LE_BROADCAST_CODE),
+                Settings.Secure.getUriFor(Settings.Secure.BLUETOOTH_LE_BROADCAST_APP_SOURCE_NAME),
+            };
 
     private BluetoothLeBroadcast mServiceBroadcast;
     private BluetoothLeBroadcastAssistant mServiceBroadcastAssistant;
@@ -95,62 +101,82 @@
     private Executor mExecutor;
     private ContentResolver mContentResolver;
     private ContentObserver mSettingsObserver;
+    // Cached broadcast callbacks being register before service is connected.
+    private Map<BluetoothLeBroadcast.Callback, Executor> mCachedBroadcastCallbackExecutorMap =
+            new ConcurrentHashMap<>();
 
-    private final ServiceListener mServiceListener = new ServiceListener() {
-        @Override
-        public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            if (DEBUG) {
-                Log.d(TAG, "Bluetooth service connected: " + profile);
-            }
-            if ((profile == BluetoothProfile.LE_AUDIO_BROADCAST) && !mIsBroadcastProfileReady) {
-                mServiceBroadcast = (BluetoothLeBroadcast) proxy;
-                mIsBroadcastProfileReady = true;
-                registerServiceCallBack(mExecutor, mBroadcastCallback);
-                List<BluetoothLeBroadcastMetadata> metadata = getAllBroadcastMetadata();
-                if (!metadata.isEmpty()) {
-                    updateBroadcastInfoFromBroadcastMetadata(metadata.get(0));
+    private final ServiceListener mServiceListener =
+            new ServiceListener() {
+                @Override
+                public void onServiceConnected(int profile, BluetoothProfile proxy) {
+                    if (DEBUG) {
+                        Log.d(TAG, "Bluetooth service connected: " + profile);
+                    }
+                    if ((profile == BluetoothProfile.LE_AUDIO_BROADCAST)
+                            && !mIsBroadcastProfileReady) {
+                        mServiceBroadcast = (BluetoothLeBroadcast) proxy;
+                        mIsBroadcastProfileReady = true;
+                        registerServiceCallBack(mExecutor, mBroadcastCallback);
+                        List<BluetoothLeBroadcastMetadata> metadata = getAllBroadcastMetadata();
+                        if (!metadata.isEmpty()) {
+                            updateBroadcastInfoFromBroadcastMetadata(metadata.get(0));
+                        }
+                        registerContentObserver();
+                        if (DEBUG) {
+                            Log.d(
+                                    TAG,
+                                    "onServiceConnected: register "
+                                            + "mCachedBroadcastCallbackExecutorMap = "
+                                            + mCachedBroadcastCallbackExecutorMap);
+                        }
+                        mCachedBroadcastCallbackExecutorMap.forEach(
+                                (callback, executor) ->
+                                        registerServiceCallBack(executor, callback));
+                    } else if ((profile == BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT)
+                            && !mIsBroadcastAssistantProfileReady) {
+                        mIsBroadcastAssistantProfileReady = true;
+                        mServiceBroadcastAssistant = (BluetoothLeBroadcastAssistant) proxy;
+                        registerBroadcastAssistantCallback(mExecutor, mBroadcastAssistantCallback);
+                    }
                 }
-                registerContentObserver();
-            } else if ((profile == BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT)
-                    && !mIsBroadcastAssistantProfileReady) {
-                mIsBroadcastAssistantProfileReady = true;
-                mServiceBroadcastAssistant = (BluetoothLeBroadcastAssistant) proxy;
-                registerBroadcastAssistantCallback(mExecutor, mBroadcastAssistantCallback);
-            }
-        }
 
-        @Override
-        public void onServiceDisconnected(int profile) {
-            if (DEBUG) {
-                Log.d(TAG, "Bluetooth service disconnected");
-            }
-            if ((profile == BluetoothProfile.LE_AUDIO_BROADCAST) && mIsBroadcastProfileReady) {
-                mIsBroadcastProfileReady = false;
-                unregisterServiceCallBack(mBroadcastCallback);
-            }
-            if ((profile == BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT)
-                    && mIsBroadcastAssistantProfileReady) {
-                mIsBroadcastAssistantProfileReady = false;
-                unregisterBroadcastAssistantCallback(mBroadcastAssistantCallback);
-            }
+                @Override
+                public void onServiceDisconnected(int profile) {
+                    if (DEBUG) {
+                        Log.d(TAG, "Bluetooth service disconnected: " + profile);
+                    }
+                    if ((profile == BluetoothProfile.LE_AUDIO_BROADCAST)
+                            && mIsBroadcastProfileReady) {
+                        mIsBroadcastProfileReady = false;
+                        unregisterServiceCallBack(mBroadcastCallback);
+                        mCachedBroadcastCallbackExecutorMap.clear();
+                    }
+                    if ((profile == BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT)
+                            && mIsBroadcastAssistantProfileReady) {
+                        mIsBroadcastAssistantProfileReady = false;
+                        unregisterBroadcastAssistantCallback(mBroadcastAssistantCallback);
+                    }
 
-            if (!mIsBroadcastAssistantProfileReady && !mIsBroadcastProfileReady) {
-                unregisterContentObserver();
-            }
-        }
-    };
+                    if (!mIsBroadcastAssistantProfileReady && !mIsBroadcastProfileReady) {
+                        unregisterContentObserver();
+                    }
+                }
+            };
 
     private final BluetoothLeBroadcast.Callback mBroadcastCallback =
             new BluetoothLeBroadcast.Callback() {
                 @Override
                 public void onBroadcastStarted(int reason, int broadcastId) {
                     if (DEBUG) {
-                        Log.d(TAG,
-                                "onBroadcastStarted(), reason = " + reason + ", broadcastId = "
+                        Log.d(
+                                TAG,
+                                "onBroadcastStarted(), reason = "
+                                        + reason
+                                        + ", broadcastId = "
                                         + broadcastId);
                     }
                     setLatestBroadcastId(broadcastId);
-                    setAppSourceName(mNewAppSourceName, /*updateContentResolver=*/ true);
+                    setAppSourceName(mNewAppSourceName, /* updateContentResolver= */ true);
                 }
 
                 @Override
@@ -161,8 +187,8 @@
                 }
 
                 @Override
-                public void onBroadcastMetadataChanged(int broadcastId,
-                        @NonNull BluetoothLeBroadcastMetadata metadata) {
+                public void onBroadcastMetadataChanged(
+                        int broadcastId, @NonNull BluetoothLeBroadcastMetadata metadata) {
                     if (DEBUG) {
                         Log.d(TAG, "onBroadcastMetadataChanged(), broadcastId = " + broadcastId);
                     }
@@ -172,8 +198,11 @@
                 @Override
                 public void onBroadcastStopped(int reason, int broadcastId) {
                     if (DEBUG) {
-                        Log.d(TAG,
-                                "onBroadcastStopped(), reason = " + reason + ", broadcastId = "
+                        Log.d(
+                                TAG,
+                                "onBroadcastStopped(), reason = "
+                                        + reason
+                                        + ", broadcastId = "
                                         + broadcastId);
                     }
 
@@ -191,37 +220,42 @@
                 @Override
                 public void onBroadcastUpdated(int reason, int broadcastId) {
                     if (DEBUG) {
-                        Log.d(TAG,
-                                "onBroadcastUpdated(), reason = " + reason + ", broadcastId = "
+                        Log.d(
+                                TAG,
+                                "onBroadcastUpdated(), reason = "
+                                        + reason
+                                        + ", broadcastId = "
                                         + broadcastId);
                     }
                     setLatestBroadcastId(broadcastId);
-                    setAppSourceName(mNewAppSourceName, /*updateContentResolver=*/ true);
+                    setAppSourceName(mNewAppSourceName, /* updateContentResolver= */ true);
                 }
 
                 @Override
                 public void onBroadcastUpdateFailed(int reason, int broadcastId) {
                     if (DEBUG) {
-                        Log.d(TAG,
-                                "onBroadcastUpdateFailed(), reason = " + reason + ", broadcastId = "
+                        Log.d(
+                                TAG,
+                                "onBroadcastUpdateFailed(), reason = "
+                                        + reason
+                                        + ", broadcastId = "
                                         + broadcastId);
                     }
                 }
 
                 @Override
-                public void onPlaybackStarted(int reason, int broadcastId) {
-                }
+                public void onPlaybackStarted(int reason, int broadcastId) {}
 
                 @Override
-                public void onPlaybackStopped(int reason, int broadcastId) {
-                }
+                public void onPlaybackStopped(int reason, int broadcastId) {}
             };
 
     private final BluetoothLeBroadcastAssistant.Callback mBroadcastAssistantCallback =
             new BluetoothLeBroadcastAssistant.Callback() {
                 @Override
-                public void onSourceAdded(@NonNull BluetoothDevice sink, int sourceId,
-                        int reason) {}
+                public void onSourceAdded(
+                        @NonNull BluetoothDevice sink, int sourceId, int reason) {}
+
                 @Override
                 public void onSearchStarted(int reason) {}
 
@@ -238,38 +272,65 @@
                 public void onSourceFound(@NonNull BluetoothLeBroadcastMetadata source) {}
 
                 @Override
-                public void onSourceAddFailed(@NonNull BluetoothDevice sink,
-                        @NonNull BluetoothLeBroadcastMetadata source, int reason) {}
-
-                @Override
-                public void onSourceModified(@NonNull BluetoothDevice sink, int sourceId,
+                public void onSourceAddFailed(
+                        @NonNull BluetoothDevice sink,
+                        @NonNull BluetoothLeBroadcastMetadata source,
                         int reason) {}
 
                 @Override
-                public void onSourceModifyFailed(@NonNull BluetoothDevice sink, int sourceId,
-                        int reason) {}
+                public void onSourceModified(
+                        @NonNull BluetoothDevice sink, int sourceId, int reason) {}
 
                 @Override
-                public void onSourceRemoved(@NonNull BluetoothDevice sink, int sourceId,
-                        int reason) {
+                public void onSourceModifyFailed(
+                        @NonNull BluetoothDevice sink, int sourceId, int reason) {}
+
+                @Override
+                public void onSourceRemoved(
+                        @NonNull BluetoothDevice sink, int sourceId, int reason) {
                     if (DEBUG) {
-                        Log.d(TAG, "onSourceRemoved(), sink = " + sink + ", reason = "
-                                + reason + ", sourceId = " + sourceId);
+                        Log.d(
+                                TAG,
+                                "onSourceRemoved(), sink = "
+                                        + sink
+                                        + ", reason = "
+                                        + reason
+                                        + ", sourceId = "
+                                        + sourceId);
                     }
                 }
 
                 @Override
-                public void onSourceRemoveFailed(@NonNull BluetoothDevice sink, int sourceId,
-                        int reason) {
+                public void onSourceRemoveFailed(
+                        @NonNull BluetoothDevice sink, int sourceId, int reason) {
                     if (DEBUG) {
-                        Log.d(TAG, "onSourceRemoveFailed(), sink = " + sink + ", reason = "
-                                + reason + ", sourceId = " + sourceId);
+                        Log.d(
+                                TAG,
+                                "onSourceRemoveFailed(), sink = "
+                                        + sink
+                                        + ", reason = "
+                                        + reason
+                                        + ", sourceId = "
+                                        + sourceId);
                     }
                 }
 
                 @Override
-                public void onReceiveStateChanged(@NonNull BluetoothDevice sink, int sourceId,
-                        @NonNull BluetoothLeBroadcastReceiveState state) {}
+                public void onReceiveStateChanged(
+                        @NonNull BluetoothDevice sink,
+                        int sourceId,
+                        @NonNull BluetoothLeBroadcastReceiveState state) {
+                    if (DEBUG) {
+                        Log.d(
+                                TAG,
+                                "onReceiveStateChanged(), sink = "
+                                        + sink
+                                        + ", sourceId = "
+                                        + sourceId
+                                        + ", state = "
+                                        + state);
+                    }
+                }
             };
 
     private class BroadcastSettingsObserver extends ContentObserver {
@@ -296,8 +357,8 @@
         BluetoothAdapter.getDefaultAdapter()
                 .getProfileProxy(context, mServiceListener, BluetoothProfile.LE_AUDIO_BROADCAST);
         BluetoothAdapter.getDefaultAdapter()
-                .getProfileProxy(context, mServiceListener,
-                BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+                .getProfileProxy(
+                        context, mServiceListener, BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
     }
 
     /**
@@ -312,20 +373,91 @@
         }
         String programInfo = getProgramInfo();
         if (DEBUG) {
-            Log.d(TAG,
-                    "startBroadcast: language = " + language + " ,programInfo = " + programInfo);
+            Log.d(TAG, "startBroadcast: language = " + language + " ,programInfo = " + programInfo);
         }
         buildContentMetadata(language, programInfo);
-        mServiceBroadcast.startBroadcast(mBluetoothLeAudioContentMetadata,
+        mServiceBroadcast.startBroadcast(
+                mBluetoothLeAudioContentMetadata,
                 (mBroadcastCode != null && mBroadcastCode.length > 0) ? mBroadcastCode : null);
     }
 
+    /**
+     * Start the private Broadcast for personal audio sharing or qr code sharing.
+     *
+     * <p>The broadcast will use random string for both broadcast name and subgroup program info;
+     * The broadcast will use random string for broadcast code; The broadcast will only have one
+     * subgroup due to system limitation; The subgroup language will be null.
+     *
+     * <p>If the system started the LE Broadcast, then the system calls the corresponding callback
+     * {@link BluetoothLeBroadcast.Callback}.
+     */
+    public void startPrivateBroadcast(int quality) {
+        mNewAppSourceName = "Sharing audio";
+        if (mServiceBroadcast == null) {
+            Log.d(TAG, "The BluetoothLeBroadcast is null when starting the private broadcast.");
+            return;
+        }
+        if (mServiceBroadcast.getAllBroadcastMetadata().size()
+                >= mServiceBroadcast.getMaximumNumberOfBroadcasts()) {
+            Log.d(TAG, "Skip starting the broadcast due to number limit.");
+            return;
+        }
+        String programInfo = getProgramInfo();
+        if (DEBUG) {
+            Log.d(TAG, "startBroadcast: language = null ,programInfo = " + programInfo);
+        }
+        // Current broadcast framework only support one subgroup
+        BluetoothLeBroadcastSubgroupSettings subgroupSettings =
+                buildBroadcastSubgroupSettings(/* language= */ null, programInfo, quality);
+        BluetoothLeBroadcastSettings settings =
+                buildBroadcastSettings(
+                        true, // TODO: set to false after framework fix
+                        TextUtils.isEmpty(programInfo) ? null : programInfo,
+                        (mBroadcastCode != null && mBroadcastCode.length > 0)
+                                ? mBroadcastCode
+                                : null,
+                        ImmutableList.of(subgroupSettings));
+        mServiceBroadcast.startBroadcast(settings);
+    }
+
+    private BluetoothLeBroadcastSettings buildBroadcastSettings(
+            boolean isPublic,
+            @Nullable String broadcastName,
+            @Nullable byte[] broadcastCode,
+            List<BluetoothLeBroadcastSubgroupSettings> subgroupSettingsList) {
+        BluetoothLeBroadcastSettings.Builder builder =
+                new BluetoothLeBroadcastSettings.Builder()
+                        .setPublicBroadcast(isPublic)
+                        .setBroadcastName(broadcastName)
+                        .setBroadcastCode(broadcastCode);
+        for (BluetoothLeBroadcastSubgroupSettings subgroupSettings : subgroupSettingsList) {
+            builder.addSubgroupSettings(subgroupSettings);
+        }
+        return builder.build();
+    }
+
+    private BluetoothLeBroadcastSubgroupSettings buildBroadcastSubgroupSettings(
+            @Nullable String language, @Nullable String programInfo, int quality) {
+        BluetoothLeAudioContentMetadata metadata =
+                new BluetoothLeAudioContentMetadata.Builder()
+                        .setLanguage(language)
+                        .setProgramInfo(programInfo)
+                        .build();
+        // Current broadcast framework only support one subgroup, thus we still maintain the latest
+        // metadata to keep legacy UI working.
+        mBluetoothLeAudioContentMetadata = metadata;
+        return new BluetoothLeBroadcastSubgroupSettings.Builder()
+                .setPreferredQuality(quality)
+                .setContentMetadata(mBluetoothLeAudioContentMetadata)
+                .build();
+    }
+
     public String getProgramInfo() {
         return mProgramInfo;
     }
 
     public void setProgramInfo(String programInfo) {
-        setProgramInfo(programInfo, /*updateContentResolver=*/ true);
+        setProgramInfo(programInfo, /* updateContentResolver= */ true);
     }
 
     private void setProgramInfo(String programInfo, boolean updateContentResolver) {
@@ -344,8 +476,10 @@
                 Log.d(TAG, "mContentResolver is null");
                 return;
             }
-            Settings.Secure.putString(mContentResolver,
-                    Settings.Secure.BLUETOOTH_LE_BROADCAST_PROGRAM_INFO, programInfo);
+            Settings.Secure.putString(
+                    mContentResolver,
+                    Settings.Secure.BLUETOOTH_LE_BROADCAST_PROGRAM_INFO,
+                    programInfo);
         }
     }
 
@@ -354,7 +488,7 @@
     }
 
     public void setBroadcastCode(byte[] broadcastCode) {
-        setBroadcastCode(broadcastCode, /*updateContentResolver=*/ true);
+        setBroadcastCode(broadcastCode, /* updateContentResolver= */ true);
     }
 
     private void setBroadcastCode(byte[] broadcastCode, boolean updateContentResolver) {
@@ -372,7 +506,9 @@
                 Log.d(TAG, "mContentResolver is null");
                 return;
             }
-            Settings.Secure.putString(mContentResolver, Settings.Secure.BLUETOOTH_LE_BROADCAST_CODE,
+            Settings.Secure.putString(
+                    mContentResolver,
+                    Settings.Secure.BLUETOOTH_LE_BROADCAST_CODE,
                     new String(broadcastCode, StandardCharsets.UTF_8));
         }
     }
@@ -401,8 +537,10 @@
                 Log.d(TAG, "mContentResolver is null");
                 return;
             }
-            Settings.Secure.putString(mContentResolver,
-                    Settings.Secure.BLUETOOTH_LE_BROADCAST_APP_SOURCE_NAME, mAppSourceName);
+            Settings.Secure.putString(
+                    mContentResolver,
+                    Settings.Secure.BLUETOOTH_LE_BROADCAST_APP_SOURCE_NAME,
+                    mAppSourceName);
         }
     }
 
@@ -427,10 +565,11 @@
         if (mBluetoothLeBroadcastMetadata == null) {
             final List<BluetoothLeBroadcastMetadata> metadataList =
                     mServiceBroadcast.getAllBroadcastMetadata();
-            mBluetoothLeBroadcastMetadata = metadataList.stream()
-                    .filter(i -> i.getBroadcastId() == mBroadcastId)
-                    .findFirst()
-                    .orElse(null);
+            mBluetoothLeBroadcastMetadata =
+                    metadataList.stream()
+                            .filter(i -> i.getBroadcastId() == mBroadcastId)
+                            .findFirst()
+                            .orElse(null);
         }
         return mBluetoothLeBroadcastMetadata;
     }
@@ -440,22 +579,27 @@
             Log.d(TAG, "updateBroadcastInfoFromContentProvider: mContentResolver is null");
             return;
         }
-        String programInfo = Settings.Secure.getString(mContentResolver,
-                Settings.Secure.BLUETOOTH_LE_BROADCAST_PROGRAM_INFO);
+        String programInfo =
+                Settings.Secure.getString(
+                        mContentResolver, Settings.Secure.BLUETOOTH_LE_BROADCAST_PROGRAM_INFO);
         if (programInfo == null) {
             programInfo = getDefaultValueOfProgramInfo();
         }
-        setProgramInfo(programInfo, /*updateContentResolver=*/ false);
+        setProgramInfo(programInfo, /* updateContentResolver= */ false);
 
-        String prefBroadcastCode = Settings.Secure.getString(mContentResolver,
-                Settings.Secure.BLUETOOTH_LE_BROADCAST_CODE);
-        byte[] broadcastCode = (prefBroadcastCode == null) ? getDefaultValueOfBroadcastCode()
-                : prefBroadcastCode.getBytes(StandardCharsets.UTF_8);
-        setBroadcastCode(broadcastCode, /*updateContentResolver=*/ false);
+        String prefBroadcastCode =
+                Settings.Secure.getString(
+                        mContentResolver, Settings.Secure.BLUETOOTH_LE_BROADCAST_CODE);
+        byte[] broadcastCode =
+                (prefBroadcastCode == null)
+                        ? getDefaultValueOfBroadcastCode()
+                        : prefBroadcastCode.getBytes(StandardCharsets.UTF_8);
+        setBroadcastCode(broadcastCode, /* updateContentResolver= */ false);
 
-        String appSourceName = Settings.Secure.getString(mContentResolver,
-                Settings.Secure.BLUETOOTH_LE_BROADCAST_APP_SOURCE_NAME);
-        setAppSourceName(appSourceName, /*updateContentResolver=*/ false);
+        String appSourceName =
+                Settings.Secure.getString(
+                        mContentResolver, Settings.Secure.BLUETOOTH_LE_BROADCAST_APP_SOURCE_NAME);
+        setAppSourceName(appSourceName, /* updateContentResolver= */ false);
     }
 
     private void updateBroadcastInfoFromBroadcastMetadata(
@@ -474,12 +618,12 @@
         }
         BluetoothLeAudioContentMetadata contentMetadata = subgroup.get(0).getContentMetadata();
         setProgramInfo(contentMetadata.getProgramInfo());
-        setAppSourceName(getAppSourceName(), /*updateContentResolver=*/ true);
+        setAppSourceName(getAppSourceName(), /* updateContentResolver= */ true);
     }
 
     /**
-     * Stop the latest LE Broadcast. If the system stopped the LE Broadcast, then the system
-     * calls the corresponding callback {@link BluetoothLeBroadcast.Callback}.
+     * Stop the latest LE Broadcast. If the system stopped the LE Broadcast, then the system calls
+     * the corresponding callback {@link BluetoothLeBroadcast.Callback}.
      */
     public void stopLatestBroadcast() {
         stopBroadcast(mBroadcastId);
@@ -511,7 +655,8 @@
         }
         String programInfo = getProgramInfo();
         if (DEBUG) {
-            Log.d(TAG,
+            Log.d(
+                    TAG,
                     "updateBroadcast: language = " + language + " ,programInfo = " + programInfo);
         }
         mNewAppSourceName = appSourceName;
@@ -519,50 +664,79 @@
         mServiceBroadcast.updateBroadcast(mBroadcastId, mBluetoothLeAudioContentMetadata);
     }
 
-    public void registerServiceCallBack(@NonNull @CallbackExecutor Executor executor,
-            @NonNull BluetoothLeBroadcast.Callback callback) {
-        if (mServiceBroadcast == null) {
-            Log.d(TAG, "The BluetoothLeBroadcast is null.");
-            return;
-        }
-
-        mServiceBroadcast.registerCallback(executor, callback);
-    }
-
     /**
-     * Register Broadcast Assistant Callbacks to track it's state and receivers
+     * Register Broadcast Callbacks to track its state and receivers
      *
      * @param executor Executor object for callback
      * @param callback Callback object to be registered
      */
-    public void registerBroadcastAssistantCallback(@NonNull @CallbackExecutor Executor executor,
+    public void registerServiceCallBack(
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull BluetoothLeBroadcast.Callback callback) {
+        if (mServiceBroadcast == null) {
+            Log.d(TAG, "registerServiceCallBack failed, the BluetoothLeBroadcast is null.");
+            mCachedBroadcastCallbackExecutorMap.putIfAbsent(callback, executor);
+            return;
+        }
+
+        try {
+            mServiceBroadcast.registerCallback(executor, callback);
+        } catch (IllegalArgumentException e) {
+            Log.w(TAG, "registerServiceCallBack failed. " + e.getMessage());
+        }
+    }
+
+    /**
+     * Register Broadcast Assistant Callbacks to track its state and receivers
+     *
+     * @param executor Executor object for callback
+     * @param callback Callback object to be registered
+     */
+    private void registerBroadcastAssistantCallback(
+            @NonNull @CallbackExecutor Executor executor,
             @NonNull BluetoothLeBroadcastAssistant.Callback callback) {
         if (mServiceBroadcastAssistant == null) {
-            Log.d(TAG, "The BluetoothLeBroadcastAssisntant is null.");
+            Log.d(
+                    TAG,
+                    "registerBroadcastAssistantCallback failed, "
+                            + "the BluetoothLeBroadcastAssistant is null.");
             return;
         }
 
         mServiceBroadcastAssistant.registerCallback(executor, callback);
     }
 
-    public void unregisterServiceCallBack(@NonNull BluetoothLeBroadcast.Callback callback) {
-        if (mServiceBroadcast == null) {
-            Log.d(TAG, "The BluetoothLeBroadcast is null.");
-            return;
-        }
-
-        mServiceBroadcast.unregisterCallback(callback);
-    }
-
     /**
-     * Unregister previousely registered Broadcast Assistant Callbacks
+     * Unregister previously registered Broadcast Callbacks
      *
      * @param callback Callback object to be unregistered
      */
-    public void unregisterBroadcastAssistantCallback(
+    public void unregisterServiceCallBack(@NonNull BluetoothLeBroadcast.Callback callback) {
+        mCachedBroadcastCallbackExecutorMap.remove(callback);
+        if (mServiceBroadcast == null) {
+            Log.d(TAG, "unregisterServiceCallBack failed, the BluetoothLeBroadcast is null.");
+            return;
+        }
+
+        try {
+            mServiceBroadcast.unregisterCallback(callback);
+        } catch (IllegalArgumentException e) {
+            Log.w(TAG, "unregisterServiceCallBack failed. " + e.getMessage());
+        }
+    }
+
+    /**
+     * Unregister previously registered Broadcast Assistant Callbacks
+     *
+     * @param callback Callback object to be unregistered
+     */
+    private void unregisterBroadcastAssistantCallback(
             @NonNull BluetoothLeBroadcastAssistant.Callback callback) {
         if (mServiceBroadcastAssistant == null) {
-            Log.d(TAG, "The BluetoothLeBroadcastAssisntant is null.");
+            Log.d(
+                    TAG,
+                    "unregisterBroadcastAssistantCallback, "
+                            + "the BluetoothLeBroadcastAssistant is null.");
             return;
         }
 
@@ -570,8 +744,8 @@
     }
 
     private void buildContentMetadata(String language, String programInfo) {
-        mBluetoothLeAudioContentMetadata = mBuilder.setLanguage(language).setProgramInfo(
-                programInfo).build();
+        mBluetoothLeAudioContentMetadata =
+                mBuilder.setLanguage(language).setProgramInfo(programInfo).build();
     }
 
     public LocalBluetoothLeBroadcastMetadata getLocalBluetoothLeBroadcastMetaData() {
@@ -600,9 +774,7 @@
         return true;
     }
 
-    /**
-     * Not supported since LE Audio Broadcasts do not establish a connection.
-     */
+    /** Not supported since LE Audio Broadcasts do not establish a connection. */
     public int getConnectionStatus(BluetoothDevice device) {
         if (mServiceBroadcast == null) {
             return BluetoothProfile.STATE_DISCONNECTED;
@@ -611,9 +783,7 @@
         return mServiceBroadcast.getConnectionState(device);
     }
 
-    /**
-     * Not supported since LE Audio Broadcasts do not establish a connection.
-     */
+    /** Not supported since LE Audio Broadcasts do not establish a connection. */
     public List<BluetoothDevice> getConnectedDevices() {
         if (mServiceBroadcast == null) {
             return new ArrayList<BluetoothDevice>(0);
@@ -622,8 +792,8 @@
         return mServiceBroadcast.getConnectedDevices();
     }
 
-    public @NonNull
-    List<BluetoothLeBroadcastMetadata> getAllBroadcastMetadata() {
+    /** Get all broadcast metadata. */
+    public @NonNull List<BluetoothLeBroadcastMetadata> getAllBroadcastMetadata() {
         if (mServiceBroadcast == null) {
             Log.d(TAG, "The BluetoothLeBroadcast is null.");
             return Collections.emptyList();
@@ -640,16 +810,14 @@
         return !mServiceBroadcast.getAllBroadcastMetadata().isEmpty();
     }
 
-    /**
-     * Service does not provide method to get/set policy.
-     */
+    /** Service does not provide method to get/set policy. */
     public int getConnectionPolicy(BluetoothDevice device) {
         return CONNECTION_POLICY_FORBIDDEN;
     }
 
     /**
-     * Service does not provide "setEnabled" method. Please use {@link #startBroadcast},
-     * {@link #stopBroadcast()} or {@link #updateBroadcast(String, String)}
+     * Service does not provide "setEnabled" method. Please use {@link #startBroadcast}, {@link
+     * #stopBroadcast()} or {@link #updateBroadcast(String, String)}
      */
     public boolean setEnabled(BluetoothDevice device, boolean enabled) {
         return false;
@@ -683,9 +851,8 @@
         }
         if (mServiceBroadcast != null) {
             try {
-                BluetoothAdapter.getDefaultAdapter().closeProfileProxy(
-                        BluetoothProfile.LE_AUDIO_BROADCAST,
-                        mServiceBroadcast);
+                BluetoothAdapter.getDefaultAdapter()
+                        .closeProfileProxy(BluetoothProfile.LE_AUDIO_BROADCAST, mServiceBroadcast);
                 mServiceBroadcast = null;
             } catch (Throwable t) {
                 Log.w(TAG, "Error cleaning up LeAudio proxy", t);
@@ -694,13 +861,13 @@
     }
 
     private String getDefaultValueOfProgramInfo() {
-        //set the default value;
+        // set the default value;
         int postfix = ThreadLocalRandom.current().nextInt(DEFAULT_CODE_MIN, DEFAULT_CODE_MAX);
         return BluetoothAdapter.getDefaultAdapter().getName() + UNDERLINE + postfix;
     }
 
     private byte[] getDefaultValueOfBroadcastCode() {
-        //set the default value;
+        // set the default value;
         return generateRandomPassword().getBytes(StandardCharsets.UTF_8);
     }
 
@@ -708,14 +875,14 @@
         if (DEBUG) {
             Log.d(TAG, "resetCacheInfo:");
         }
-        setAppSourceName("", /*updateContentResolver=*/ true);
+        setAppSourceName("", /* updateContentResolver= */ true);
         mBluetoothLeBroadcastMetadata = null;
         mBroadcastId = UNKNOWN_VALUE_PLACEHOLDER;
     }
 
     private String generateRandomPassword() {
         String randomUUID = UUID.randomUUID().toString();
-        //first 12 chars from xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
+        // first 12 chars from xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
         return randomUUID.substring(0, 8) + randomUUID.substring(9, 13);
     }
 
@@ -752,5 +919,4 @@
             }
         }
     }
-
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastAssistant.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastAssistant.java
index bb103b8..34008ac 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastAssistant.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcastAssistant.java
@@ -39,13 +39,14 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Executor;
 
-
 /**
- * LocalBluetoothLeBroadcastAssistant provides an interface between the Settings app
- * and the functionality of the local {@link BluetoothLeBroadcastAssistant}.
- * Use the {@link BluetoothLeBroadcastAssistant.Callback} to get the result callback.
+ * LocalBluetoothLeBroadcastAssistant provides an interface between the Settings app and the
+ * functionality of the local {@link BluetoothLeBroadcastAssistant}. Use the {@link
+ * BluetoothLeBroadcastAssistant.Callback} to get the result callback.
  */
 public class LocalBluetoothLeBroadcastAssistant implements LocalBluetoothProfile {
     private static final String TAG = "LocalBluetoothLeBroadcastAssistant";
@@ -62,58 +63,76 @@
     private BluetoothLeBroadcastMetadata mBluetoothLeBroadcastMetadata;
     private BluetoothLeBroadcastMetadata.Builder mBuilder;
     private boolean mIsProfileReady;
+    // Cached assistant callbacks being register before service is connected.
+    private final Map<BluetoothLeBroadcastAssistant.Callback, Executor> mCachedCallbackExecutorMap =
+            new ConcurrentHashMap<>();
 
-    private final ServiceListener mServiceListener = new ServiceListener() {
-        @Override
-        public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            if (DEBUG) {
-                Log.d(TAG, "Bluetooth service connected");
-            }
-            mService = (BluetoothLeBroadcastAssistant) proxy;
-            // We just bound to the service, so refresh the UI for any connected LeAudio devices.
-            List<BluetoothDevice> deviceList = mService.getConnectedDevices();
-            while (!deviceList.isEmpty()) {
-                BluetoothDevice nextDevice = deviceList.remove(0);
-                CachedBluetoothDevice device = mDeviceManager.findDevice(nextDevice);
-                // we may add a new device here, but generally this should not happen
-                if (device == null) {
+    private final ServiceListener mServiceListener =
+            new ServiceListener() {
+                @Override
+                public void onServiceConnected(int profile, BluetoothProfile proxy) {
                     if (DEBUG) {
-                        Log.d(TAG, "LocalBluetoothLeBroadcastAssistant found new device: "
-                                + nextDevice);
+                        Log.d(TAG, "Bluetooth service connected");
                     }
-                    device = mDeviceManager.addDevice(nextDevice);
+                    mService = (BluetoothLeBroadcastAssistant) proxy;
+                    // We just bound to the service, so refresh the UI for any connected LeAudio
+                    // devices.
+                    List<BluetoothDevice> deviceList = mService.getConnectedDevices();
+                    while (!deviceList.isEmpty()) {
+                        BluetoothDevice nextDevice = deviceList.remove(0);
+                        CachedBluetoothDevice device = mDeviceManager.findDevice(nextDevice);
+                        // we may add a new device here, but generally this should not happen
+                        if (device == null) {
+                            if (DEBUG) {
+                                Log.d(
+                                        TAG,
+                                        "LocalBluetoothLeBroadcastAssistant found new device: "
+                                                + nextDevice);
+                            }
+                            device = mDeviceManager.addDevice(nextDevice);
+                        }
+                        device.onProfileStateChanged(
+                                LocalBluetoothLeBroadcastAssistant.this,
+                                BluetoothProfile.STATE_CONNECTED);
+                        device.refresh();
+                    }
+
+                    mProfileManager.callServiceConnectedListeners();
+                    mIsProfileReady = true;
+                    if (DEBUG) {
+                        Log.d(
+                                TAG,
+                                "onServiceConnected, register mCachedCallbackExecutorMap = "
+                                        + mCachedCallbackExecutorMap);
+                    }
+                    mCachedCallbackExecutorMap.forEach(
+                            (callback, executor) -> registerServiceCallBack(executor, callback));
                 }
-                device.onProfileStateChanged(LocalBluetoothLeBroadcastAssistant.this,
-                        BluetoothProfile.STATE_CONNECTED);
-                device.refresh();
-            }
 
-            mProfileManager.callServiceConnectedListeners();
-            mIsProfileReady = true;
-        }
+                @Override
+                public void onServiceDisconnected(int profile) {
+                    if (profile != BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT) {
+                        Log.d(TAG, "The profile is not LE_AUDIO_BROADCAST_ASSISTANT");
+                        return;
+                    }
+                    if (DEBUG) {
+                        Log.d(TAG, "Bluetooth service disconnected");
+                    }
+                    mProfileManager.callServiceDisconnectedListeners();
+                    mIsProfileReady = false;
+                    mCachedCallbackExecutorMap.clear();
+                }
+            };
 
-        @Override
-        public void onServiceDisconnected(int profile) {
-            if (profile != BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT) {
-                Log.d(TAG, "The profile is not LE_AUDIO_BROADCAST_ASSISTANT");
-                return;
-            }
-            if (DEBUG) {
-                Log.d(TAG, "Bluetooth service disconnected");
-            }
-            mProfileManager.callServiceDisconnectedListeners();
-            mIsProfileReady = false;
-        }
-    };
-
-    public LocalBluetoothLeBroadcastAssistant(Context context,
+    public LocalBluetoothLeBroadcastAssistant(
+            Context context,
             CachedBluetoothDeviceManager deviceManager,
             LocalBluetoothProfileManager profileManager) {
         mProfileManager = profileManager;
         mDeviceManager = deviceManager;
-        BluetoothAdapter.getDefaultAdapter().
-                getProfileProxy(context, mServiceListener,
-                        BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+        BluetoothAdapter.getDefaultAdapter()
+                .getProfileProxy(
+                        context, mServiceListener, BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
         mBuilder = new BluetoothLeBroadcastMetadata.Builder();
     }
 
@@ -123,11 +142,11 @@
      * @param sink Broadcast Sink to which the Broadcast Source should be added
      * @param metadata Broadcast Source metadata to be added to the Broadcast Sink
      * @param isGroupOp {@code true} if Application wants to perform this operation for all
-     *                  coordinated set members throughout this session. Otherwise, caller
-     *                  would have to add, modify, and remove individual set members.
+     *     coordinated set members throughout this session. Otherwise, caller would have to add,
+     *     modify, and remove individual set members.
      */
-    public void addSource(BluetoothDevice sink, BluetoothLeBroadcastMetadata metadata,
-            boolean isGroupOp) {
+    public void addSource(
+            BluetoothDevice sink, BluetoothLeBroadcastMetadata metadata, boolean isGroupOp) {
         if (mService == null) {
             Log.d(TAG, "The BluetoothLeBroadcastAssistant is null");
             return;
@@ -140,36 +159,55 @@
      * the qr code string.
      *
      * @param sink Broadcast Sink to which the Broadcast Source should be added
-     * @param sourceAddressType hardware MAC Address of the device. See
-     *                          {@link BluetoothDevice.AddressType}.
+     * @param sourceAddressType hardware MAC Address of the device. See {@link
+     *     BluetoothDevice.AddressType}.
      * @param presentationDelayMicros presentation delay of this Broadcast Source in microseconds.
      * @param sourceAdvertisingSid 1-byte long Advertising_SID of the Broadcast Source.
      * @param broadcastId 3-byte long Broadcast_ID of the Broadcast Source.
-     * @param paSyncInterval Periodic Advertising Sync interval of the broadcast Source,
-     *                       {@link BluetoothLeBroadcastMetadata#PA_SYNC_INTERVAL_UNKNOWN} if
-     *                       unknown.
+     * @param paSyncInterval Periodic Advertising Sync interval of the broadcast Source, {@link
+     *     BluetoothLeBroadcastMetadata#PA_SYNC_INTERVAL_UNKNOWN} if unknown.
      * @param isEncrypted whether the Broadcast Source is encrypted.
      * @param broadcastCode Broadcast Code for this Broadcast Source, null if code is not required.
      * @param sourceDevice source advertiser address.
      * @param isGroupOp {@code true} if Application wants to perform this operation for all
-     *                  coordinated set members throughout this session. Otherwise, caller
-     *                  would have to add, modify, and remove individual set members.
+     *     coordinated set members throughout this session. Otherwise, caller would have to add,
+     *     modify, and remove individual set members.
      */
-    public void addSource(@NonNull BluetoothDevice sink, int sourceAddressType,
-            int presentationDelayMicros, int sourceAdvertisingSid, int broadcastId,
-            int paSyncInterval, boolean isEncrypted, byte[] broadcastCode,
-            BluetoothDevice sourceDevice, boolean isGroupOp) {
+    public void addSource(
+            @NonNull BluetoothDevice sink,
+            int sourceAddressType,
+            int presentationDelayMicros,
+            int sourceAdvertisingSid,
+            int broadcastId,
+            int paSyncInterval,
+            boolean isEncrypted,
+            byte[] broadcastCode,
+            BluetoothDevice sourceDevice,
+            boolean isGroupOp) {
         if (DEBUG) {
             Log.d(TAG, "addSource()");
         }
-        buildMetadata(sourceAddressType, presentationDelayMicros, sourceAdvertisingSid, broadcastId,
-                paSyncInterval, isEncrypted, broadcastCode, sourceDevice);
+        buildMetadata(
+                sourceAddressType,
+                presentationDelayMicros,
+                sourceAdvertisingSid,
+                broadcastId,
+                paSyncInterval,
+                isEncrypted,
+                broadcastCode,
+                sourceDevice);
         addSource(sink, mBluetoothLeBroadcastMetadata, isGroupOp);
     }
 
-    private void buildMetadata(int sourceAddressType, int presentationDelayMicros,
-            int sourceAdvertisingSid, int broadcastId, int paSyncInterval, boolean isEncrypted,
-            byte[] broadcastCode, BluetoothDevice sourceDevice) {
+    private void buildMetadata(
+            int sourceAddressType,
+            int presentationDelayMicros,
+            int sourceAdvertisingSid,
+            int broadcastId,
+            int paSyncInterval,
+            boolean isEncrypted,
+            byte[] broadcastCode,
+            BluetoothDevice sourceDevice) {
         mBluetoothLeBroadcastMetadata =
                 mBuilder.setSourceDevice(sourceDevice, sourceAddressType)
                         .setSourceAdvertisingSid(sourceAdvertisingSid)
@@ -223,10 +261,10 @@
     /**
      * Stops an ongoing search for nearby Broadcast Sources.
      *
-     * On success, {@link BluetoothLeBroadcastAssistant.Callback#onSearchStopped(int)} will be
-     * called with reason code {@link BluetoothStatusCodes#REASON_LOCAL_APP_REQUEST}.
-     * On failure, {@link BluetoothLeBroadcastAssistant.Callback#onSearchStopFailed(int)} will be
-     * called with reason code
+     * <p>On success, {@link BluetoothLeBroadcastAssistant.Callback#onSearchStopped(int)} will be
+     * called with reason code {@link BluetoothStatusCodes#REASON_LOCAL_APP_REQUEST}. On failure,
+     * {@link BluetoothLeBroadcastAssistant.Callback#onSearchStopFailed(int)} will be called with
+     * reason code
      *
      * @throws IllegalStateException if callback was not registered
      */
@@ -245,8 +283,8 @@
      * Get information about all Broadcast Sources that a Broadcast Sink knows about.
      *
      * @param sink Broadcast Sink from which to get all Broadcast Sources
-     * @return the list of Broadcast Receive State {@link BluetoothLeBroadcastReceiveState}
-     *         stored in the Broadcast Sink
+     * @return the list of Broadcast Receive State {@link BluetoothLeBroadcastReceiveState} stored
+     *     in the Broadcast Sink
      * @throws NullPointerException when <var>sink</var> is null
      */
     public @NonNull List<BluetoothLeBroadcastReceiveState> getAllSources(
@@ -261,24 +299,50 @@
         return mService.getAllSources(sink);
     }
 
-    public void registerServiceCallBack(@NonNull @CallbackExecutor Executor executor,
+    /**
+     * Register Broadcast Assistant Callbacks to track its state and receivers
+     *
+     * @param executor Executor object for callback
+     * @param callback Callback object to be registered
+     */
+    public void registerServiceCallBack(
+            @NonNull @CallbackExecutor Executor executor,
             @NonNull BluetoothLeBroadcastAssistant.Callback callback) {
         if (mService == null) {
-            Log.d(TAG, "The BluetoothLeBroadcast is null.");
+            Log.d(
+                    TAG,
+                    "registerServiceCallBack failed, the BluetoothLeBroadcastAssistant is null.");
+            mCachedCallbackExecutorMap.putIfAbsent(callback, executor);
             return;
         }
 
-        mService.registerCallback(executor, callback);
+        try {
+            mService.registerCallback(executor, callback);
+        } catch (IllegalArgumentException e) {
+            Log.w(TAG, "registerServiceCallBack failed. " + e.getMessage());
+        }
     }
 
+    /**
+     * Unregister previously registered Broadcast Assistant Callbacks
+     *
+     * @param callback Callback object to be unregistered
+     */
     public void unregisterServiceCallBack(
             @NonNull BluetoothLeBroadcastAssistant.Callback callback) {
+        mCachedCallbackExecutorMap.remove(callback);
         if (mService == null) {
-            Log.d(TAG, "The BluetoothLeBroadcast is null.");
+            Log.d(
+                    TAG,
+                    "unregisterServiceCallBack failed, the BluetoothLeBroadcastAssistant is null.");
             return;
         }
 
-        mService.unregisterCallback(callback);
+        try {
+            mService.unregisterCallback(callback);
+        } catch (IllegalArgumentException e) {
+            Log.w(TAG, "unregisterServiceCallBack failed. " + e.getMessage());
+        }
     }
 
     public boolean isProfileReady() {
@@ -310,9 +374,11 @@
             return new ArrayList<BluetoothDevice>(0);
         }
         return mService.getDevicesMatchingConnectionStates(
-                new int[]{BluetoothProfile.STATE_CONNECTED,
-                        BluetoothProfile.STATE_CONNECTING,
-                        BluetoothProfile.STATE_DISCONNECTING});
+                new int[] {
+                    BluetoothProfile.STATE_CONNECTED,
+                    BluetoothProfile.STATE_CONNECTING,
+                    BluetoothProfile.STATE_DISCONNECTING
+                });
     }
 
     public boolean isEnabled(BluetoothDevice device) {
@@ -373,9 +439,8 @@
         }
         if (mService != null) {
             try {
-                BluetoothAdapter.getDefaultAdapter().closeProfileProxy(
-                        BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT,
-                        mService);
+                BluetoothAdapter.getDefaultAdapter()
+                        .closeProfileProxy(BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT, mService);
                 mService = null;
             } catch (Throwable t) {
                 Log.w(TAG, "Error cleaning up LeAudio proxy", t);
diff --git a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodSettingValuesWrapper.java b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodSettingValuesWrapper.java
index 5860bda..4384400 100644
--- a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodSettingValuesWrapper.java
+++ b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodSettingValuesWrapper.java
@@ -89,8 +89,14 @@
 
     public void refreshAllInputMethodAndSubtypes() {
         mMethodList.clear();
-        mMethodList.addAll(mImm.getInputMethodListAsUser(
-                mContentResolver.getUserId(), DirectBootAwareness.ANY));
+        List<InputMethodInfo> imis = mImm.getInputMethodListAsUser(
+                mContentResolver.getUserId(), DirectBootAwareness.ANY);
+        for (int i = 0; i < imis.size(); ++i) {
+            InputMethodInfo imi = imis.get(i);
+            if (!imi.isVirtualDeviceOnly()) {
+                mMethodList.add(imi);
+            }
+        }
     }
 
     public List<InputMethodInfo> getInputMethodList() {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SettingsJankMonitorTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SettingsJankMonitorTest.java
index 25833b3..5aee8cd 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SettingsJankMonitorTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SettingsJankMonitorTest.java
@@ -16,7 +16,7 @@
 
 package com.android.settingslib.core.instrumentation;
 
-import static com.android.internal.jank.InteractionJankMonitor.CUJ_SETTINGS_TOGGLE;
+import static com.android.internal.jank.Cuj.CUJ_SETTINGS_TOGGLE;
 import static com.android.settingslib.core.instrumentation.SettingsJankMonitor.MONITORED_ANIMATION_DURATION_MS;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -34,8 +34,8 @@
 import androidx.preference.SwitchPreference;
 import androidx.recyclerview.widget.RecyclerView;
 
+import com.android.internal.jank.Cuj.CujType;
 import com.android.internal.jank.InteractionJankMonitor;
-import com.android.internal.jank.InteractionJankMonitor.CujType;
 import com.android.settingslib.testutils.OverpoweredReflectionHelper;
 import com.android.settingslib.testutils.shadow.ShadowInteractionJankMonitor;
 
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index 5c09b16..2167a8a 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -73,6 +73,8 @@
         Settings.Secure.TTS_ENABLED_PLUGINS,
         Settings.Secure.TTS_DEFAULT_LOCALE,
         Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD,
+        Settings.Secure.ACCESSIBILITY_BOUNCE_KEYS,
+        Settings.Secure.ACCESSIBILITY_STICKY_KEYS,
         Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,            // moved to global
         Settings.Secure.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY,               // moved to global
         Settings.Secure.WIFI_NUM_OPEN_NETWORKS_KEPT,                        // moved to global
@@ -105,6 +107,9 @@
         Settings.Secure.CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED,
         Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED,
         Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED,
+        // ACCESSIBILITY_QS_TARGETS needs to be restored after ENABLED_ACCESSIBILITY_SERVICES
+        // but before QS_TILES
+        Settings.Secure.ACCESSIBILITY_QS_TARGETS,
         Settings.Secure.QS_TILES,
         Settings.Secure.QS_AUTO_ADDED_TILES,
         Settings.Secure.CONTROLS_ENABLED,
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index b0169a1..868623f 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -119,6 +119,8 @@
         VALIDATORS.put(Secure.TTS_ENABLED_PLUGINS, new PackageNameListValidator(" "));
         VALIDATORS.put(Secure.TTS_DEFAULT_LOCALE, TTS_LIST_VALIDATOR);
         VALIDATORS.put(Secure.SHOW_IME_WITH_HARD_KEYBOARD, BOOLEAN_VALIDATOR);
+        VALIDATORS.put(Secure.ACCESSIBILITY_BOUNCE_KEYS, ANY_INTEGER_VALIDATOR);
+        VALIDATORS.put(Secure.ACCESSIBILITY_STICKY_KEYS, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, NON_NEGATIVE_INTEGER_VALIDATOR);
         VALIDATORS.put(Secure.WIFI_NUM_OPEN_NETWORKS_KEPT, NON_NEGATIVE_INTEGER_VALIDATOR);
@@ -319,6 +321,9 @@
         VALIDATORS.put(
                 Secure.ACCESSIBILITY_BUTTON_TARGETS,
                 ACCESSIBILITY_SHORTCUT_TARGET_LIST_VALIDATOR);
+        VALIDATORS.put(
+                Secure.ACCESSIBILITY_QS_TARGETS,
+                ACCESSIBILITY_SHORTCUT_TARGET_LIST_VALIDATOR);
         VALIDATORS.put(Secure.ACCESSIBILITY_FORCE_INVERT_COLOR_ENABLED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.ONE_HANDED_MODE_ACTIVATED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.ONE_HANDED_MODE_ENABLED, BOOLEAN_VALIDATOR);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index a978889..5afcd5d 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1813,6 +1813,9 @@
                 Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
                 SecureSettingsProto.Accessibility.BUTTON_TARGETS);
         dumpSetting(s, p,
+                Settings.Secure.ACCESSIBILITY_QS_TARGETS,
+                SecureSettingsProto.Accessibility.QS_TARGETS);
+        dumpSetting(s, p,
                 Settings.Secure.ACCESSIBILITY_MAGNIFICATION_CAPABILITY,
                 SecureSettingsProto.Accessibility.ACCESSIBILITY_MAGNIFICATION_CAPABILITY);
         dumpSetting(s, p,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index 7cec99d..8f459c6 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -95,7 +95,9 @@
 
     static final int SETTINGS_VERSION_NEW_ENCODING = 121;
 
+    // LINT.IfChange
     public static final int MAX_LENGTH_PER_STRING = 32768;
+    // LINT.ThenChange(/services/core/java/com/android/server/audio/AudioDeviceInventory.java:settings_max_length_per_string)
     private static final long WRITE_SETTINGS_DELAY_MILLIS = 200;
     private static final long MAX_WRITE_SETTINGS_DELAY_MILLIS = 2000;
 
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index d12d9d6..6e65c16 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -879,6 +879,12 @@
 
     <uses-permission android:name="android.permission.GET_BINDING_UID_IMPORTANCE" />
 
+    <!-- Permissions required for CTS test - CtsAccessibilityServiceTestCases-->
+    <uses-permission android:name="android.permission.ACCESSIBILITY_MOTION_EVENT_OBSERVING" />
+
+    <!-- Permission required for Cts test - CtsNotificationTestCases -->
+    <uses-permission android:name="android.permission.RECEIVE_SENSITIVE_NOTIFICATIONS" />
+
     <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 c2c5e00..f10ac1b 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -204,6 +204,7 @@
         "lottie",
         "LowLightDreamLib",
         "motion_tool_lib",
+        "notification_flags_lib",
     ],
     libs: [
         "keepanno-annotations",
@@ -281,6 +282,7 @@
         "com_android_systemui_flags_lib",
         "com_android_systemui_shared_flags_lib",
         "flag-junit-base",
+        "platform-parametric-runner-lib",
         "androidx.viewpager2_viewpager2",
         "androidx.legacy_legacy-support-v4",
         "androidx.recyclerview_recyclerview",
@@ -327,6 +329,7 @@
         "androidx.compose.ui_ui",
         "flag-junit",
         "platform-test-annotations",
+        "notification_flags_lib",
     ],
 }
 
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index f1029a3..1a35f04 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -238,6 +238,7 @@
     <uses-permission android:name="android.permission.MANAGE_NOTIFICATIONS" />
     <uses-permission android:name="android.permission.GET_RUNTIME_PERMISSIONS" />
     <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
+    <uses-permission android:name="android.permission.RECEIVE_SENSITIVE_NOTIFICATIONS" />
 
     <!-- role holder APIs -->
     <uses-permission android:name="android.permission.MANAGE_ROLE_HOLDERS" />
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/Android.bp b/packages/SystemUI/accessibility/accessibilitymenu/Android.bp
index 8b12f3c..6c75b434 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/Android.bp
+++ b/packages/SystemUI/accessibility/accessibilitymenu/Android.bp
@@ -59,6 +59,4 @@
     platform_apis: true,
     resource_dirs: ["res"],
     certificate: "platform",
-    // This app uses allowlisted privileged permissions.
-    privileged: true,
 }
diff --git a/packages/SystemUI/aconfig/Android.bp b/packages/SystemUI/aconfig/Android.bp
index e842967..50ed7ab 100644
--- a/packages/SystemUI/aconfig/Android.bp
+++ b/packages/SystemUI/aconfig/Android.bp
@@ -23,6 +23,7 @@
     default_visibility: [
         "//visibility:override",
         "//frameworks/base/packages/SystemUI:__subpackages__",
+        "//platform_testing:__subpackages__"
     ],
 }
 
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index c52a89c..facb244 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -61,6 +61,13 @@
 }
 
 flag {
+    name: "refactor_get_current_user"
+    namespace: "systemui"
+    description: "KeyguardUpdateMonitor.getCurrentUser() was providing outdated results."
+    bug: "305984787"
+}
+
+flag {
     name: "notification_throttle_hun"
     namespace: "systemui"
     description: "During notification avalanche, throttle HUNs showing in fast succession."
@@ -138,6 +145,13 @@
 }
 
 flag {
+   name: "qs_new_tiles"
+   namespace: "systemui"
+   description: "Use the new tiles in the Quick Settings. Should have no behavior changes."
+   bug: "241772429"
+}
+
+flag {
     name: "coroutine_tracing"
     namespace: "systemui"
     description: "Adds thread-local data to System UI's global coroutine scopes to "
@@ -204,6 +218,13 @@
 }
 
 flag {
+  name: "enable_layout_tracing"
+  namespace: "systemui"
+  description: "Enables detailed traversal slices during measure and layout in perfetto traces"
+  bug: "315274804"
+}
+
+flag {
    name: "quick_settings_visual_haptics_longpress"
    namespace: "systemui"
    description: "Enable special visual and haptic effects for quick settings tiles with long-press actions"
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
index f7d9056c3..9c46ebdc 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
@@ -21,7 +21,6 @@
 import android.app.PendingIntent
 import android.app.TaskInfo
 import android.graphics.Matrix
-import android.graphics.Path
 import android.graphics.Rect
 import android.graphics.RectF
 import android.os.Build
@@ -37,7 +36,6 @@
 import android.view.View
 import android.view.ViewGroup
 import android.view.WindowManager
-import android.view.animation.Interpolator
 import android.view.animation.PathInterpolator
 import androidx.annotation.AnyThread
 import androidx.annotation.BinderThread
@@ -93,7 +91,7 @@
         val INTERPOLATORS =
             LaunchAnimator.Interpolators(
                 positionInterpolator = Interpolators.EMPHASIZED,
-                positionXInterpolator = createPositionXInterpolator(),
+                positionXInterpolator = Interpolators.EMPHASIZED_COMPLEMENT,
                 contentBeforeFadeOutInterpolator = Interpolators.LINEAR_OUT_SLOW_IN,
                 contentAfterFadeInInterpolator = PathInterpolator(0f, 0f, 0.6f, 1f)
             )
@@ -121,16 +119,6 @@
          * cancelled by WM.
          */
         private const val LONG_LAUNCH_TIMEOUT = 5_000L
-
-        private fun createPositionXInterpolator(): Interpolator {
-            val path =
-                Path().apply {
-                    moveTo(0f, 0f)
-                    cubicTo(0.1217f, 0.0462f, 0.15f, 0.4686f, 0.1667f, 0.66f)
-                    cubicTo(0.1834f, 0.8878f, 0.1667f, 1f, 1f, 1f)
-                }
-            return PathInterpolator(path)
-        }
     }
 
     /**
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
index 187d073..168039e 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
@@ -33,8 +33,8 @@
 import android.view.WindowManager
 import android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
 import com.android.app.animation.Interpolators
+import com.android.internal.jank.Cuj.CujType
 import com.android.internal.jank.InteractionJankMonitor
-import com.android.internal.jank.InteractionJankMonitor.CujType
 import com.android.systemui.util.maybeForceFullscreen
 import com.android.systemui.util.registerAnimationOnBackInvoked
 import kotlin.math.roundToInt
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt
index af35ea4..b738e2b 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt
@@ -33,6 +33,7 @@
 import android.view.ViewGroup
 import android.view.ViewGroupOverlay
 import android.widget.FrameLayout
+import com.android.internal.jank.Cuj.CujType
 import com.android.internal.jank.InteractionJankMonitor
 import java.util.LinkedList
 import kotlin.math.min
@@ -58,7 +59,7 @@
     /** The view that will be ghosted and from which the background will be extracted. */
     private val ghostedView: View,
 
-    /** The [InteractionJankMonitor.CujType] associated to this animation. */
+    /** The [CujType] associated to this animation. */
     private val cujType: Int? = null,
     private var interactionJankMonitor: InteractionJankMonitor =
         InteractionJankMonitor.getInstance(),
diff --git a/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/compose/ComposeFacade.kt b/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/compose/ComposeFacade.kt
index 914e5f2..fd04b5ee0 100644
--- a/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/compose/ComposeFacade.kt
+++ b/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/compose/ComposeFacade.kt
@@ -51,6 +51,7 @@
         activity: ComponentActivity,
         viewModel: BaseCommunalViewModel,
         onOpenWidgetPicker: () -> Unit,
+        onEditDone: () -> Unit,
     ) {
         throwComposeUnavailableError()
     }
diff --git a/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeFacade.kt b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeFacade.kt
index 59bd95b..5055ee1 100644
--- a/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeFacade.kt
+++ b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeFacade.kt
@@ -66,12 +66,14 @@
         activity: ComponentActivity,
         viewModel: BaseCommunalViewModel,
         onOpenWidgetPicker: () -> Unit,
+        onEditDone: () -> Unit,
     ) {
         activity.setContent {
             PlatformTheme {
                 CommunalHub(
                     viewModel = viewModel,
                     onOpenWidgetPicker = onOpenWidgetPicker,
+                    onEditDone = onEditDone,
                 )
             }
         }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt
index 1a653c3..1d7c7d63 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+@file:OptIn(ExperimentalFoundationApi::class)
+
 package com.android.systemui.bouncer.ui.composable
 
 import android.app.AlertDialog
@@ -29,18 +31,17 @@
 import androidx.compose.foundation.gestures.detectTapGestures
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.BoxScope
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.aspectRatio
 import androidx.compose.foundation.layout.fillMaxHeight
-import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.imePadding
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.layout.width
-import androidx.compose.foundation.layout.widthIn
 import androidx.compose.foundation.shape.RoundedCornerShape
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.KeyboardArrowDown
@@ -51,6 +52,7 @@
 import androidx.compose.material3.Icon
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Text
+import androidx.compose.material3.windowsizeclass.WindowHeightSizeClass
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.collectAsState
 import androidx.compose.runtime.getValue
@@ -78,6 +80,7 @@
 import com.android.compose.animation.scene.SceneTransitionLayout
 import com.android.compose.animation.scene.transitions
 import com.android.compose.modifiers.thenIf
+import com.android.compose.windowsizeclass.LocalWindowSizeClass
 import com.android.systemui.bouncer.shared.model.BouncerActionButtonModel
 import com.android.systemui.bouncer.ui.helper.BouncerSceneLayout
 import com.android.systemui.bouncer.ui.viewmodel.AuthMethodBouncerViewModel
@@ -100,37 +103,41 @@
     dialogFactory: BouncerDialogFactory,
     modifier: Modifier = Modifier,
 ) {
-    val isFullScreenUserSwitcherEnabled = viewModel.isUserSwitcherVisible
     val isSideBySideSupported by viewModel.isSideBySideSupported.collectAsState()
     val layout = calculateLayout(isSideBySideSupported = isSideBySideSupported)
 
-    when (layout) {
-        BouncerSceneLayout.STANDARD ->
-            StandardLayout(
-                viewModel = viewModel,
-                dialogFactory = dialogFactory,
-                modifier = modifier,
-            )
-        BouncerSceneLayout.SIDE_BY_SIDE ->
-            SideBySideLayout(
-                viewModel = viewModel,
-                dialogFactory = dialogFactory,
-                isUserSwitcherVisible = isFullScreenUserSwitcherEnabled,
-                modifier = modifier,
-            )
-        BouncerSceneLayout.STACKED ->
-            StackedLayout(
-                viewModel = viewModel,
-                dialogFactory = dialogFactory,
-                isUserSwitcherVisible = isFullScreenUserSwitcherEnabled,
-                modifier = modifier,
-            )
-        BouncerSceneLayout.SPLIT ->
-            SplitLayout(
-                viewModel = viewModel,
-                dialogFactory = dialogFactory,
-                modifier = modifier,
-            )
+    Box(
+        // Allows the content within each of the layouts to react to the appearance and
+        // disappearance of the IME, which is also known as the software keyboard.
+        //
+        // Despite the keyboard only being part of the password bouncer, adding it at this level is
+        // both necessary to properly handle the keyboard in all layouts and harmless in cases when
+        // the keyboard isn't used (like the PIN or pattern auth methods).
+        modifier = modifier.imePadding(),
+    ) {
+        when (layout) {
+            BouncerSceneLayout.STANDARD_BOUNCER ->
+                StandardLayout(
+                    viewModel = viewModel,
+                )
+            BouncerSceneLayout.BESIDE_USER_SWITCHER ->
+                BesideUserSwitcherLayout(
+                    viewModel = viewModel,
+                )
+            BouncerSceneLayout.BELOW_USER_SWITCHER ->
+                BelowUserSwitcherLayout(
+                    viewModel = viewModel,
+                )
+            BouncerSceneLayout.SPLIT_BOUNCER ->
+                SplitLayout(
+                    viewModel = viewModel,
+                )
+        }
+
+        Dialog(
+            viewModel = viewModel,
+            dialogFactory = dialogFactory,
+        )
     }
 }
 
@@ -141,15 +148,330 @@
 @Composable
 private fun StandardLayout(
     viewModel: BouncerViewModel,
-    dialogFactory: BouncerDialogFactory,
     modifier: Modifier = Modifier,
-    layout: BouncerSceneLayout = BouncerSceneLayout.STANDARD,
-    outputOnly: Boolean = false,
+) {
+    val isHeightExpanded =
+        LocalWindowSizeClass.current.heightSizeClass == WindowHeightSizeClass.Expanded
+
+    FoldAware(
+        modifier =
+            modifier.padding(
+                top = 92.dp,
+                bottom = 48.dp,
+            ),
+        viewModel = viewModel,
+        aboveFold = {
+            Column(
+                horizontalAlignment = Alignment.CenterHorizontally,
+                modifier = Modifier.fillMaxWidth(),
+            ) {
+                StatusMessage(
+                    viewModel = viewModel,
+                    modifier = Modifier,
+                )
+
+                OutputArea(
+                    viewModel = viewModel,
+                    modifier = Modifier.padding(top = if (isHeightExpanded) 96.dp else 64.dp),
+                )
+            }
+        },
+        belowFold = {
+            Column(
+                horizontalAlignment = Alignment.CenterHorizontally,
+                modifier = Modifier.fillMaxWidth(),
+            ) {
+                Box(
+                    modifier = Modifier.weight(1f),
+                ) {
+                    InputArea(
+                        viewModel = viewModel,
+                        pinButtonRowVerticalSpacing = 12.dp,
+                        centerPatternDotsVertically = false,
+                        modifier = Modifier.align(Alignment.BottomCenter),
+                    )
+                }
+
+                ActionArea(
+                    viewModel = viewModel,
+                    modifier = Modifier.padding(top = 48.dp),
+                )
+            }
+        },
+    )
+}
+
+/**
+ * Renders the bouncer UI in split mode, with half on one side and half on the other side, swappable
+ * by double-tapping on the side.
+ */
+@Composable
+private fun SplitLayout(
+    viewModel: BouncerViewModel,
+    modifier: Modifier = Modifier,
+) {
+    val authMethod by viewModel.authMethodViewModel.collectAsState()
+
+    Row(
+        modifier =
+            modifier
+                .fillMaxHeight()
+                .padding(
+                    horizontal = 24.dp,
+                    vertical = if (authMethod is PasswordBouncerViewModel) 24.dp else 48.dp,
+                ),
+    ) {
+        // Left side (in left-to-right locales).
+        Box(
+            modifier = Modifier.fillMaxHeight().weight(1f),
+        ) {
+            when (authMethod) {
+                is PinBouncerViewModel -> {
+                    StatusMessage(
+                        viewModel = viewModel,
+                        modifier = Modifier.align(Alignment.TopCenter),
+                    )
+
+                    OutputArea(viewModel = viewModel, modifier = Modifier.align(Alignment.Center))
+
+                    ActionArea(
+                        viewModel = viewModel,
+                        modifier = Modifier.align(Alignment.BottomCenter).padding(top = 48.dp),
+                    )
+                }
+                is PatternBouncerViewModel -> {
+                    StatusMessage(
+                        viewModel = viewModel,
+                        modifier = Modifier.align(Alignment.TopCenter),
+                    )
+
+                    ActionArea(
+                        viewModel = viewModel,
+                        modifier = Modifier.align(Alignment.BottomCenter).padding(vertical = 48.dp),
+                    )
+                }
+                is PasswordBouncerViewModel -> {
+                    ActionArea(
+                        viewModel = viewModel,
+                        modifier = Modifier.align(Alignment.BottomCenter),
+                    )
+                }
+                else -> Unit
+            }
+        }
+
+        // Right side (in right-to-left locales).
+        Box(
+            modifier = Modifier.fillMaxHeight().weight(1f),
+        ) {
+            when (authMethod) {
+                is PinBouncerViewModel,
+                is PatternBouncerViewModel -> {
+                    InputArea(
+                        viewModel = viewModel,
+                        pinButtonRowVerticalSpacing = 8.dp,
+                        centerPatternDotsVertically = true,
+                        modifier = Modifier.align(Alignment.Center),
+                    )
+                }
+                is PasswordBouncerViewModel -> {
+                    Column(
+                        horizontalAlignment = Alignment.CenterHorizontally,
+                        modifier = Modifier.fillMaxWidth().align(Alignment.Center),
+                    ) {
+                        StatusMessage(
+                            viewModel = viewModel,
+                        )
+
+                        OutputArea(viewModel = viewModel, modifier = Modifier.padding(top = 24.dp))
+                    }
+                }
+                else -> Unit
+            }
+        }
+    }
+}
+
+/**
+ * Arranges the bouncer contents and user switcher contents side-by-side, supporting a double tap
+ * anywhere on the background to flip their positions.
+ */
+@Composable
+private fun BesideUserSwitcherLayout(
+    viewModel: BouncerViewModel,
+    modifier: Modifier = Modifier,
+) {
+    val layoutDirection = LocalLayoutDirection.current
+    val isLeftToRight = layoutDirection == LayoutDirection.Ltr
+    val (isSwapped, setSwapped) = rememberSaveable(isLeftToRight) { mutableStateOf(!isLeftToRight) }
+    val isHeightExpanded =
+        LocalWindowSizeClass.current.heightSizeClass == WindowHeightSizeClass.Expanded
+    val authMethod by viewModel.authMethodViewModel.collectAsState()
+
+    Row(
+        modifier =
+            modifier
+                .pointerInput(Unit) {
+                    detectTapGestures(
+                        onDoubleTap = { offset ->
+                            // Depending on where the user double tapped, switch the elements such
+                            // that the non-swapped element is closer to the side that was double
+                            // tapped.
+                            setSwapped(offset.x < size.width / 2)
+                        }
+                    )
+                }
+                .padding(
+                    top = if (isHeightExpanded) 128.dp else 96.dp,
+                    bottom = if (isHeightExpanded) 128.dp else 48.dp,
+                ),
+    ) {
+        val animatedOffset by
+            animateFloatAsState(
+                targetValue =
+                    if (!isSwapped) {
+                        // A non-swapped element has its natural placement so it's not offset.
+                        0f
+                    } else if (isLeftToRight) {
+                        // A swapped element has its elements offset horizontally. In the case of
+                        // LTR locales, this means pushing the element to the right, hence the
+                        // positive number.
+                        1f
+                    } else {
+                        // A swapped element has its elements offset horizontally. In the case of
+                        // RTL locales, this means pushing the element to the left, hence the
+                        // negative number.
+                        -1f
+                    },
+                label = "offset",
+            )
+
+        fun Modifier.swappable(inversed: Boolean = false): Modifier {
+            return graphicsLayer {
+                translationX =
+                    size.width *
+                        animatedOffset *
+                        if (inversed) {
+                            // A negative sign is used to make sure this is offset in the direction
+                            // that's opposite to the direction that the user switcher is pushed in.
+                            -1
+                        } else {
+                            1
+                        }
+                alpha = animatedAlpha(animatedOffset)
+            }
+        }
+
+        UserSwitcher(
+            viewModel = viewModel,
+            modifier = Modifier.weight(1f).swappable(),
+        )
+
+        FoldAware(
+            modifier = Modifier.weight(1f).swappable(inversed = true),
+            viewModel = viewModel,
+            aboveFold = {
+                Column(
+                    horizontalAlignment = Alignment.CenterHorizontally,
+                    modifier = Modifier.fillMaxWidth()
+                ) {
+                    StatusMessage(
+                        viewModel = viewModel,
+                    )
+
+                    OutputArea(viewModel = viewModel, modifier = Modifier.padding(top = 24.dp))
+                }
+            },
+            belowFold = {
+                Column(
+                    horizontalAlignment = Alignment.CenterHorizontally,
+                    modifier = Modifier.fillMaxWidth(),
+                ) {
+                    val isOutputAreaVisible = authMethod !is PatternBouncerViewModel
+                    // If there is an output area and the window is not tall enough, spacing needs
+                    // to be added between the input and the output areas (otherwise the two get
+                    // very squished together).
+                    val addSpacingBetweenOutputAndInput = isOutputAreaVisible && !isHeightExpanded
+
+                    Box(
+                        modifier =
+                            Modifier.weight(1f)
+                                .padding(top = (if (addSpacingBetweenOutputAndInput) 24 else 0).dp),
+                    ) {
+                        InputArea(
+                            viewModel = viewModel,
+                            pinButtonRowVerticalSpacing = 12.dp,
+                            centerPatternDotsVertically = true,
+                            modifier = Modifier.align(Alignment.BottomCenter),
+                        )
+                    }
+
+                    ActionArea(
+                        viewModel = viewModel,
+                        modifier = Modifier.padding(top = 48.dp),
+                    )
+                }
+            },
+        )
+    }
+}
+
+/** Arranges the bouncer contents and user switcher contents one on top of the other, vertically. */
+@Composable
+private fun BelowUserSwitcherLayout(
+    viewModel: BouncerViewModel,
+    modifier: Modifier = Modifier,
+) {
+    Column(
+        modifier =
+            modifier.padding(
+                vertical = 128.dp,
+            )
+    ) {
+        UserSwitcher(
+            viewModel = viewModel,
+            modifier = Modifier.fillMaxWidth(),
+        )
+
+        Spacer(Modifier.weight(1f))
+
+        Box(modifier = Modifier.fillMaxWidth()) {
+            Column(
+                horizontalAlignment = Alignment.CenterHorizontally,
+                modifier = Modifier.fillMaxWidth(),
+            ) {
+                StatusMessage(
+                    viewModel = viewModel,
+                )
+
+                OutputArea(viewModel = viewModel, modifier = Modifier.padding(top = 24.dp))
+
+                InputArea(
+                    viewModel = viewModel,
+                    pinButtonRowVerticalSpacing = 12.dp,
+                    centerPatternDotsVertically = true,
+                    modifier = Modifier.padding(top = 128.dp),
+                )
+
+                ActionArea(
+                    viewModel = viewModel,
+                    modifier = Modifier.padding(top = 48.dp),
+                )
+            }
+        }
+    }
+}
+
+@Composable
+private fun FoldAware(
+    viewModel: BouncerViewModel,
+    aboveFold: @Composable BoxScope.() -> Unit,
+    belowFold: @Composable BoxScope.() -> Unit,
+    modifier: Modifier = Modifier,
 ) {
     val foldPosture: FoldPosture by foldPosture()
     val isSplitAroundTheFoldRequired by viewModel.isFoldSplitRequired.collectAsState()
-    val isSplitAroundTheFold =
-        foldPosture == FoldPosture.Tabletop && !outputOnly && isSplitAroundTheFoldRequired
+    val isSplitAroundTheFold = foldPosture == FoldPosture.Tabletop && isSplitAroundTheFoldRequired
     val currentSceneKey =
         if (isSplitAroundTheFold) SceneKeys.SplitSceneKey else SceneKeys.ContiguousSceneKey
 
@@ -160,115 +482,57 @@
         modifier = modifier,
     ) {
         scene(SceneKeys.ContiguousSceneKey) {
-            FoldSplittable(
-                viewModel = viewModel,
-                dialogFactory = dialogFactory,
-                layout = layout,
-                outputOnly = outputOnly,
+            FoldableScene(
+                aboveFold = aboveFold,
+                belowFold = belowFold,
                 isSplit = false,
             )
         }
 
         scene(SceneKeys.SplitSceneKey) {
-            FoldSplittable(
-                viewModel = viewModel,
-                dialogFactory = dialogFactory,
-                layout = layout,
-                outputOnly = outputOnly,
+            FoldableScene(
+                aboveFold = aboveFold,
+                belowFold = belowFold,
                 isSplit = true,
             )
         }
     }
 }
 
-/**
- * Renders the "standard" layout of the bouncer, where the bouncer is rendered on its own (no user
- * switcher UI) and laid out vertically, centered horizontally.
- *
- * If [isSplit] is `true`, the top and bottom parts of the bouncer are split such that they don't
- * render across the location of the fold hardware when the device is fully or part-way unfolded
- * with the fold hinge in a horizontal position.
- *
- * If [outputOnly] is `true`, only the "output" part of the UI is shown (where the entered PIN
- * "shapes" appear), if `false`, the entire UI is shown, including the area where the user can enter
- * their PIN or pattern.
- */
 @Composable
-private fun SceneScope.FoldSplittable(
-    viewModel: BouncerViewModel,
-    dialogFactory: BouncerDialogFactory,
-    layout: BouncerSceneLayout,
-    outputOnly: Boolean,
+private fun SceneScope.FoldableScene(
+    aboveFold: @Composable BoxScope.() -> Unit,
+    belowFold: @Composable BoxScope.() -> Unit,
     isSplit: Boolean,
     modifier: Modifier = Modifier,
 ) {
-    val message: BouncerViewModel.MessageViewModel by viewModel.message.collectAsState()
-    val dialogMessage: String? by viewModel.throttlingDialogMessage.collectAsState()
-    var dialog: Dialog? by remember { mutableStateOf(null) }
-    val actionButton: BouncerActionButtonModel? by viewModel.actionButton.collectAsState()
     val splitRatio =
         LocalContext.current.resources.getFloat(
             R.dimen.motion_layout_half_fold_bouncer_height_ratio
         )
 
-    Column(modifier = modifier.padding(horizontal = 32.dp)) {
+    Column(
+        modifier = modifier.fillMaxHeight(),
+    ) {
         // Content above the fold, when split on a foldable device in a "table top" posture:
         Box(
             modifier =
                 Modifier.element(SceneElements.AboveFold)
-                    .fillMaxWidth()
                     .then(
                         if (isSplit) {
                             Modifier.weight(splitRatio)
-                        } else if (outputOnly) {
-                            Modifier.fillMaxHeight()
                         } else {
                             Modifier
                         }
                     ),
         ) {
-            Column(
-                horizontalAlignment = Alignment.CenterHorizontally,
-                modifier = Modifier.fillMaxWidth().padding(top = layout.topPadding),
-            ) {
-                Crossfade(
-                    targetState = message,
-                    label = "Bouncer message",
-                    animationSpec = if (message.isUpdateAnimated) tween() else snap(),
-                ) { message ->
-                    Text(
-                        text = message.text,
-                        color = MaterialTheme.colorScheme.onSurface,
-                        style = MaterialTheme.typography.bodyLarge,
-                    )
-                }
-
-                if (!outputOnly) {
-                    Spacer(Modifier.height(layout.spacingBetweenMessageAndEnteredInput))
-
-                    UserInputArea(
-                        viewModel = viewModel,
-                        visibility = UserInputAreaVisibility.OUTPUT_ONLY,
-                        layout = layout,
-                    )
-                }
-            }
-
-            if (outputOnly) {
-                UserInputArea(
-                    viewModel = viewModel,
-                    visibility = UserInputAreaVisibility.OUTPUT_ONLY,
-                    layout = layout,
-                    modifier = Modifier.align(Alignment.Center),
-                )
-            }
+            aboveFold()
         }
 
         // Content below the fold, when split on a foldable device in a "table top" posture:
         Box(
             modifier =
                 Modifier.element(SceneElements.BelowFold)
-                    .fillMaxWidth()
                     .weight(
                         if (isSplit) {
                             1 - splitRatio
@@ -277,73 +541,40 @@
                         }
                     ),
         ) {
-            Column(
-                horizontalAlignment = Alignment.CenterHorizontally,
-                modifier = Modifier.fillMaxSize()
-            ) {
-                if (!outputOnly) {
-                    Box(Modifier.weight(1f)) {
-                        UserInputArea(
-                            viewModel = viewModel,
-                            visibility = UserInputAreaVisibility.INPUT_ONLY,
-                            layout = layout,
-                            modifier = Modifier.align(Alignment.BottomCenter),
-                        )
-                    }
-                }
-
-                Spacer(Modifier.height(48.dp))
-
-                val actionButtonModifier = Modifier.height(56.dp)
-
-                actionButton.let { actionButtonViewModel ->
-                    if (actionButtonViewModel != null) {
-                        BouncerActionButton(
-                            viewModel = actionButtonViewModel,
-                            modifier = actionButtonModifier,
-                        )
-                    } else {
-                        Spacer(modifier = actionButtonModifier)
-                    }
-                }
-
-                Spacer(Modifier.height(layout.bottomPadding))
-            }
-        }
-
-        if (dialogMessage != null) {
-            if (dialog == null) {
-                dialog =
-                    dialogFactory().apply {
-                        setMessage(dialogMessage)
-                        setButton(
-                            DialogInterface.BUTTON_NEUTRAL,
-                            context.getString(R.string.ok),
-                        ) { _, _ ->
-                            viewModel.onThrottlingDialogDismissed()
-                        }
-                        setCancelable(false)
-                        setCanceledOnTouchOutside(false)
-                        show()
-                    }
-            }
-        } else {
-            dialog?.dismiss()
-            dialog = null
+            belowFold()
         }
     }
 }
 
+@Composable
+private fun StatusMessage(
+    viewModel: BouncerViewModel,
+    modifier: Modifier = Modifier,
+) {
+    val message: BouncerViewModel.MessageViewModel by viewModel.message.collectAsState()
+
+    Crossfade(
+        targetState = message,
+        label = "Bouncer message",
+        animationSpec = if (message.isUpdateAnimated) tween() else snap(),
+        modifier = modifier,
+    ) {
+        Text(
+            text = it.text,
+            color = MaterialTheme.colorScheme.onSurface,
+            style = MaterialTheme.typography.bodyLarge,
+        )
+    }
+}
+
 /**
- * Renders the user input area, where the user interacts with the UI to enter their credentials.
+ * Renders the user output area, where the user sees what they entered.
  *
- * For example, this can be the pattern input area, the password text box, or pin pad.
+ * For example, this can be the PIN shapes or password text field.
  */
 @Composable
-private fun UserInputArea(
+private fun OutputArea(
     viewModel: BouncerViewModel,
-    visibility: UserInputAreaVisibility,
-    layout: BouncerSceneLayout,
     modifier: Modifier = Modifier,
 ) {
     val authMethodViewModel: AuthMethodBouncerViewModel? by
@@ -351,66 +582,115 @@
 
     when (val nonNullViewModel = authMethodViewModel) {
         is PinBouncerViewModel ->
-            when (visibility) {
-                UserInputAreaVisibility.OUTPUT_ONLY ->
-                    PinInputDisplay(
-                        viewModel = nonNullViewModel,
-                        modifier = modifier,
-                    )
-                UserInputAreaVisibility.INPUT_ONLY ->
-                    PinPad(
-                        viewModel = nonNullViewModel,
-                        layout = layout,
-                        modifier = modifier,
-                    )
-            }
+            PinInputDisplay(
+                viewModel = nonNullViewModel,
+                modifier = modifier,
+            )
         is PasswordBouncerViewModel ->
-            if (visibility == UserInputAreaVisibility.INPUT_ONLY) {
-                PasswordBouncer(
-                    viewModel = nonNullViewModel,
-                    modifier = modifier,
-                )
-            }
-        is PatternBouncerViewModel ->
-            if (visibility == UserInputAreaVisibility.INPUT_ONLY) {
-                PatternBouncer(
-                    viewModel = nonNullViewModel,
-                    layout = layout,
-                    modifier = modifier.aspectRatio(1f, matchHeightConstraintsFirst = false),
-                )
-            }
+            PasswordBouncer(
+                viewModel = nonNullViewModel,
+                modifier = modifier,
+            )
         else -> Unit
     }
 }
 
 /**
- * Renders the action button on the bouncer, which triggers either Return to Call or Emergency Call.
+ * Renders the user input area, where the user enters their credentials.
+ *
+ * For example, this can be the pattern input area or the PIN pad.
  */
-@OptIn(ExperimentalFoundationApi::class)
 @Composable
-private fun BouncerActionButton(
-    viewModel: BouncerActionButtonModel,
+private fun InputArea(
+    viewModel: BouncerViewModel,
+    pinButtonRowVerticalSpacing: Dp,
+    centerPatternDotsVertically: Boolean,
     modifier: Modifier = Modifier,
 ) {
-    Button(
-        onClick = viewModel.onClick,
-        modifier =
-            modifier.thenIf(viewModel.onLongClick != null) {
-                Modifier.combinedClickable(
-                    onClick = viewModel.onClick,
-                    onLongClick = viewModel.onLongClick,
+    val authMethodViewModel: AuthMethodBouncerViewModel? by
+        viewModel.authMethodViewModel.collectAsState()
+
+    when (val nonNullViewModel = authMethodViewModel) {
+        is PinBouncerViewModel -> {
+            PinPad(
+                viewModel = nonNullViewModel,
+                verticalSpacing = pinButtonRowVerticalSpacing,
+                modifier = modifier,
+            )
+        }
+        is PatternBouncerViewModel -> {
+            PatternBouncer(
+                viewModel = nonNullViewModel,
+                centerDotsVertically = centerPatternDotsVertically,
+                modifier = modifier,
+            )
+        }
+        else -> Unit
+    }
+}
+
+@Composable
+private fun ActionArea(
+    viewModel: BouncerViewModel,
+    modifier: Modifier = Modifier,
+) {
+    val actionButton: BouncerActionButtonModel? by viewModel.actionButton.collectAsState()
+
+    actionButton?.let { actionButtonViewModel ->
+        Box(
+            modifier = modifier,
+        ) {
+            Button(
+                onClick = actionButtonViewModel.onClick,
+                modifier =
+                    Modifier.height(56.dp).thenIf(actionButtonViewModel.onLongClick != null) {
+                        Modifier.combinedClickable(
+                            onClick = actionButtonViewModel.onClick,
+                            onLongClick = actionButtonViewModel.onLongClick,
+                        )
+                    },
+                colors =
+                    ButtonDefaults.buttonColors(
+                        containerColor = MaterialTheme.colorScheme.tertiaryContainer,
+                        contentColor = MaterialTheme.colorScheme.onTertiaryContainer,
+                    ),
+            ) {
+                Text(
+                    text = actionButtonViewModel.label,
+                    style = MaterialTheme.typography.bodyMedium,
                 )
-            },
-        colors =
-            ButtonDefaults.buttonColors(
-                containerColor = MaterialTheme.colorScheme.tertiaryContainer,
-                contentColor = MaterialTheme.colorScheme.onTertiaryContainer,
-            ),
-    ) {
-        Text(
-            text = viewModel.label,
-            style = MaterialTheme.typography.bodyMedium,
-        )
+            }
+        }
+    }
+}
+
+@Composable
+private fun Dialog(
+    viewModel: BouncerViewModel,
+    dialogFactory: BouncerDialogFactory,
+) {
+    val dialogMessage: String? by viewModel.dialogMessage.collectAsState()
+    var dialog: Dialog? by remember { mutableStateOf(null) }
+
+    if (dialogMessage != null) {
+        if (dialog == null) {
+            dialog =
+                dialogFactory().apply {
+                    setMessage(dialogMessage)
+                    setButton(
+                        DialogInterface.BUTTON_NEUTRAL,
+                        context.getString(R.string.ok),
+                    ) { _, _ ->
+                        viewModel.onDialogDismissed()
+                    }
+                    setCancelable(false)
+                    setCanceledOnTouchOutside(false)
+                    show()
+                }
+        }
+    } else {
+        dialog?.dismiss()
+        dialog = null
     }
 }
 
@@ -420,6 +700,14 @@
     viewModel: BouncerViewModel,
     modifier: Modifier = Modifier,
 ) {
+    if (!viewModel.isUserSwitcherVisible) {
+        // Take up the same space as the user switcher normally would, but with nothing inside it.
+        Box(
+            modifier = modifier,
+        )
+        return
+    }
+
     val selectedUserImage by viewModel.selectedUserImage.collectAsState(null)
     val dropdownItems by viewModel.userSwitcherDropdown.collectAsState(emptyList())
 
@@ -539,195 +827,10 @@
     }
 }
 
-/**
- * Renders the bouncer UI in split mode, with half on one side and half on the other side, swappable
- * by double-tapping on the side.
- */
-@Composable
-private fun SplitLayout(
-    viewModel: BouncerViewModel,
-    dialogFactory: BouncerDialogFactory,
-    modifier: Modifier = Modifier,
-) {
-    SwappableLayout(
-        startContent = { startContentModifier ->
-            StandardLayout(
-                viewModel = viewModel,
-                dialogFactory = dialogFactory,
-                layout = BouncerSceneLayout.SPLIT,
-                outputOnly = true,
-                modifier = startContentModifier,
-            )
-        },
-        endContent = { endContentModifier ->
-            UserInputArea(
-                viewModel = viewModel,
-                visibility = UserInputAreaVisibility.INPUT_ONLY,
-                layout = BouncerSceneLayout.SPLIT,
-                modifier = endContentModifier,
-            )
-        },
-        layout = BouncerSceneLayout.SPLIT,
-        modifier = modifier,
-    )
-}
-
-/**
- * Arranges the given two contents side-by-side, supporting a double tap anywhere on the background
- * to flip their positions.
- */
-@Composable
-private fun SwappableLayout(
-    startContent: @Composable (Modifier) -> Unit,
-    endContent: @Composable (Modifier) -> Unit,
-    layout: BouncerSceneLayout,
-    modifier: Modifier = Modifier,
-) {
-    val layoutDirection = LocalLayoutDirection.current
-    val isLeftToRight = layoutDirection == LayoutDirection.Ltr
-    val (isSwapped, setSwapped) = rememberSaveable(isLeftToRight) { mutableStateOf(!isLeftToRight) }
-
-    Row(
-        modifier =
-            modifier.pointerInput(Unit) {
-                detectTapGestures(
-                    onDoubleTap = { offset ->
-                        // Depending on where the user double tapped, switch the elements such that
-                        // the endContent is closer to the side that was double tapped.
-                        setSwapped(offset.x < size.width / 2)
-                    }
-                )
-            },
-    ) {
-        val animatedOffset by
-            animateFloatAsState(
-                targetValue =
-                    if (!isSwapped) {
-                        // When startContent is first, both elements have their natural placement so
-                        // they are not offset in any way.
-                        0f
-                    } else if (isLeftToRight) {
-                        // Since startContent is not first, the elements have to be swapped
-                        // horizontally. In the case of LTR locales, this means pushing startContent
-                        // to the right, hence the positive number.
-                        1f
-                    } else {
-                        // Since startContent is not first, the elements have to be swapped
-                        // horizontally. In the case of RTL locales, this means pushing startContent
-                        // to the left, hence the negative number.
-                        -1f
-                    },
-                label = "offset",
-            )
-
-        startContent(
-            Modifier.fillMaxHeight().weight(1f).graphicsLayer {
-                translationX = size.width * animatedOffset
-                alpha = animatedAlpha(animatedOffset)
-            }
-        )
-
-        Box(
-            modifier =
-                Modifier.fillMaxHeight().weight(1f).graphicsLayer {
-                    // A negative sign is used to make sure this is offset in the direction that's
-                    // opposite of the direction that the user switcher is pushed in.
-                    translationX = -size.width * animatedOffset
-                    alpha = animatedAlpha(animatedOffset)
-                }
-        ) {
-            endContent(Modifier.align(layout.swappableEndContentAlignment).widthIn(max = 400.dp))
-        }
-    }
-}
-
-/**
- * Arranges the bouncer contents and user switcher contents side-by-side, supporting a double tap
- * anywhere on the background to flip their positions.
- *
- * In situations when [isUserSwitcherVisible] is `false`, one of two things may happen: either the
- * UI for the bouncer will be shown on its own, taking up one side, with the other side just being
- * empty space or, if that kind of "stand-alone side-by-side" isn't supported, the standard
- * rendering of the bouncer will be used instead of the side-by-side layout.
- */
-@Composable
-private fun SideBySideLayout(
-    viewModel: BouncerViewModel,
-    dialogFactory: BouncerDialogFactory,
-    isUserSwitcherVisible: Boolean,
-    modifier: Modifier = Modifier,
-) {
-    SwappableLayout(
-        startContent = { startContentModifier ->
-            if (isUserSwitcherVisible) {
-                UserSwitcher(
-                    viewModel = viewModel,
-                    modifier = startContentModifier,
-                )
-            } else {
-                Box(
-                    modifier = startContentModifier,
-                )
-            }
-        },
-        endContent = { endContentModifier ->
-            StandardLayout(
-                viewModel = viewModel,
-                dialogFactory = dialogFactory,
-                layout = BouncerSceneLayout.SIDE_BY_SIDE,
-                modifier = endContentModifier,
-            )
-        },
-        layout = BouncerSceneLayout.SIDE_BY_SIDE,
-        modifier = modifier,
-    )
-}
-
-/** Arranges the bouncer contents and user switcher contents one on top of the other, vertically. */
-@Composable
-private fun StackedLayout(
-    viewModel: BouncerViewModel,
-    dialogFactory: BouncerDialogFactory,
-    isUserSwitcherVisible: Boolean,
-    modifier: Modifier = Modifier,
-) {
-    Column(
-        modifier = modifier,
-    ) {
-        if (isUserSwitcherVisible) {
-            UserSwitcher(
-                viewModel = viewModel,
-                modifier = Modifier.fillMaxWidth().weight(1f),
-            )
-        }
-
-        StandardLayout(
-            viewModel = viewModel,
-            dialogFactory = dialogFactory,
-            layout = BouncerSceneLayout.STACKED,
-            modifier = Modifier.fillMaxWidth().weight(1f),
-        )
-    }
-}
-
 interface BouncerDialogFactory {
     operator fun invoke(): AlertDialog
 }
 
-/** Enumerates all supported user-input area visibilities. */
-private enum class UserInputAreaVisibility {
-    /**
-     * Only the area where the user enters the input is shown; the area where the input is reflected
-     * back to the user is not shown.
-     */
-    INPUT_ONLY,
-    /**
-     * Only the area where the input is reflected back to the user is shown; the area where the
-     * input is entered by the user is not shown.
-     */
-    OUTPUT_ONLY,
-}
-
 /**
  * Calculates an alpha for the user switcher and bouncer such that it's at `1` when the offset of
  * the two reaches a stopping point but `0` in the middle of the transition.
@@ -774,48 +877,3 @@
 private val SceneTransitions = transitions {
     from(SceneKeys.ContiguousSceneKey, to = SceneKeys.SplitSceneKey) { spec = tween() }
 }
-
-/** Whether a more compact size should be used for various spacing dimensions. */
-internal val BouncerSceneLayout.isUseCompactSize: Boolean
-    get() =
-        when (this) {
-            BouncerSceneLayout.SIDE_BY_SIDE -> true
-            BouncerSceneLayout.SPLIT -> true
-            else -> false
-        }
-
-/** Amount of space to place between the message and the entered input UI elements, in dips. */
-private val BouncerSceneLayout.spacingBetweenMessageAndEnteredInput: Dp
-    get() =
-        when {
-            this == BouncerSceneLayout.STACKED -> 24.dp
-            isUseCompactSize -> 96.dp
-            else -> 128.dp
-        }
-
-/** Amount of space to place above the topmost UI element, in dips. */
-private val BouncerSceneLayout.topPadding: Dp
-    get() =
-        if (this == BouncerSceneLayout.SPLIT) {
-            40.dp
-        } else {
-            92.dp
-        }
-
-/** Amount of space to place below the bottommost UI element, in dips. */
-private val BouncerSceneLayout.bottomPadding: Dp
-    get() =
-        if (this == BouncerSceneLayout.SPLIT) {
-            40.dp
-        } else {
-            48.dp
-        }
-
-/** The in-a-box alignment for the content on the "end" side of a swappable layout. */
-private val BouncerSceneLayout.swappableEndContentAlignment: Alignment
-    get() =
-        if (this == BouncerSceneLayout.SPLIT) {
-            Alignment.Center
-        } else {
-            Alignment.BottomCenter
-        }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerSceneLayout.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerSceneLayout.kt
index 08b7559..1c3d93c 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerSceneLayout.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerSceneLayout.kt
@@ -26,8 +26,8 @@
 
 /**
  * Returns the [BouncerSceneLayout] that should be used by the bouncer scene. If
- * [isSideBySideSupported] is `false`, then [BouncerSceneLayout.SIDE_BY_SIDE] is replaced by
- * [BouncerSceneLayout.STANDARD].
+ * [isSideBySideSupported] is `false`, then [BouncerSceneLayout.BESIDE_USER_SWITCHER] is replaced by
+ * [BouncerSceneLayout.STANDARD_BOUNCER].
  */
 @Composable
 fun calculateLayout(
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PasswordBouncer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PasswordBouncer.kt
index 2799959..0960811 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PasswordBouncer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PasswordBouncer.kt
@@ -17,7 +17,6 @@
 package com.android.systemui.bouncer.ui.composable
 
 import android.view.ViewTreeObserver
-import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.text.KeyboardActions
 import androidx.compose.foundation.text.KeyboardOptions
 import androidx.compose.material3.LocalTextStyle
@@ -31,7 +30,6 @@
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.produceState
 import androidx.compose.runtime.remember
-import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.drawBehind
 import androidx.compose.ui.focus.FocusRequester
@@ -81,42 +79,38 @@
         }
     }
 
-    Column(
-        horizontalAlignment = Alignment.CenterHorizontally,
-        modifier = modifier,
-    ) {
-        val color = MaterialTheme.colorScheme.onSurfaceVariant
-        val lineWidthPx = with(LocalDensity.current) { 2.dp.toPx() }
+    val color = MaterialTheme.colorScheme.onSurfaceVariant
+    val lineWidthPx = with(LocalDensity.current) { 2.dp.toPx() }
 
-        TextField(
-            value = password,
-            onValueChange = viewModel::onPasswordInputChanged,
-            enabled = isInputEnabled,
-            visualTransformation = PasswordVisualTransformation(),
-            singleLine = true,
-            textStyle = LocalTextStyle.current.copy(textAlign = TextAlign.Center),
-            keyboardOptions =
-                KeyboardOptions(
-                    keyboardType = KeyboardType.Password,
-                    imeAction = ImeAction.Done,
-                ),
-            keyboardActions =
-                KeyboardActions(
-                    onDone = { viewModel.onAuthenticateKeyPressed() },
-                ),
-            modifier =
-                Modifier.focusRequester(focusRequester)
-                    .onFocusChanged { viewModel.onTextFieldFocusChanged(it.isFocused) }
-                    .drawBehind {
-                        drawLine(
-                            color = color,
-                            start = Offset(x = 0f, y = size.height - lineWidthPx),
-                            end = Offset(size.width, y = size.height - lineWidthPx),
-                            strokeWidth = lineWidthPx,
-                        )
-                    },
-        )
-    }
+    TextField(
+        value = password,
+        onValueChange = viewModel::onPasswordInputChanged,
+        enabled = isInputEnabled,
+        visualTransformation = PasswordVisualTransformation(),
+        singleLine = true,
+        textStyle = LocalTextStyle.current.copy(textAlign = TextAlign.Center),
+        keyboardOptions =
+            KeyboardOptions(
+                keyboardType = KeyboardType.Password,
+                imeAction = ImeAction.Done,
+            ),
+        keyboardActions =
+            KeyboardActions(
+                onDone = { viewModel.onAuthenticateKeyPressed() },
+            ),
+        modifier =
+            modifier
+                .focusRequester(focusRequester)
+                .onFocusChanged { viewModel.onTextFieldFocusChanged(it.isFocused) }
+                .drawBehind {
+                    drawLine(
+                        color = color,
+                        start = Offset(x = 0f, y = size.height - lineWidthPx),
+                        end = Offset(size.width, y = size.height - lineWidthPx),
+                        strokeWidth = lineWidthPx,
+                    )
+                },
+    )
 }
 
 /** Returns a [State] with `true` when the IME/keyboard is visible and `false` when it's not. */
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt
index a4b1955..0a5f5d2 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt
@@ -24,6 +24,8 @@
 import androidx.compose.foundation.gestures.awaitEachGesture
 import androidx.compose.foundation.gestures.awaitFirstDown
 import androidx.compose.foundation.gestures.detectDragGestures
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.width
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.DisposableEffect
@@ -48,7 +50,6 @@
 import com.android.compose.animation.Easings
 import com.android.compose.modifiers.thenIf
 import com.android.internal.R
-import com.android.systemui.bouncer.ui.helper.BouncerSceneLayout
 import com.android.systemui.bouncer.ui.viewmodel.PatternBouncerViewModel
 import com.android.systemui.bouncer.ui.viewmodel.PatternDotViewModel
 import kotlin.math.min
@@ -61,11 +62,14 @@
  * UI for the input part of a pattern-requiring version of the bouncer.
  *
  * The user can press, hold, and drag their pointer to select dots along a grid of dots.
+ *
+ * If [centerDotsVertically] is `true`, the dots should be centered along the axis of interest; if
+ * `false`, the dots will be pushed towards the end/bottom of the axis.
  */
 @Composable
 internal fun PatternBouncer(
     viewModel: PatternBouncerViewModel,
-    layout: BouncerSceneLayout,
+    centerDotsVertically: Boolean,
     modifier: Modifier = Modifier,
 ) {
     DisposableEffect(Unit) {
@@ -197,6 +201,14 @@
 
     Canvas(
         modifier
+            // Because the width also includes spacing to the left and right of the leftmost and
+            // rightmost dots in the grid and because UX mocks specify the width without that
+            // spacing, the actual width needs to be defined slightly bigger than the UX mock width.
+            .width((262 * colCount / 2).dp)
+            // Because the height also includes spacing above and below the topmost and bottommost
+            // dots in the grid and because UX mocks specify the height without that spacing, the
+            // actual height needs to be defined slightly bigger than the UX mock height.
+            .height((262 * rowCount / 2).dp)
             // Need to clip to bounds to make sure that the lines don't follow the input pointer
             // when it leaves the bounds of the dot grid.
             .clipToBounds()
@@ -260,7 +272,7 @@
                     availableSize = containerSize.height,
                     spacingPerDot = spacing,
                     dotCount = rowCount,
-                    isCentered = layout.isCenteredVertically,
+                    isCentered = centerDotsVertically,
                 )
             offset = Offset(horizontalOffset, verticalOffset)
             scale = (colCount * spacing) / containerSize.width
@@ -423,10 +435,6 @@
     }
 }
 
-/** Whether the UI should be centered vertically. */
-private val BouncerSceneLayout.isCenteredVertically: Boolean
-    get() = this == BouncerSceneLayout.SPLIT
-
 private const val DOT_DIAMETER_DP = 16
 private const val SELECTED_DOT_DIAMETER_DP = 24
 private const val SELECTED_DOT_REACTION_ANIMATION_DURATION_MS = 83
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinBouncer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinBouncer.kt
index 8f5d9f4..f505b90 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinBouncer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinBouncer.kt
@@ -52,7 +52,6 @@
 import com.android.compose.animation.Easings
 import com.android.compose.grid.VerticalGrid
 import com.android.compose.modifiers.thenIf
-import com.android.systemui.bouncer.ui.helper.BouncerSceneLayout
 import com.android.systemui.bouncer.ui.viewmodel.ActionButtonAppearance
 import com.android.systemui.bouncer.ui.viewmodel.PinBouncerViewModel
 import com.android.systemui.common.shared.model.ContentDescription
@@ -70,7 +69,7 @@
 @Composable
 fun PinPad(
     viewModel: PinBouncerViewModel,
-    layout: BouncerSceneLayout,
+    verticalSpacing: Dp,
     modifier: Modifier = Modifier,
 ) {
     DisposableEffect(Unit) {
@@ -96,8 +95,8 @@
 
     VerticalGrid(
         columns = columns,
-        verticalSpacing = layout.verticalSpacing,
-        horizontalSpacing = calculateHorizontalSpacingBetweenColumns(layout.gridWidth),
+        verticalSpacing = verticalSpacing,
+        horizontalSpacing = calculateHorizontalSpacingBetweenColumns(gridWidth = 300.dp),
         modifier = modifier,
     ) {
         repeat(9) { index ->
@@ -355,14 +354,6 @@
     return (gridWidth - (pinButtonMaxSize * columns)) / (columns - 1)
 }
 
-/** The width of the grid of PIN pad buttons, in dips. */
-private val BouncerSceneLayout.gridWidth: Dp
-    get() = if (isUseCompactSize) 292.dp else 300.dp
-
-/** The spacing between rows of PIN pad buttons, in dips. */
-private val BouncerSceneLayout.verticalSpacing: Dp
-    get() = if (isUseCompactSize) 8.dp else 12.dp
-
 /** Number of columns in the PIN pad grid. */
 private const val columns = 3
 /** Maximum size (width and height) of each PIN pad button. */
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 185a06c..d83f3aa 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
@@ -14,6 +14,7 @@
 import androidx.compose.material3.Icon
 import androidx.compose.material3.IconButton
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.DisposableEffect
 import androidx.compose.runtime.collectAsState
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
@@ -28,15 +29,20 @@
 import com.android.compose.animation.scene.Edge
 import com.android.compose.animation.scene.ElementKey
 import com.android.compose.animation.scene.FixedSizeEdgeDetector
+import com.android.compose.animation.scene.ObservableTransitionState
 import com.android.compose.animation.scene.SceneKey
 import com.android.compose.animation.scene.SceneScope
 import com.android.compose.animation.scene.SceneTransitionLayout
 import com.android.compose.animation.scene.SceneTransitionLayoutState
 import com.android.compose.animation.scene.Swipe
 import com.android.compose.animation.scene.SwipeDirection
+import com.android.compose.animation.scene.observableTransitionState
 import com.android.compose.animation.scene.transitions
 import com.android.systemui.communal.shared.model.CommunalSceneKey
+import com.android.systemui.communal.shared.model.ObservableCommunalTransitionState
 import com.android.systemui.communal.ui.viewmodel.BaseCommunalViewModel
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.transform
 
 object Communal {
@@ -60,7 +66,7 @@
  * This is a temporary container to allow the communal UI to use [SceneTransitionLayout] for gesture
  * handling and transitions before the full Flexiglass layout is ready.
  */
-@OptIn(ExperimentalComposeUiApi::class)
+@OptIn(ExperimentalComposeUiApi::class, ExperimentalCoroutinesApi::class)
 @Composable
 fun CommunalContainer(
     modifier: Modifier = Modifier,
@@ -81,6 +87,15 @@
         return
     }
 
+    // This effect exposes the SceneTransitionLayout's observable transition state to the rest of
+    // the system, and unsets it when the view is disposed to avoid a memory leak.
+    DisposableEffect(viewModel, sceneTransitionLayoutState) {
+        viewModel.setTransitionState(
+            sceneTransitionLayoutState.observableTransitionState().map { it.toModel() }
+        )
+        onDispose { viewModel.setTransitionState(null) }
+    }
+
     Box(modifier = modifier.fillMaxSize()) {
         SceneTransitionLayout(
             modifier = Modifier.fillMaxSize(),
@@ -171,18 +186,40 @@
     Box(modifier.element(Communal.Elements.Content)) { CommunalHub(viewModel = viewModel) }
 }
 
-// TODO(b/293899074): Remove these conversions once Compose can be used throughout SysUI.
+// TODO(b/315490861): Remove these conversions once Compose can be used throughout SysUI.
 object TransitionSceneKey {
     val Blank = CommunalSceneKey.Blank.toTransitionSceneKey()
     val Communal = CommunalSceneKey.Communal.toTransitionSceneKey()
 }
 
+// TODO(b/315490861): Remove these conversions once Compose can be used throughout SysUI.
+fun SceneKey.toCommunalSceneKey(): CommunalSceneKey {
+    return this.identity as CommunalSceneKey
+}
+
+// TODO(b/315490861): Remove these conversions once Compose can be used throughout SysUI.
 fun CommunalSceneKey.toTransitionSceneKey(): SceneKey {
     return SceneKey(name = toString(), identity = this)
 }
 
-fun SceneKey.toCommunalSceneKey(): CommunalSceneKey {
-    return this.identity as CommunalSceneKey
+/**
+ * Converts between the [SceneTransitionLayout] state class and our forked data class that can be
+ * used throughout SysUI.
+ */
+// TODO(b/315490861): Remove these conversions once Compose can be used throughout SysUI.
+fun ObservableTransitionState.toModel(): ObservableCommunalTransitionState {
+    return when (this) {
+        is ObservableTransitionState.Idle ->
+            ObservableCommunalTransitionState.Idle(scene.toCommunalSceneKey())
+        is ObservableTransitionState.Transition ->
+            ObservableCommunalTransitionState.Transition(
+                fromScene = fromScene.toCommunalSceneKey(),
+                toScene = toScene.toCommunalSceneKey(),
+                progress = progress,
+                isInitiatedByUserInput = isInitiatedByUserInput,
+                isUserInputOngoing = isUserInputOngoing,
+            )
+    }
 }
 
 object ContainerDimensions {
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 e8ecd3a..2a9cf0f 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
@@ -25,10 +25,12 @@
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.fillMaxHeight
 import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.width
 import androidx.compose.foundation.lazy.grid.GridCells
 import androidx.compose.foundation.lazy.grid.GridItemSpan
@@ -36,23 +38,41 @@
 import androidx.compose.foundation.lazy.grid.rememberLazyGridState
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Add
-import androidx.compose.material.icons.filled.Close
 import androidx.compose.material.icons.filled.Edit
+import androidx.compose.material.icons.outlined.Delete
+import androidx.compose.material3.Button
+import androidx.compose.material3.ButtonColors
+import androidx.compose.material3.ButtonDefaults
 import androidx.compose.material3.Card
 import androidx.compose.material3.CardDefaults
 import androidx.compose.material3.Icon
 import androidx.compose.material3.IconButton
+import androidx.compose.material3.OutlinedButton
+import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.collectAsState
 import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.input.pointer.pointerInput
+import androidx.compose.ui.layout.LayoutCoordinates
+import androidx.compose.ui.layout.onGloballyPositioned
+import androidx.compose.ui.layout.onSizeChanged
+import androidx.compose.ui.layout.positionInWindow
+import androidx.compose.ui.platform.LocalConfiguration
+import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.IntSize
+import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.viewinterop.AndroidView
+import com.android.compose.theme.LocalAndroidColorScheme
 import com.android.systemui.communal.domain.model.CommunalContentModel
 import com.android.systemui.communal.shared.model.CommunalContentSize
 import com.android.systemui.communal.ui.viewmodel.BaseCommunalViewModel
@@ -66,21 +86,38 @@
     modifier: Modifier = Modifier,
     viewModel: BaseCommunalViewModel,
     onOpenWidgetPicker: (() -> Unit)? = null,
+    onEditDone: (() -> Unit)? = null,
 ) {
     val communalContent by viewModel.communalContent.collectAsState(initial = emptyList())
+    var removeButtonCoordinates: LayoutCoordinates? by remember { mutableStateOf(null) }
+    var toolbarSize: IntSize? by remember { mutableStateOf(null) }
+    var gridCoordinates: LayoutCoordinates? by remember { mutableStateOf(null) }
+    var isDraggingToRemove by remember { mutableStateOf(false) }
+
     Box(
         modifier = modifier.fillMaxSize().background(Color.White),
     ) {
         CommunalHubLazyGrid(
-            modifier = Modifier.height(Dimensions.GridHeight).align(Alignment.CenterStart),
+            modifier = Modifier.align(Alignment.CenterStart),
             communalContent = communalContent,
-            isEditMode = viewModel.isEditMode,
             viewModel = viewModel,
-        )
-        if (viewModel.isEditMode && onOpenWidgetPicker != null) {
-            IconButton(onClick = onOpenWidgetPicker) {
-                Icon(Icons.Default.Add, stringResource(R.string.hub_mode_add_widget_button_text))
+            contentPadding = gridContentPadding(viewModel.isEditMode, toolbarSize),
+            setGridCoordinates = { gridCoordinates = it },
+            updateDragPositionForRemove = {
+                isDraggingToRemove =
+                    checkForDraggingToRemove(it, removeButtonCoordinates, gridCoordinates)
+                isDraggingToRemove
             }
+        )
+
+        if (viewModel.isEditMode && onOpenWidgetPicker != null && onEditDone != null) {
+            Toolbar(
+                isDraggingToRemove = isDraggingToRemove,
+                setToolbarSize = { toolbarSize = it },
+                setRemoveButtonCoordinates = { removeButtonCoordinates = it },
+                onEditDone = onEditDone,
+                onOpenWidgetPicker = onOpenWidgetPicker,
+            )
         } else {
             IconButton(onClick = viewModel::onOpenWidgetEditor) {
                 Icon(Icons.Default.Edit, stringResource(R.string.button_to_open_widget_editor))
@@ -103,25 +140,38 @@
 @Composable
 private fun CommunalHubLazyGrid(
     communalContent: List<CommunalContentModel>,
-    isEditMode: Boolean,
     viewModel: BaseCommunalViewModel,
     modifier: Modifier = Modifier,
+    contentPadding: PaddingValues,
+    setGridCoordinates: (coordinates: LayoutCoordinates) -> Unit,
+    updateDragPositionForRemove: (offset: Offset) -> Boolean,
 ) {
     var gridModifier = modifier
     val gridState = rememberLazyGridState()
     var list = communalContent
     var dragDropState: GridDragDropState? = null
-    if (isEditMode && viewModel is CommunalEditModeViewModel) {
+    if (viewModel.isEditMode && viewModel is CommunalEditModeViewModel) {
         val contentListState = rememberContentListState(communalContent, viewModel)
         list = contentListState.list
-        dragDropState = rememberGridDragDropState(gridState, contentListState)
-        gridModifier = gridModifier.dragContainer(dragDropState)
+        dragDropState =
+            rememberGridDragDropState(
+                gridState = gridState,
+                contentListState = contentListState,
+                updateDragPositionForRemove = updateDragPositionForRemove
+            )
+        gridModifier =
+            gridModifier
+                .fillMaxSize()
+                .dragContainer(dragDropState, beforeContentPadding(contentPadding))
+                .onGloballyPositioned { setGridCoordinates(it) }
+    } else {
+        gridModifier = gridModifier.height(Dimensions.GridHeight)
     }
     LazyHorizontalGrid(
         modifier = gridModifier,
         state = gridState,
         rows = GridCells.Fixed(CommunalContentSize.FULL.span),
-        contentPadding = PaddingValues(horizontal = Dimensions.Spacing),
+        contentPadding = contentPadding,
         horizontalArrangement = Arrangement.spacedBy(Dimensions.Spacing),
         verticalArrangement = Arrangement.spacedBy(Dimensions.Spacing),
     ) {
@@ -130,19 +180,18 @@
             key = { index -> list[index].key },
             span = { index -> GridItemSpan(list[index].size.span) },
         ) { index ->
-            val cardModifier = Modifier.fillMaxHeight().width(Dimensions.CardWidth)
+            val cardModifier = Modifier.width(Dimensions.CardWidth)
             val size =
                 SizeF(
                     Dimensions.CardWidth.value,
                     list[index].size.dp().value,
                 )
-            if (isEditMode && dragDropState != null) {
+            if (viewModel.isEditMode && dragDropState != null) {
                 DraggableItem(dragDropState = dragDropState, enabled = true, index = index) {
                     isDragging ->
                     val elevation by animateDpAsState(if (isDragging) 4.dp else 1.dp)
                     CommunalContent(
                         modifier = cardModifier,
-                        deleteOnClick = viewModel::onDeleteWidget,
                         elevation = elevation,
                         model = list[index],
                         viewModel = viewModel,
@@ -161,6 +210,95 @@
     }
 }
 
+/**
+ * Toolbar that contains action buttons to
+ * 1) open the widget picker
+ * 2) remove a widget from the grid and
+ * 3) exit the edit mode.
+ */
+@Composable
+private fun Toolbar(
+    isDraggingToRemove: Boolean,
+    setToolbarSize: (toolbarSize: IntSize) -> Unit,
+    setRemoveButtonCoordinates: (coordinates: LayoutCoordinates) -> Unit,
+    onOpenWidgetPicker: () -> Unit,
+    onEditDone: () -> Unit,
+) {
+    Row(
+        modifier =
+            Modifier.fillMaxWidth()
+                .padding(
+                    top = Dimensions.ToolbarPaddingTop,
+                    start = Dimensions.ToolbarPaddingHorizontal,
+                    end = Dimensions.ToolbarPaddingHorizontal,
+                )
+                .onSizeChanged { setToolbarSize(it) },
+        horizontalArrangement = Arrangement.SpaceBetween,
+        verticalAlignment = Alignment.CenterVertically
+    ) {
+        val buttonContentPadding =
+            PaddingValues(
+                vertical = Dimensions.ToolbarButtonPaddingVertical,
+                horizontal = Dimensions.ToolbarButtonPaddingHorizontal,
+            )
+        val spacerModifier = Modifier.width(Dimensions.ToolbarButtonSpaceBetween)
+        Button(
+            onClick = onOpenWidgetPicker,
+            colors = filledSecondaryButtonColors(),
+            contentPadding = buttonContentPadding
+        ) {
+            Icon(Icons.Default.Add, stringResource(R.string.button_to_open_widget_editor))
+            Spacer(spacerModifier)
+            Text(
+                text = stringResource(R.string.hub_mode_add_widget_button_text),
+            )
+        }
+
+        val buttonColors =
+            if (isDraggingToRemove) filledButtonColors() else ButtonDefaults.outlinedButtonColors()
+        OutlinedButton(
+            onClick = {},
+            colors = buttonColors,
+            contentPadding = buttonContentPadding,
+            modifier = Modifier.onGloballyPositioned { setRemoveButtonCoordinates(it) },
+        ) {
+            Icon(Icons.Outlined.Delete, stringResource(R.string.button_to_open_widget_editor))
+            Spacer(spacerModifier)
+            Text(
+                text = stringResource(R.string.button_to_remove_widget),
+            )
+        }
+
+        Button(
+            onClick = onEditDone,
+            colors = filledButtonColors(),
+            contentPadding = buttonContentPadding
+        ) {
+            Text(
+                text = stringResource(R.string.hub_mode_editing_exit_button_text),
+            )
+        }
+    }
+}
+
+@Composable
+private fun filledButtonColors(): ButtonColors {
+    val colors = LocalAndroidColorScheme.current
+    return ButtonDefaults.buttonColors(
+        containerColor = colors.primary,
+        contentColor = colors.onPrimary,
+    )
+}
+
+@Composable
+private fun filledSecondaryButtonColors(): ButtonColors {
+    val colors = LocalAndroidColorScheme.current
+    return ButtonDefaults.buttonColors(
+        containerColor = colors.secondary,
+        contentColor = colors.onSecondary,
+    )
+}
+
 @Composable
 private fun CommunalContent(
     model: CommunalContentModel,
@@ -168,11 +306,9 @@
     size: SizeF,
     modifier: Modifier = Modifier,
     elevation: Dp = 0.dp,
-    deleteOnClick: ((id: Int) -> Unit)? = null,
 ) {
     when (model) {
-        is CommunalContentModel.Widget ->
-            WidgetContent(model, size, elevation, deleteOnClick, modifier)
+        is CommunalContentModel.Widget -> WidgetContent(model, size, elevation, modifier)
         is CommunalContentModel.Smartspace -> SmartspaceContent(model, modifier)
         is CommunalContentModel.Tutorial -> TutorialContent(modifier)
         is CommunalContentModel.Umo -> Umo(viewModel, modifier)
@@ -184,19 +320,12 @@
     model: CommunalContentModel.Widget,
     size: SizeF,
     elevation: Dp,
-    deleteOnClick: ((id: Int) -> Unit)?,
     modifier: Modifier = Modifier,
 ) {
-    // TODO(b/309009246): update background color
     Card(
-        modifier = modifier.fillMaxSize().background(Color.White),
+        modifier = modifier.height(size.height.dp),
         elevation = CardDefaults.cardElevation(draggedElevation = elevation),
     ) {
-        if (deleteOnClick != null) {
-            IconButton(onClick = { deleteOnClick(model.appWidgetId) }) {
-                Icon(Icons.Default.Close, stringResource(R.string.button_to_remove_widget))
-            }
-        }
         AndroidView(
             modifier = modifier,
             factory = { context ->
@@ -249,6 +378,60 @@
     )
 }
 
+/**
+ * Returns the `contentPadding` of the grid. Use the vertical padding to push the grid content area
+ * below the toolbar and let the grid take the max size. This ensures the item can be dragged
+ * outside the grid over the toolbar, without part of it getting clipped by the container.
+ */
+@Composable
+private fun gridContentPadding(isEditMode: Boolean, toolbarSize: IntSize?): PaddingValues {
+    if (!isEditMode || toolbarSize == null) {
+        return PaddingValues(horizontal = Dimensions.Spacing)
+    }
+    val configuration = LocalConfiguration.current
+    val density = LocalDensity.current
+    val screenHeight = configuration.screenHeightDp.dp
+    val toolbarHeight = with(density) { Dimensions.ToolbarPaddingTop + toolbarSize.height.toDp() }
+    val verticalPadding =
+        ((screenHeight - toolbarHeight - Dimensions.GridHeight) / 2).coerceAtLeast(
+            Dimensions.Spacing
+        )
+    return PaddingValues(
+        start = Dimensions.ToolbarPaddingHorizontal,
+        end = Dimensions.ToolbarPaddingHorizontal,
+        top = verticalPadding + toolbarHeight,
+        bottom = verticalPadding
+    )
+}
+
+@Composable
+private fun beforeContentPadding(paddingValues: PaddingValues): ContentPaddingInPx {
+    return with(LocalDensity.current) {
+        ContentPaddingInPx(
+            startPadding = paddingValues.calculateLeftPadding(LayoutDirection.Ltr).toPx(),
+            topPadding = paddingValues.calculateTopPadding().toPx()
+        )
+    }
+}
+
+/**
+ * Check whether the pointer position that the item is being dragged at is within the coordinates of
+ * the remove button in the toolbar. Returns true if the item is removable.
+ */
+private fun checkForDraggingToRemove(
+    offset: Offset,
+    removeButtonCoordinates: LayoutCoordinates?,
+    gridCoordinates: LayoutCoordinates?,
+): Boolean {
+    if (removeButtonCoordinates == null || gridCoordinates == null) {
+        return false
+    }
+    val pointer = gridCoordinates.positionInWindow() + offset
+    val removeButton = removeButtonCoordinates.positionInWindow()
+    return pointer.x in removeButton.x..removeButton.x + removeButtonCoordinates.size.width &&
+        pointer.y in removeButton.y..removeButton.y + removeButtonCoordinates.size.height
+}
+
 private fun CommunalContentSize.dp(): Dp {
     return when (this) {
         CommunalContentSize.FULL -> Dimensions.CardHeightFull
@@ -257,6 +440,8 @@
     }
 }
 
+data class ContentPaddingInPx(val startPadding: Float, val topPadding: Float)
+
 object Dimensions {
     val CardWidth = 464.dp
     val CardHeightFull = 630.dp
@@ -264,4 +449,11 @@
     val CardHeightThird = 199.dp
     val GridHeight = CardHeightFull
     val Spacing = 16.dp
+
+    // The sizing/padding of the toolbar in glanceable hub edit mode
+    val ToolbarPaddingTop = 27.dp
+    val ToolbarPaddingHorizontal = 16.dp
+    val ToolbarButtonPaddingHorizontal = 24.dp
+    val ToolbarButtonPaddingVertical = 16.dp
+    val ToolbarButtonSpaceBetween = 8.dp
 }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/GridDragDropState.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/GridDragDropState.kt
index 6cfa2f2..5451d05 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/GridDragDropState.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/GridDragDropState.kt
@@ -48,12 +48,18 @@
 @Composable
 fun rememberGridDragDropState(
     gridState: LazyGridState,
-    contentListState: ContentListState
+    contentListState: ContentListState,
+    updateDragPositionForRemove: (offset: Offset) -> Boolean,
 ): GridDragDropState {
     val scope = rememberCoroutineScope()
     val state =
         remember(gridState, contentListState) {
-            GridDragDropState(state = gridState, contentListState = contentListState, scope = scope)
+            GridDragDropState(
+                state = gridState,
+                contentListState = contentListState,
+                scope = scope,
+                updateDragPositionForRemove = updateDragPositionForRemove
+            )
         }
     LaunchedEffect(state) {
         while (true) {
@@ -67,23 +73,30 @@
 /**
  * Handles drag and drop cards in the glanceable hub. While dragging to move, other items that are
  * affected will dynamically get positioned and the state is tracked by [ContentListState]. When
- * dragging to remove, affected cards will be moved and [ContentListState.onRemove] is called to
- * remove the dragged item. On dragging ends, call [ContentListState.onSaveList] to persist the
- * change.
+ * dragging to remove, affected cards will be moved and [updateDragPositionForRemove] is called to
+ * check whether the dragged item can be removed. On dragging ends, call [ContentListState.onRemove]
+ * to remove the dragged item if condition met and call [ContentListState.onSaveList] to persist any
+ * change in ordering.
  */
 class GridDragDropState
 internal constructor(
     private val state: LazyGridState,
     private val contentListState: ContentListState,
     private val scope: CoroutineScope,
+    private val updateDragPositionForRemove: (offset: Offset) -> Boolean
 ) {
     var draggingItemIndex by mutableStateOf<Int?>(null)
         private set
 
+    var isDraggingToRemove by mutableStateOf(false)
+        private set
+
     internal val scrollChannel = Channel<Float>()
 
     private var draggingItemDraggedDelta by mutableStateOf(Offset.Zero)
     private var draggingItemInitialOffset by mutableStateOf(Offset.Zero)
+    private var dragStartPointerOffset by mutableStateOf(Offset.Zero)
+
     internal val draggingItemOffset: Offset
         get() =
             draggingItemLayoutInfo?.let { item ->
@@ -94,27 +107,36 @@
     private val draggingItemLayoutInfo: LazyGridItemInfo?
         get() = state.layoutInfo.visibleItemsInfo.firstOrNull { it.index == draggingItemIndex }
 
-    internal fun onDragStart(offset: Offset) {
+    internal fun onDragStart(offset: Offset, contentOffset: Offset) {
         state.layoutInfo.visibleItemsInfo
             .firstOrNull { item ->
+                // grid item offset is based off grid content container so we need to deduct
+                // before content padding from the initial pointer position
                 item.isEditable &&
-                    offset.x.toInt() in item.offset.x..item.offsetEnd.x &&
-                    offset.y.toInt() in item.offset.y..item.offsetEnd.y
+                    (offset.x - contentOffset.x).toInt() in item.offset.x..item.offsetEnd.x &&
+                    (offset.y - contentOffset.y).toInt() in item.offset.y..item.offsetEnd.y
             }
             ?.apply {
+                dragStartPointerOffset = offset - this.offset.toOffset()
                 draggingItemIndex = index
                 draggingItemInitialOffset = this.offset.toOffset()
             }
     }
 
     internal fun onDragInterrupted() {
-        if (draggingItemIndex != null) {
+        draggingItemIndex?.let {
+            if (isDraggingToRemove) {
+                contentListState.onRemove(it)
+                isDraggingToRemove = false
+                updateDragPositionForRemove(Offset.Zero)
+            }
             // persist list editing changes on dragging ends
             contentListState.onSaveList()
             draggingItemIndex = null
         }
         draggingItemDraggedDelta = Offset.Zero
         draggingItemInitialOffset = Offset.Zero
+        dragStartPointerOffset = Offset.Zero
     }
 
     internal fun onDrag(offset: Offset) {
@@ -152,18 +174,13 @@
                 contentListState.onMove(draggingItem.index, targetItem.index)
             }
             draggingItemIndex = targetItem.index
+            isDraggingToRemove = false
         } else {
             val overscroll = checkForOverscroll(startOffset, endOffset)
             if (overscroll != 0f) {
                 scrollChannel.trySend(overscroll)
             }
-            val removeOffset = checkForRemove(startOffset)
-            if (removeOffset != 0f) {
-                draggingItemIndex?.let {
-                    contentListState.onRemove(it)
-                    draggingItemIndex = null
-                }
-            }
+            isDraggingToRemove = checkForRemove(startOffset)
         }
     }
 
@@ -185,14 +202,11 @@
         }
     }
 
-    // TODO(b/309968801): a temporary solution to decide whether to remove card when it's dragged up
-    //  and out of grid. Once we have a taskbar, calculate the intersection of the dragged item with
-    //  the Remove button.
-    private fun checkForRemove(startOffset: Offset): Float {
+    /** Calls the callback with the updated drag position and returns whether to remove the item. */
+    private fun checkForRemove(startOffset: Offset): Boolean {
         return if (draggingItemDraggedDelta.y < 0)
-            (startOffset.y + Dimensions.CardHeightHalf.value - state.layoutInfo.viewportStartOffset)
-                .coerceAtMost(0f)
-        else 0f
+            updateDragPositionForRemove(startOffset + dragStartPointerOffset)
+        else false
     }
 }
 
@@ -204,14 +218,22 @@
     return Offset(x + size.width, y + size.height)
 }
 
-fun Modifier.dragContainer(dragDropState: GridDragDropState): Modifier {
-    return pointerInput(dragDropState) {
+fun Modifier.dragContainer(
+    dragDropState: GridDragDropState,
+    beforeContentPadding: ContentPaddingInPx
+): Modifier {
+    return pointerInput(dragDropState, beforeContentPadding) {
         detectDragGesturesAfterLongPress(
             onDrag = { change, offset ->
                 change.consume()
                 dragDropState.onDrag(offset = offset)
             },
-            onDragStart = { offset -> dragDropState.onDragStart(offset) },
+            onDragStart = { offset ->
+                dragDropState.onDragStart(
+                    offset,
+                    Offset(beforeContentPadding.startPadding, beforeContentPadding.topPadding)
+                )
+            },
             onDragEnd = { dragDropState.onDragInterrupted() },
             onDragCancel = { dragDropState.onDragInterrupted() }
         )
@@ -237,6 +259,7 @@
             Modifier.zIndex(1f).graphicsLayer {
                 translationX = dragDropState.draggingItemOffset.x
                 translationY = dragDropState.draggingItemOffset.y
+                alpha = if (dragDropState.isDraggingToRemove) 0.5f else 1f
             }
         } else {
             Modifier.animateItemPlacement()
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 c49c197..12f1b30 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
@@ -27,11 +27,13 @@
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.collectAsState
 import androidx.compose.runtime.getValue
 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.graphics.graphicsLayer
 import androidx.compose.ui.layout.LayoutCoordinates
 import androidx.compose.ui.layout.boundsInWindow
 import androidx.compose.ui.layout.onPlaced
@@ -89,13 +91,18 @@
     isScrimVisible: Boolean,
     modifier: Modifier = Modifier,
 ) {
+    val cornerRadius by viewModel.cornerRadiusDp.collectAsState()
+
     Box(modifier = modifier) {
         if (isScrimVisible) {
             Box(
                 modifier =
                     Modifier.element(Notifications.Elements.NotificationScrim)
                         .fillMaxSize()
-                        .clip(RoundedCornerShape(32.dp))
+                        .graphicsLayer {
+                            shape = RoundedCornerShape(cornerRadius.dp)
+                            clip = true
+                        }
                         .background(MaterialTheme.colorScheme.surface)
             )
         }
@@ -167,7 +174,9 @@
                     }
                     val boundsInWindow = coordinates.boundsInWindow()
                     viewModel.onBoundsChanged(
+                        left = boundsInWindow.left,
                         top = boundsInWindow.top,
+                        right = boundsInWindow.right,
                         bottom = boundsInWindow.bottom,
                     )
                 }
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 009f8bb..2944bd9 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
@@ -174,12 +174,8 @@
     lerp: (T, T, Float) -> T,
     canOverflow: Boolean,
 ): T {
-    val state = layoutImpl.state.transitionState
-    if (
-        state !is TransitionState.Transition ||
-            state.fromScene == state.toScene ||
-            !layoutImpl.isTransitionReady(state)
-    ) {
+    val transition = layoutImpl.state.currentTransition
+    if (transition == null || !layoutImpl.isTransitionReady(transition)) {
         return sharedValue.value
     }
 
@@ -195,10 +191,11 @@
         return value as Element.SharedValue<T>
     }
 
-    val fromValue = sceneValue(state.fromScene)
-    val toValue = sceneValue(state.toScene)
+    val fromValue = sceneValue(transition.fromScene)
+    val toValue = sceneValue(transition.toScene)
     return if (fromValue != null && toValue != null) {
-        val progress = if (canOverflow) state.progress else state.progress.coerceIn(0f, 1f)
+        val progress =
+            if (canOverflow) transition.progress else transition.progress.coerceIn(0f, 1f)
         lerp(fromValue.value, toValue.value, progress)
     } else if (fromValue != null) {
         fromValue.value
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateToScene.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateToScene.kt
index 199832b..ba6d00e 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateToScene.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateToScene.kt
@@ -28,11 +28,11 @@
  * the currently running transition, if there is one.
  */
 internal fun CoroutineScope.animateToScene(
-    layoutImpl: SceneTransitionLayoutImpl,
+    layoutState: SceneTransitionLayoutStateImpl,
     target: SceneKey,
 ) {
-    val state = layoutImpl.state.transitionState
-    if (state.currentScene == target) {
+    val transitionState = layoutState.transitionState
+    if (transitionState.currentScene == target) {
         // This can happen in 3 different situations, for which there isn't anything else to do:
         //  1. There is no ongoing transition and [target] is already the current scene.
         //  2. The user is swiping to [target] from another scene and released their pointer such
@@ -44,50 +44,47 @@
         return
     }
 
-    when (state) {
-        is TransitionState.Idle -> animate(layoutImpl, target)
+    when (transitionState) {
+        is TransitionState.Idle -> animate(layoutState, target)
         is TransitionState.Transition -> {
-            if (state.toScene == state.fromScene) {
-                // Same as idle.
-                animate(layoutImpl, target)
-                return
-            }
-
             // A transition is currently running: first check whether `transition.toScene` or
             // `transition.fromScene` is the same as our target scene, in which case the transition
             // can be accelerated or reversed to end up in the target state.
 
-            if (state.toScene == target) {
+            if (transitionState.toScene == target) {
                 // The user is currently swiping to [target] but didn't release their pointer yet:
                 // animate the progress to `1`.
 
-                check(state.fromScene == state.currentScene)
-                val progress = state.progress
+                check(transitionState.fromScene == transitionState.currentScene)
+                val progress = transitionState.progress
                 if ((1f - progress).absoluteValue < ProgressVisibilityThreshold) {
-                    // The transition is already finished (progress ~= 1): no need to animate.
-                    layoutImpl.state.transitionState = TransitionState.Idle(state.currentScene)
+                    // The transition is already finished (progress ~= 1): no need to animate. We
+                    // finish the current transition early to make sure that the current state
+                    // change is committed.
+                    layoutState.finishTransition(transitionState, transitionState.currentScene)
                 } else {
                     // The transition is in progress: start the canned animation at the same
                     // progress as it was in.
                     // TODO(b/290184746): Also take the current velocity into account.
-                    animate(layoutImpl, target, startProgress = progress)
+                    animate(layoutState, target, startProgress = progress)
                 }
 
                 return
             }
 
-            if (state.fromScene == target) {
+            if (transitionState.fromScene == target) {
                 // There is a transition from [target] to another scene: simply animate the same
                 // transition progress to `0`.
 
-                check(state.toScene == state.currentScene)
-                val progress = state.progress
+                check(transitionState.toScene == transitionState.currentScene)
+                val progress = transitionState.progress
                 if (progress.absoluteValue < ProgressVisibilityThreshold) {
-                    // The transition is at progress ~= 0: no need to animate.
-                    layoutImpl.state.transitionState = TransitionState.Idle(state.currentScene)
+                    // The transition is at progress ~= 0: no need to animate.We finish the current
+                    // transition early to make sure that the current state change is committed.
+                    layoutState.finishTransition(transitionState, transitionState.currentScene)
                 } else {
                     // TODO(b/290184746): Also take the current velocity into account.
-                    animate(layoutImpl, target, startProgress = progress, reversed = true)
+                    animate(layoutState, target, startProgress = progress, reversed = true)
                 }
 
                 return
@@ -95,27 +92,22 @@
 
             // Generic interruption; the current transition is neither from or to [target].
             // TODO(b/290930950): Better handle interruptions here.
-            animate(layoutImpl, target)
+            animate(layoutState, target)
         }
     }
 }
 
 private fun CoroutineScope.animate(
-    layoutImpl: SceneTransitionLayoutImpl,
+    layoutState: SceneTransitionLayoutStateImpl,
     target: SceneKey,
     startProgress: Float = 0f,
     reversed: Boolean = false,
 ) {
-    val fromScene = layoutImpl.state.transitionState.currentScene
+    val fromScene = layoutState.transitionState.currentScene
     val isUserInput =
-        (layoutImpl.state.transitionState as? TransitionState.Transition)?.isInitiatedByUserInput
+        (layoutState.transitionState as? TransitionState.Transition)?.isInitiatedByUserInput
             ?: false
 
-    val animationSpec = layoutImpl.transitions.transitionSpec(fromScene, target).spec
-    val visibilityThreshold =
-        (animationSpec as? SpringSpec)?.visibilityThreshold ?: ProgressVisibilityThreshold
-    val animatable = Animatable(startProgress, visibilityThreshold = visibilityThreshold)
-
     val targetProgress = if (reversed) 0f else 1f
     val transition =
         if (reversed) {
@@ -125,7 +117,6 @@
                 currentScene = target,
                 isInitiatedByUserInput = isUserInput,
                 isUserInputOngoing = false,
-                animatable = animatable,
             )
         } else {
             OneOffTransition(
@@ -134,32 +125,46 @@
                 currentScene = target,
                 isInitiatedByUserInput = isUserInput,
                 isUserInputOngoing = false,
-                animatable = animatable,
             )
         }
 
-    // Change the current layout state to use this new transition.
-    layoutImpl.state.transitionState = transition
+    // Change the current layout state to start this new transition. This will compute the
+    // TransformationSpec associated to this transition, which we need to initialize the Animatable
+    // that will actually animate it.
+    layoutState.startTransition(transition)
+
+    // The transformation now contains the spec that we should use to instantiate the Animatable.
+    val animationSpec = layoutState.transformationSpec.progressSpec
+    val visibilityThreshold =
+        (animationSpec as? SpringSpec)?.visibilityThreshold ?: ProgressVisibilityThreshold
+    val animatable =
+        Animatable(startProgress, visibilityThreshold = visibilityThreshold).also {
+            transition.animatable = it
+        }
 
     // Animate the progress to its target value.
     launch {
         animatable.animateTo(targetProgress, animationSpec)
-
-        // Unless some other external state change happened, the state should now be idle.
-        if (layoutImpl.state.transitionState == transition) {
-            layoutImpl.state.transitionState = TransitionState.Idle(target)
-        }
+        layoutState.finishTransition(transition, target)
     }
 }
 
 private class OneOffTransition(
-    override val fromScene: SceneKey,
-    override val toScene: SceneKey,
+    fromScene: SceneKey,
+    toScene: SceneKey,
     override val currentScene: SceneKey,
     override val isInitiatedByUserInput: Boolean,
     override val isUserInputOngoing: Boolean,
-    private val animatable: Animatable<Float, AnimationVector1D>,
-) : TransitionState.Transition {
+) : TransitionState.Transition(fromScene, toScene) {
+    /**
+     * The animatable used to animate this transition.
+     *
+     * Note: This is lateinit because we need to first create this Transition object so that
+     * [SceneTransitionLayoutState] can compute the transformations and animation spec associated to
+     * it, which is need to initialize this Animatable.
+     */
+    lateinit var animatable: Animatable<Float, AnimationVector1D>
+
     override val progress: Float
         get() = animatable.value
 }
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 2b11952..5dc1079 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
@@ -181,15 +181,11 @@
 }
 
 internal class ElementNode(
-    layoutImpl: SceneTransitionLayoutImpl,
-    scene: Scene,
-    element: Element,
-    sceneValues: Element.TargetValues,
+    private var layoutImpl: SceneTransitionLayoutImpl,
+    private var scene: Scene,
+    private var element: Element,
+    private var sceneValues: Element.TargetValues,
 ) : Modifier.Node(), DrawModifierNode {
-    private var layoutImpl: SceneTransitionLayoutImpl = layoutImpl
-    private var scene: Scene = scene
-    private var element: Element = element
-    private var sceneValues: Element.TargetValues = sceneValues
 
     override fun onAttach() {
         super.onAttach()
@@ -213,22 +209,11 @@
     override fun onDetach() {
         super.onDetach()
         removeNodeFromSceneValues()
+        maybePruneMaps(layoutImpl, element, sceneValues)
     }
 
     private fun removeNodeFromSceneValues() {
         sceneValues.nodes.remove(this)
-
-        // If element is not composed from this scene anymore, remove the scene values. This works
-        // because [onAttach] is called before [onDetach], so if an element is moved from the UI
-        // tree we will first add the new code location then remove the old one.
-        if (sceneValues.nodes.isEmpty()) {
-            element.sceneValues.remove(sceneValues.scene)
-        }
-
-        // If the element is not composed in any scene, remove it from the elements map.
-        if (element.sceneValues.isEmpty()) {
-            layoutImpl.elements.remove(element.key)
-        }
     }
 
     fun update(
@@ -237,12 +222,16 @@
         element: Element,
         sceneValues: Element.TargetValues,
     ) {
+        check(layoutImpl == this.layoutImpl && scene == this.scene)
         removeNodeFromSceneValues()
-        this.layoutImpl = layoutImpl
-        this.scene = scene
+
+        val prevElement = this.element
+        val prevSceneValues = this.sceneValues
         this.element = element
         this.sceneValues = sceneValues
+
         addNodeToSceneValues()
+        maybePruneMaps(layoutImpl, prevElement, prevSceneValues)
     }
 
     override fun ContentDrawScope.draw() {
@@ -261,6 +250,28 @@
             }
         }
     }
+
+    companion object {
+        private fun maybePruneMaps(
+            layoutImpl: SceneTransitionLayoutImpl,
+            element: Element,
+            sceneValues: Element.TargetValues,
+        ) {
+            // If element is not composed from this scene anymore, remove the scene values. This
+            // works because [onAttach] is called before [onDetach], so if an element is moved from
+            // the UI tree we will first add the new code location then remove the old one.
+            if (
+                sceneValues.nodes.isEmpty() && element.sceneValues[sceneValues.scene] == sceneValues
+            ) {
+                element.sceneValues.remove(sceneValues.scene)
+
+                // If the element is not composed in any scene, remove it from the elements map.
+                if (element.sceneValues.isEmpty() && layoutImpl.elements[element.key] == element) {
+                    layoutImpl.elements.remove(element.key)
+                }
+            }
+        }
+    }
 }
 
 private fun shouldDrawElement(
@@ -268,27 +279,27 @@
     scene: Scene,
     element: Element,
 ): Boolean {
-    val state = layoutImpl.state.transitionState
+    val transition = layoutImpl.state.currentTransition
 
     // Always draw the element if there is no ongoing transition or if the element is not shared.
     if (
-        state !is TransitionState.Transition ||
-            state.fromScene == state.toScene ||
-            !layoutImpl.isTransitionReady(state) ||
-            state.fromScene !in element.sceneValues ||
-            state.toScene !in element.sceneValues
+        transition == null ||
+            !layoutImpl.isTransitionReady(transition) ||
+            transition.fromScene !in element.sceneValues ||
+            transition.toScene !in element.sceneValues
     ) {
         return true
     }
 
-    val sharedTransformation = sharedElementTransformation(layoutImpl, state, element.key)
+    val sharedTransformation =
+        sharedElementTransformation(layoutImpl.state, transition, element.key)
     if (sharedTransformation?.enabled == false) {
         return true
     }
 
     return shouldDrawOrComposeSharedElement(
         layoutImpl,
-        state,
+        transition,
         scene.key,
         element.key,
         sharedTransformation,
@@ -317,21 +328,21 @@
 }
 
 private fun isSharedElementEnabled(
-    layoutImpl: SceneTransitionLayoutImpl,
+    layoutState: SceneTransitionLayoutStateImpl,
     transition: TransitionState.Transition,
     element: ElementKey,
 ): Boolean {
-    return sharedElementTransformation(layoutImpl, transition, element)?.enabled ?: true
+    return sharedElementTransformation(layoutState, transition, element)?.enabled ?: true
 }
 
 internal fun sharedElementTransformation(
-    layoutImpl: SceneTransitionLayoutImpl,
+    layoutState: SceneTransitionLayoutStateImpl,
     transition: TransitionState.Transition,
     element: ElementKey,
 ): SharedElementTransformation? {
-    val spec = layoutImpl.transitions.transitionSpec(transition.fromScene, transition.toScene)
-    val sharedInFromScene = spec.transformations(element, transition.fromScene).shared
-    val sharedInToScene = spec.transformations(element, transition.toScene).shared
+    val transformationSpec = layoutState.transformationSpec
+    val sharedInFromScene = transformationSpec.transformations(element, transition.fromScene).shared
+    val sharedInToScene = transformationSpec.transformations(element, transition.toScene).shared
 
     // The sharedElement() transformation must either be null or be the same in both scenes.
     if (sharedInFromScene != sharedInToScene) {
@@ -357,13 +368,9 @@
     scene: Scene,
     sceneValues: Element.TargetValues,
 ): Boolean {
-    val state = layoutImpl.state.transitionState
+    val transition = layoutImpl.state.currentTransition ?: return true
 
-    if (state !is TransitionState.Transition || state.fromScene == state.toScene) {
-        return true
-    }
-
-    if (!layoutImpl.isTransitionReady(state)) {
+    if (!layoutImpl.isTransitionReady(transition)) {
         val lastValue =
             sceneValues.lastValues.alpha.takeIf { it != Element.AlphaUnspecified }
                 ?: element.lastSharedValues.alpha.takeIf { it != Element.AlphaUnspecified } ?: 1f
@@ -371,8 +378,8 @@
         return lastValue == 1f
     }
 
-    val fromScene = state.fromScene
-    val toScene = state.toScene
+    val fromScene = transition.fromScene
+    val toScene = transition.toScene
     val fromValues = element.sceneValues[fromScene]
     val toValues = element.sceneValues[toScene]
 
@@ -381,14 +388,11 @@
     }
 
     val isSharedElement = fromValues != null && toValues != null
-    if (isSharedElement && isSharedElementEnabled(layoutImpl, state, element.key)) {
+    if (isSharedElement && isSharedElementEnabled(layoutImpl.state, transition, element.key)) {
         return true
     }
 
-    return layoutImpl.transitions
-        .transitionSpec(fromScene, toScene)
-        .transformations(element.key, scene.key)
-        .alpha == null
+    return layoutImpl.state.transformationSpec.transformations(element.key, scene.key).alpha == null
 }
 
 /**
@@ -593,50 +597,46 @@
     lastValue: () -> T,
     lerp: (T, T, Float) -> T,
 ): T {
-    val state = layoutImpl.state.transitionState
-
-    // There is no ongoing transition.
-    if (state !is TransitionState.Transition || state.fromScene == state.toScene) {
-        // Even if this element SceneTransitionLayout is not animated, the layout itself might be
-        // animated (e.g. by another parent SceneTransitionLayout), in which case this element still
-        // need to participate in the layout phase.
-        return currentValue()
-    }
+    val transition =
+        layoutImpl.state.currentTransition
+        // There is no ongoing transition. Even if this element SceneTransitionLayout is not
+        // animated, the layout itself might be animated (e.g. by another parent
+        // SceneTransitionLayout), in which case this element still need to participate in the
+        // layout phase.
+        ?: return currentValue()
 
     // A transition was started but it's not ready yet (not all elements have been composed/laid
     // out yet). Use the last value that was set, to make sure elements don't unexpectedly jump.
-    if (!layoutImpl.isTransitionReady(state)) {
+    if (!layoutImpl.isTransitionReady(transition)) {
         return lastValue()
     }
 
-    val fromScene = state.fromScene
-    val toScene = state.toScene
+    val fromScene = transition.fromScene
+    val toScene = transition.toScene
     val fromValues = element.sceneValues[fromScene]
     val toValues = element.sceneValues[toScene]
 
     if (fromValues == null && toValues == null) {
-        error("This should not happen, element $element is neither in $fromScene or $toScene")
+        // TODO(b/311600838): Throw an exception instead once layers of disposed elements are not
+        // run anymore.
+        return lastValue()
     }
 
     // The element is shared: interpolate between the value in fromScene and the value in toScene.
     // TODO(b/290184746): Support non linear shared paths as well as a way to make sure that shared
     // elements follow the finger direction.
     val isSharedElement = fromValues != null && toValues != null
-    if (isSharedElement && isSharedElementEnabled(layoutImpl, state, element.key)) {
+    if (isSharedElement && isSharedElementEnabled(layoutImpl.state, transition, element.key)) {
         val start = sceneValue(fromValues!!)
         val end = sceneValue(toValues!!)
 
         // 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.
-        return if (start == end) start else lerp(start, end, state.progress)
+        return if (start == end) start else lerp(start, end, transition.progress)
     }
 
     val transformation =
-        transformation(
-            layoutImpl.transitions
-                .transitionSpec(fromScene, toScene)
-                .transformations(element.key, scene.key)
-        )
+        transformation(layoutImpl.state.transformationSpec.transformations(element.key, scene.key))
         // If there is no transformation explicitly associated to this element value, let's use
         // the value given by the system (like the current position and size given by the layout
         // pass).
@@ -659,7 +659,7 @@
             scene,
             element,
             sceneValues,
-            state,
+            transition,
             idleValue,
         )
 
@@ -669,7 +669,7 @@
         return targetValue
     }
 
-    val progress = state.progress
+    val progress = transition.progress
     // TODO(b/290184746): Make sure that we don't overflow transformations associated to a range.
     val rangeProgress = transformation.range?.progress(progress) ?: progress
 
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/GestureHandler.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/GestureHandler.kt
index 5d8eaf7..58052cd 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/GestureHandler.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/GestureHandler.kt
@@ -2,10 +2,9 @@
 
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
-import androidx.compose.ui.unit.IntSize
 
 interface DraggableHandler {
-    fun onDragStarted(layoutSize: IntSize, startedPosition: Offset, pointersDown: Int = 1)
+    fun onDragStarted(startedPosition: Offset, overSlop: Float, pointersDown: Int = 1)
     fun onDelta(pixels: Float)
     fun onDragStopped(velocity: Float)
 }
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 fa385d0..306f276 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
@@ -120,21 +120,13 @@
     scene: SceneKey,
     element: Element,
 ): Boolean {
-    val transitionState = layoutImpl.state.transitionState
-
-    // If we are idle, there is only one [scene] that is composed so we can compose our movable
-    // content here.
-    if (transitionState is TransitionState.Idle) {
-        check(transitionState.currentScene == scene)
-        return true
-    }
-
-    val fromScene = (transitionState as TransitionState.Transition).fromScene
-    val toScene = transitionState.toScene
-    if (fromScene == toScene) {
-        check(fromScene == scene)
-        return true
-    }
+    val transition =
+        layoutImpl.state.currentTransition
+        // If we are idle, there is only one [scene] that is composed so we can compose our
+        // movable content here.
+        ?: return true
+    val fromScene = transition.fromScene
+    val toScene = transition.toScene
 
     val fromReady = layoutImpl.isSceneReady(fromScene)
     val toReady = layoutImpl.isSceneReady(toScene)
@@ -185,10 +177,10 @@
 
     return shouldDrawOrComposeSharedElement(
         layoutImpl,
-        transitionState,
+        transition,
         scene,
         element.key,
-        sharedElementTransformation(layoutImpl, transitionState, element.key),
+        sharedElementTransformation(layoutImpl.state, transition, element.key),
     )
 }
 
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt
index a0fba80..3873878 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt
@@ -66,8 +66,8 @@
     orientation: Orientation,
     enabled: Boolean,
     startDragImmediately: Boolean,
-    onDragStarted: (layoutSize: IntSize, startedPosition: Offset, pointersDown: Int) -> Unit,
-    onDragDelta: (Float) -> Unit,
+    onDragStarted: (startedPosition: Offset, overSlop: Float, pointersDown: Int) -> Unit,
+    onDragDelta: (delta: Float) -> Unit,
     onDragStopped: (velocity: Float) -> Unit,
 ): Modifier =
     this.then(
@@ -86,7 +86,7 @@
     private val enabled: Boolean,
     private val startDragImmediately: Boolean,
     private val onDragStarted:
-        (layoutSize: IntSize, startedPosition: Offset, pointersDown: Int) -> Unit,
+        (startedPosition: Offset, overSlop: Float, pointersDown: Int) -> Unit,
     private val onDragDelta: (Float) -> Unit,
     private val onDragStopped: (velocity: Float) -> Unit,
 ) : ModifierNodeElement<MultiPointerDraggableNode>() {
@@ -114,7 +114,7 @@
     orientation: Orientation,
     enabled: Boolean,
     var startDragImmediately: Boolean,
-    var onDragStarted: (layoutSize: IntSize, startedPosition: Offset, pointersDown: Int) -> Unit,
+    var onDragStarted: (startedPosition: Offset, overSlop: Float, pointersDown: Int) -> Unit,
     var onDragDelta: (Float) -> Unit,
     var onDragStopped: (velocity: Float) -> Unit,
 ) : PointerInputModifierNode, DelegatingNode(), CompositionLocalConsumerModifierNode {
@@ -153,9 +153,9 @@
             return
         }
 
-        val onDragStart: (Offset, Int) -> Unit = { startedPosition, pointersDown ->
+        val onDragStart: (Offset, Float, Int) -> Unit = { startedPosition, overSlop, pointersDown ->
             velocityTracker.resetTracking()
-            onDragStarted(size, startedPosition, pointersDown)
+            onDragStarted(startedPosition, overSlop, pointersDown)
         }
 
         val onDragCancel: () -> Unit = { onDragStopped(/* velocity= */ 0f) }
@@ -203,7 +203,7 @@
 private suspend fun PointerInputScope.detectDragGestures(
     orientation: Orientation,
     startDragImmediately: () -> Boolean,
-    onDragStart: (startedPosition: Offset, pointersDown: Int) -> Unit,
+    onDragStart: (startedPosition: Offset, overSlop: Float, pointersDown: Int) -> Unit,
     onDragEnd: () -> Unit,
     onDragCancel: () -> Unit,
     onDrag: (change: PointerInputChange, dragAmount: Float) -> Unit,
@@ -241,7 +241,7 @@
                 }
             }
 
-            onDragStart(drag.position, pressed.size)
+            onDragStart(drag.position, overSlop, pressed.size)
             onDrag(drag, overSlop)
 
             val successful =
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
index 2986504..e78f326 100644
--- 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
@@ -44,22 +44,22 @@
      * 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 overscroll effect between scenes.
+     * 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.
      */
-    EdgeNoOverscroll(canStartOnPostFling = false),
+    EdgeNoPreview(canStartOnPostFling = false),
 
     /**
      * 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 an overscroll effect between scenes.
+     * 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.
      */
-    EdgeWithOverscroll(canStartOnPostFling = true),
+    EdgeWithPreview(canStartOnPostFling = true),
 
     /**
      * Any overscroll will be used by the [SceneTransitionLayout] to move to the next scene.
@@ -67,43 +67,43 @@
      * In addition, during scene transitions, scroll events are consumed by the
      * [SceneTransitionLayout] instead of the scrollable component.
      */
-    Always(canStartOnPostFling = true),
+    EdgeAlways(canStartOnPostFling = true),
 }
 
 internal fun Modifier.nestedScrollToScene(
     layoutImpl: SceneTransitionLayoutImpl,
     orientation: Orientation,
-    startBehavior: NestedScrollBehavior,
-    endBehavior: NestedScrollBehavior,
+    topOrLeftBehavior: NestedScrollBehavior,
+    bottomOrRightBehavior: NestedScrollBehavior,
 ) =
     this then
         NestedScrollToSceneElement(
             layoutImpl = layoutImpl,
             orientation = orientation,
-            startBehavior = startBehavior,
-            endBehavior = endBehavior,
+            topOrLeftBehavior = topOrLeftBehavior,
+            bottomOrRightBehavior = bottomOrRightBehavior,
         )
 
 private data class NestedScrollToSceneElement(
     private val layoutImpl: SceneTransitionLayoutImpl,
     private val orientation: Orientation,
-    private val startBehavior: NestedScrollBehavior,
-    private val endBehavior: NestedScrollBehavior,
+    private val topOrLeftBehavior: NestedScrollBehavior,
+    private val bottomOrRightBehavior: NestedScrollBehavior,
 ) : ModifierNodeElement<NestedScrollToSceneNode>() {
     override fun create() =
         NestedScrollToSceneNode(
             layoutImpl = layoutImpl,
             orientation = orientation,
-            startBehavior = startBehavior,
-            endBehavior = endBehavior,
+            topOrLeftBehavior = topOrLeftBehavior,
+            bottomOrRightBehavior = bottomOrRightBehavior,
         )
 
     override fun update(node: NestedScrollToSceneNode) {
         node.update(
             layoutImpl = layoutImpl,
             orientation = orientation,
-            startBehavior = startBehavior,
-            endBehavior = endBehavior,
+            topOrLeftBehavior = topOrLeftBehavior,
+            bottomOrRightBehavior = bottomOrRightBehavior,
         )
     }
 
@@ -111,23 +111,23 @@
         name = "nestedScrollToScene"
         properties["layoutImpl"] = layoutImpl
         properties["orientation"] = orientation
-        properties["startBehavior"] = startBehavior
-        properties["endBehavior"] = endBehavior
+        properties["topOrLeftBehavior"] = topOrLeftBehavior
+        properties["bottomOrRightBehavior"] = bottomOrRightBehavior
     }
 }
 
 private class NestedScrollToSceneNode(
     layoutImpl: SceneTransitionLayoutImpl,
     orientation: Orientation,
-    startBehavior: NestedScrollBehavior,
-    endBehavior: NestedScrollBehavior,
+    topOrLeftBehavior: NestedScrollBehavior,
+    bottomOrRightBehavior: NestedScrollBehavior,
 ) : DelegatingNode() {
     private var priorityNestedScrollConnection: PriorityNestedScrollConnection =
         scenePriorityNestedScrollConnection(
             layoutImpl = layoutImpl,
             orientation = orientation,
-            startBehavior = startBehavior,
-            endBehavior = endBehavior,
+            topOrLeftBehavior = topOrLeftBehavior,
+            bottomOrRightBehavior = bottomOrRightBehavior,
         )
 
     private var nestedScrollNode: DelegatableNode =
@@ -148,8 +148,8 @@
     fun update(
         layoutImpl: SceneTransitionLayoutImpl,
         orientation: Orientation,
-        startBehavior: NestedScrollBehavior,
-        endBehavior: NestedScrollBehavior,
+        topOrLeftBehavior: NestedScrollBehavior,
+        bottomOrRightBehavior: NestedScrollBehavior,
     ) {
         // Clean up the old nested scroll connection
         priorityNestedScrollConnection.reset()
@@ -160,8 +160,8 @@
             scenePriorityNestedScrollConnection(
                 layoutImpl = layoutImpl,
                 orientation = orientation,
-                startBehavior = startBehavior,
-                endBehavior = endBehavior,
+                topOrLeftBehavior = topOrLeftBehavior,
+                bottomOrRightBehavior = bottomOrRightBehavior,
             )
         nestedScrollNode =
             nestedScrollModifierNode(
@@ -175,12 +175,13 @@
 private fun scenePriorityNestedScrollConnection(
     layoutImpl: SceneTransitionLayoutImpl,
     orientation: Orientation,
-    startBehavior: NestedScrollBehavior,
-    endBehavior: NestedScrollBehavior,
+    topOrLeftBehavior: NestedScrollBehavior,
+    bottomOrRightBehavior: NestedScrollBehavior,
 ) =
     SceneNestedScrollHandler(
-            gestureHandler = layoutImpl.gestureHandler(orientation = orientation),
-            startBehavior = startBehavior,
-            endBehavior = endBehavior,
+            layoutImpl = layoutImpl,
+            orientation = orientation,
+            topOrLeftBehavior = topOrLeftBehavior,
+            bottomOrRightBehavior = bottomOrRightBehavior,
         )
         .connection
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ObservableTransitionState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ObservableTransitionState.kt
index 1b79dbd..983cff8 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ObservableTransitionState.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ObservableTransitionState.kt
@@ -73,17 +73,13 @@
             when (val state = transitionState) {
                 is TransitionState.Idle -> ObservableTransitionState.Idle(state.currentScene)
                 is TransitionState.Transition -> {
-                    if (state.fromScene == state.toScene) {
-                        ObservableTransitionState.Idle(state.currentScene)
-                    } else {
-                        ObservableTransitionState.Transition(
-                            fromScene = state.fromScene,
-                            toScene = state.toScene,
-                            progress = snapshotFlow { state.progress },
-                            isInitiatedByUserInput = state.isInitiatedByUserInput,
-                            isUserInputOngoing = snapshotFlow { state.isUserInputOngoing },
-                        )
-                    }
+                    ObservableTransitionState.Transition(
+                        fromScene = state.fromScene,
+                        toScene = state.toScene,
+                        progress = snapshotFlow { state.progress },
+                        isInitiatedByUserInput = state.isInitiatedByUserInput,
+                        isUserInputOngoing = snapshotFlow { state.isUserInputOngoing },
+                    )
                 }
             }
         }
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Scene.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Scene.kt
index f5561cb..6a7a3a0 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Scene.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Scene.kt
@@ -86,16 +86,26 @@
         return element(layoutImpl, scene, key)
     }
 
-    override fun Modifier.nestedScrollToScene(
-        orientation: Orientation,
-        startBehavior: NestedScrollBehavior,
-        endBehavior: NestedScrollBehavior,
+    override fun Modifier.horizontalNestedScrollToScene(
+        leftBehavior: NestedScrollBehavior,
+        rightBehavior: NestedScrollBehavior,
     ): Modifier =
         nestedScrollToScene(
             layoutImpl = layoutImpl,
-            orientation = orientation,
-            startBehavior = startBehavior,
-            endBehavior = endBehavior,
+            orientation = Orientation.Horizontal,
+            topOrLeftBehavior = leftBehavior,
+            bottomOrRightBehavior = rightBehavior,
+        )
+
+    override fun Modifier.verticalNestedScrollToScene(
+        topBehavior: NestedScrollBehavior,
+        bottomBehavior: NestedScrollBehavior
+    ): Modifier =
+        nestedScrollToScene(
+            layoutImpl = layoutImpl,
+            orientation = Orientation.Vertical,
+            topOrLeftBehavior = topBehavior,
+            bottomOrRightBehavior = bottomBehavior,
         )
 
     @Composable
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneGestureHandler.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneGestureHandler.kt
index b00c886..338557d 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneGestureHandler.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneGestureHandler.kt
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+@file:Suppress("NOTHING_TO_INLINE")
+
 package com.android.compose.animation.scene
 
 import android.util.Log
@@ -26,7 +28,6 @@
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.unit.IntSize
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.round
 import com.android.compose.nestedscroll.PriorityNestedScrollConnection
@@ -40,103 +41,89 @@
     internal val orientation: Orientation,
     private val coroutineScope: CoroutineScope,
 ) {
+    private val layoutState = layoutImpl.state
     val draggable: DraggableHandler = SceneDraggableHandler(this)
 
-    internal var transitionState
-        get() = layoutImpl.state.transitionState
+    private var _swipeTransition: SwipeTransition? = null
+    internal var swipeTransition: SwipeTransition
+        get() = _swipeTransition ?: error("SwipeTransition needs to be initialized")
         set(value) {
-            layoutImpl.state.transitionState = value
+            _swipeTransition = value
         }
 
-    /**
-     * The transition controlled by this gesture handler. It will be set as the [transitionState] in
-     * the [SceneTransitionLayoutImpl] whenever this handler is driving the current transition.
-     *
-     * Note: the initialScene here does not matter, it's only used for initializing the transition
-     * and will be replaced when a drag event starts.
-     */
-    internal val swipeTransition = SwipeTransition(initialScene = currentScene)
-
-    internal val currentScene: Scene
-        get() = layoutImpl.scene(transitionState.currentScene)
+    private fun updateTransition(newTransition: SwipeTransition, force: Boolean = false) {
+        if (isDrivingTransition || force) layoutState.startTransition(newTransition)
+        swipeTransition = newTransition
+    }
 
     internal val isDrivingTransition
-        get() = transitionState == swipeTransition
-
-    internal var isAnimatingOffset
-        get() = swipeTransition.isAnimatingOffset
-        private set(value) {
-            swipeTransition.isAnimatingOffset = value
-        }
-
-    internal val swipeTransitionToScene
-        get() = swipeTransition._toScene
+        get() = layoutState.transitionState == _swipeTransition
 
     /**
      * The velocity threshold at which the intent of the user is to swipe up or down. It is the same
      * as SwipeableV2Defaults.VelocityThreshold.
      */
-    internal val velocityThreshold = with(layoutImpl.density) { 125.dp.toPx() }
+    internal val velocityThreshold: Float
+        get() = with(layoutImpl.density) { 125.dp.toPx() }
 
     /**
      * The positional threshold at which the intent of the user is to swipe to the next scene. It is
      * the same as SwipeableV2Defaults.PositionalThreshold.
      */
-    private val positionalThreshold = with(layoutImpl.density) { 56.dp.toPx() }
+    private val positionalThreshold
+        get() = with(layoutImpl.density) { 56.dp.toPx() }
 
     internal var gestureWithPriority: Any? = null
 
-    internal fun onDragStarted(pointersDown: Int, layoutSize: IntSize, startedPosition: Offset?) {
+    /** The [UserAction]s associated to the current swipe. */
+    private var actionUpOrLeft: UserAction? = null
+    private var actionDownOrRight: UserAction? = null
+    private var actionUpOrLeftNoEdge: UserAction? = null
+    private var actionDownOrRightNoEdge: UserAction? = null
+    private var upOrLeftScene: SceneKey? = null
+    private var downOrRightScene: SceneKey? = null
+
+    internal fun onDragStarted(pointersDown: Int, startedPosition: Offset?, overSlop: Float) {
         if (isDrivingTransition) {
             // This [transition] was already driving the animation: simply take over it.
             // Stop animating and start from where the current offset.
-            swipeTransition.stopOffsetAnimation()
+            swipeTransition.cancelOffsetAnimation()
+            updateTargetScenes(swipeTransition._fromScene)
             return
         }
 
-        val transition = transitionState
-        if (transition is TransitionState.Transition) {
+        val transitionState = layoutState.transitionState
+        if (transitionState is TransitionState.Transition) {
             // TODO(b/290184746): Better handle interruptions here if state != idle.
             Log.w(
                 TAG,
                 "start from TransitionState.Transition is not fully supported: from" +
-                    " ${transition.fromScene} to ${transition.toScene} " +
-                    "(progress ${transition.progress})"
+                    " ${transitionState.fromScene} to ${transitionState.toScene} " +
+                    "(progress ${transitionState.progress})"
             )
         }
 
-        val fromScene = currentScene
+        val fromScene = layoutImpl.scene(transitionState.currentScene)
+        setCurrentActions(fromScene, startedPosition, pointersDown)
 
-        swipeTransition._currentScene = fromScene
-        swipeTransition._fromScene = fromScene
+        val (targetScene, distance) =
+            findTargetSceneAndDistance(fromScene, overSlop, updateScenes = true) ?: return
 
-        // We don't know where we are transitioning to yet given that the drag just started, so set
-        // it to fromScene, which will effectively be treated the same as Idle(fromScene).
-        swipeTransition._toScene = fromScene
+        updateTransition(SwipeTransition(fromScene, targetScene, distance), force = true)
+    }
 
-        swipeTransition.stopOffsetAnimation()
-        swipeTransition.dragOffset = 0f
-
-        // Use the layout size in the swipe orientation for swipe distance.
-        // TODO(b/290184746): Also handle custom distances for transitions. With smaller distances,
-        // we will also have to make sure that we correctly handle overscroll.
-        swipeTransition.absoluteDistance =
-            when (orientation) {
-                Orientation.Horizontal -> layoutSize.width
-                Orientation.Vertical -> layoutSize.height
-            }.toFloat()
-
+    private fun setCurrentActions(fromScene: Scene, startedPosition: Offset?, pointersDown: Int) {
         val fromEdge =
             startedPosition?.let { position ->
                 layoutImpl.edgeDetector.edge(
-                    layoutSize,
+                    fromScene.targetSize,
                     position.round(),
                     layoutImpl.density,
                     orientation,
                 )
             }
 
-        swipeTransition.actionUpOrLeft =
+        val upOrLeft =
             Swipe(
                 direction =
                     when (orientation) {
@@ -147,7 +134,7 @@
                 fromEdge = fromEdge,
             )
 
-        swipeTransition.actionDownOrRight =
+        val downOrRight =
             Swipe(
                 direction =
                     when (orientation) {
@@ -159,108 +146,158 @@
             )
 
         if (fromEdge == null) {
-            swipeTransition.actionUpOrLeftNoEdge = null
-            swipeTransition.actionDownOrRightNoEdge = null
+            actionUpOrLeft = null
+            actionDownOrRight = null
+            actionUpOrLeftNoEdge = upOrLeft
+            actionDownOrRightNoEdge = downOrRight
         } else {
-            swipeTransition.actionUpOrLeftNoEdge =
-                (swipeTransition.actionUpOrLeft as Swipe).copy(fromEdge = null)
-            swipeTransition.actionDownOrRightNoEdge =
-                (swipeTransition.actionDownOrRight as Swipe).copy(fromEdge = null)
-        }
-
-        if (swipeTransition.absoluteDistance > 0f) {
-            transitionState = swipeTransition
+            actionUpOrLeft = upOrLeft
+            actionDownOrRight = downOrRight
+            actionUpOrLeftNoEdge = upOrLeft.copy(fromEdge = null)
+            actionDownOrRightNoEdge = downOrRight.copy(fromEdge = null)
         }
     }
 
-    internal fun onDrag(delta: Float) {
-        if (delta == 0f) return
+    /**
+     * Use the layout size in the swipe orientation for swipe distance.
+     *
+     * TODO(b/290184746): Also handle custom distances for transitions. With smaller distances, we
+     *   will also have to make sure that we correctly handle overscroll.
+     */
+    private fun Scene.getAbsoluteDistance(): Float {
+        return when (orientation) {
+            Orientation.Horizontal -> targetSize.width
+            Orientation.Vertical -> targetSize.height
+        }.toFloat()
+    }
 
+    internal fun onDrag(delta: Float) {
+        if (delta == 0f || !isDrivingTransition) return
         swipeTransition.dragOffset += delta
 
-        // First check transition.fromScene should be changed for the case where the user quickly
-        // swiped twice in a row to accelerate the transition and go from A => B then B => C really
-        // fast.
-        maybeHandleAcceleratedSwipe()
+        val (fromScene, acceleratedOffset) =
+            computeFromSceneConsideringAcceleratedSwipe(swipeTransition)
 
-        val offset = swipeTransition.dragOffset
-        val fromScene = swipeTransition._fromScene
+        val isNewFromScene = fromScene.key != swipeTransition.fromScene
+        val (targetScene, distance) =
+            findTargetSceneAndDistance(
+                fromScene,
+                swipeTransition.dragOffset,
+                updateScenes = isNewFromScene,
+            )
+                ?: run {
+                    onDragStopped(delta, true)
+                    return
+                }
+        swipeTransition.dragOffset += acceleratedOffset
 
-        // Compute the target scene depending on the current offset.
-        val target = fromScene.findTargetSceneAndDistance(offset)
-
-        if (swipeTransition._toScene.key != target.sceneKey) {
-            swipeTransition._toScene = layoutImpl.scenes.getValue(target.sceneKey)
+        if (isNewFromScene || targetScene.key != swipeTransition.toScene) {
+            updateTransition(
+                SwipeTransition(fromScene, targetScene, distance).apply {
+                    this.dragOffset = swipeTransition.dragOffset
+                }
+            )
         }
+    }
 
-        if (swipeTransition._distance != target.distance) {
-            swipeTransition._distance = target.distance
-        }
+    private fun updateTargetScenes(fromScene: Scene) {
+        upOrLeftScene = fromScene.upOrLeft()
+        downOrRightScene = fromScene.downOrRight()
     }
 
     /**
      * Change fromScene in the case where the user quickly swiped multiple times in the same
      * direction to accelerate the transition from A => B then B => C.
+     *
+     * @return the new fromScene and a dragOffset to be added in case the scene has changed
+     *
+     * TODO(b/290184746): the second drag needs to pass B to work. Add support for flinging twice
+     *   before B has been reached
      */
-    private fun maybeHandleAcceleratedSwipe() {
+    private inline fun computeFromSceneConsideringAcceleratedSwipe(
+        swipeTransition: SwipeTransition,
+    ): Pair<Scene, Float> {
         val toScene = swipeTransition._toScene
         val fromScene = swipeTransition._fromScene
+        val absoluteDistance = swipeTransition.distance.absoluteValue
 
         // If the swipe was not committed, don't do anything.
-        if (fromScene == toScene || swipeTransition._currentScene != toScene) {
-            return
+        if (swipeTransition._currentScene != toScene) {
+            return Pair(fromScene, 0f)
         }
 
         // If the offset is past the distance then let's change fromScene so that the user can swipe
         // to the next screen or go back to the previous one.
         val offset = swipeTransition.dragOffset
-        val absoluteDistance = swipeTransition.absoluteDistance
-        if (offset <= -absoluteDistance && swipeTransition.upOrLeft(fromScene) == toScene.key) {
-            swipeTransition.dragOffset += absoluteDistance
-            swipeTransition._fromScene = toScene
-        } else if (
-            offset >= absoluteDistance && swipeTransition.downOrRight(fromScene) == toScene.key
-        ) {
-            swipeTransition.dragOffset -= absoluteDistance
-            swipeTransition._fromScene = toScene
+        return if (offset <= -absoluteDistance && upOrLeftScene == toScene.key) {
+            Pair(toScene, absoluteDistance)
+        } else if (offset >= absoluteDistance && downOrRightScene == toScene.key) {
+            Pair(toScene, -absoluteDistance)
+        } else {
+            Pair(fromScene, 0f)
         }
-
-        // Important note: toScene and distance will be updated right after this function is called,
-        // using fromScene and dragOffset.
     }
 
-    private class TargetScene(
-        val sceneKey: SceneKey,
-        val distance: Float,
-    )
-
-    private fun Scene.findTargetSceneAndDistance(directionOffset: Float): TargetScene {
-        val upOrLeft = swipeTransition.upOrLeft(this)
-        val downOrRight = swipeTransition.downOrRight(this)
+    /**
+     * Returns the target scene and distance from [fromScene] in the direction [directionOffset].
+     *
+     * @param fromScene the scene from which we look for the target
+     * @param directionOffset signed float that indicates the direction. Positive is down or right
+     *   negative is up or left.
+     * @param updateScenes whether the target scenes should be updated to the current values held in
+     *   the Scenes map. Usually we don't want to update them while doing a drag, because this could
+     *   change the target scene (jump cutting) to a different scene, when some system state changed
+     *   the targets the background. However, an update is needed any time we calculate the targets
+     *   for a new fromScene.
+     * @return null when there are no targets in either direction. If one direction is null and you
+     *   drag into the null direction this function will return the opposite direction, assuming
+     *   that the users intention is to start the drag into the other direction eventually. If
+     *   [directionOffset] is 0f and both direction are available, it will default to
+     *   [upOrLeftScene].
+     */
+    private inline fun findTargetSceneAndDistance(
+        fromScene: Scene,
+        directionOffset: Float,
+        updateScenes: Boolean,
+    ): Pair<Scene, Float>? {
+        if (updateScenes) updateTargetScenes(fromScene)
+        val absoluteDistance = fromScene.getAbsoluteDistance()
 
         // Compute the target scene depending on the current offset.
         return when {
-            directionOffset < 0f && upOrLeft != null -> {
-                TargetScene(
-                    sceneKey = upOrLeft,
-                    distance = -swipeTransition.absoluteDistance,
-                )
-            }
-            directionOffset > 0f && downOrRight != null -> {
-                TargetScene(
-                    sceneKey = downOrRight,
-                    distance = swipeTransition.absoluteDistance,
-                )
-            }
-            else -> {
-                TargetScene(
-                    sceneKey = key,
-                    distance = 0f,
-                )
-            }
+            upOrLeftScene == null && downOrRightScene == null -> null
+            (directionOffset < 0f && upOrLeftScene != null) || downOrRightScene == null ->
+                Pair(layoutImpl.scene(upOrLeftScene!!), -absoluteDistance)
+            else -> Pair(layoutImpl.scene(downOrRightScene!!), absoluteDistance)
         }
     }
 
+    /**
+     * A strict version of [findTargetSceneAndDistance] that will return null when there is no Scene
+     * in [directionOffset] direction
+     */
+    private inline fun findTargetSceneAndDistanceStrict(
+        fromScene: Scene,
+        directionOffset: Float,
+    ): Pair<Scene, Float>? {
+        val absoluteDistance = fromScene.getAbsoluteDistance()
+        return when {
+            directionOffset > 0f ->
+                upOrLeftScene?.let { Pair(layoutImpl.scene(it), -absoluteDistance) }
+            directionOffset < 0f ->
+                downOrRightScene?.let { Pair(layoutImpl.scene(it), absoluteDistance) }
+            else -> null
+        }
+    }
+
+    private fun Scene.upOrLeft(): SceneKey? {
+        return userActions[actionUpOrLeft] ?: userActions[actionUpOrLeftNoEdge]
+    }
+
+    private fun Scene.downOrRight(): SceneKey? {
+        return userActions[actionDownOrRight] ?: userActions[actionDownOrRightNoEdge]
+    }
+
     internal fun onDragStopped(velocity: Float, canChangeScene: Boolean) {
         // The state was changed since the drag started; don't do anything.
         if (!isDrivingTransition) {
@@ -291,11 +328,6 @@
             // velocity and offset of the transition, then we launch the animation.
 
             val toScene = swipeTransition._toScene
-            if (fromScene == toScene) {
-                // We were not animating.
-                transitionState = TransitionState.Idle(fromScene.key)
-                return
-            }
 
             // Compute the destination scene (and therefore offset) to settle in.
             val offset = swipeTransition.dragOffset
@@ -321,18 +353,21 @@
             val startFromIdlePosition = swipeTransition.dragOffset == 0f
 
             if (startFromIdlePosition) {
-                // If there is a next scene, we start the overscroll animation.
-                val target = fromScene.findTargetSceneAndDistance(velocity)
-                val isValidTarget = target.distance != 0f && target.sceneKey != fromScene.key
-                if (isValidTarget) {
-                    swipeTransition._toScene = layoutImpl.scene(target.sceneKey)
-                    swipeTransition._distance = target.distance
+                // If there is a target scene, we start the overscroll animation.
+                val (targetScene, distance) =
+                    findTargetSceneAndDistanceStrict(fromScene, velocity)
+                        ?: run {
+                            // We will not animate
+                            layoutState.finishTransition(swipeTransition, idleScene = fromScene.key)
+                            return
+                        }
 
-                    animateTo(targetScene = fromScene, targetOffset = 0f)
-                } else {
-                    // We will not animate
-                    transitionState = TransitionState.Idle(fromScene.key)
-                }
+                updateTransition(
+                    SwipeTransition(fromScene, targetScene, distance).apply {
+                        _currentScene = swipeTransition._currentScene
+                    }
+                )
+                animateTo(targetScene = fromScene, targetOffset = 0f)
             } else {
                 // We were between two scenes: animate to the initial scene.
                 animateTo(targetScene = fromScene, targetOffset = 0f)
@@ -382,10 +417,10 @@
     ) {
         swipeTransition.startOffsetAnimation {
             coroutineScope.launch {
-                if (!isAnimatingOffset) {
+                if (!swipeTransition.isAnimatingOffset) {
                     swipeTransition.offsetAnimatable.snapTo(swipeTransition.dragOffset)
                 }
-                isAnimatingOffset = true
+                swipeTransition.isAnimatingOffset = true
 
                 swipeTransition.offsetAnimatable.animateTo(
                     targetOffset,
@@ -397,42 +432,28 @@
                     initialVelocity = initialVelocity,
                 )
 
-                isAnimatingOffset = false
-
-                // Now that the animation is done, the state should be idle. Note that if the state
-                // was changed since this animation started, some external code changed it and we
-                // shouldn't do anything here. Note also that this job will be cancelled in the case
-                // where the user intercepts this swipe.
-                if (isDrivingTransition) {
-                    transitionState = TransitionState.Idle(targetScene)
-                }
+                swipeTransition.finishOffsetAnimation()
+                layoutState.finishTransition(swipeTransition, targetScene)
             }
         }
     }
 
-    internal class SwipeTransition(initialScene: Scene) : TransitionState.Transition {
-        var _currentScene by mutableStateOf(initialScene)
+    internal class SwipeTransition(
+        val _fromScene: Scene,
+        val _toScene: Scene,
+        /**
+         * The signed distance between [fromScene] and [toScene]. It is negative if [fromScene] is
+         * above or to the left of [toScene].
+         */
+        val distance: Float
+    ) : TransitionState.Transition(_fromScene.key, _toScene.key) {
+        var _currentScene by mutableStateOf(_fromScene)
         override val currentScene: SceneKey
             get() = _currentScene.key
 
-        var _fromScene by mutableStateOf(initialScene)
-        override val fromScene: SceneKey
-            get() = _fromScene.key
-
-        var _toScene by mutableStateOf(initialScene)
-        override val toScene: SceneKey
-            get() = _toScene.key
-
         override val progress: Float
             get() {
                 val offset = if (isAnimatingOffset) offsetAnimatable.value else dragOffset
-                if (distance == 0f) {
-                    // This can happen only if fromScene == toScene.
-                    error(
-                        "Transition.progress should be called only when Transition.fromScene != " +
-                            "Transition.toScene"
-                    )
-                }
                 return offset / distance
             }
 
@@ -459,46 +480,22 @@
 
         /** Ends any previous [offsetAnimationJob] and runs the new [job]. */
         fun startOffsetAnimation(job: () -> Job) {
-            stopOffsetAnimation()
+            cancelOffsetAnimation()
             offsetAnimationJob = job()
         }
 
-        /** Stops any ongoing offset animation. */
-        fun stopOffsetAnimation() {
+        /** Cancel any ongoing offset animation. */
+        fun cancelOffsetAnimation() {
             offsetAnimationJob?.cancel()
+            finishOffsetAnimation()
+        }
 
+        fun finishOffsetAnimation() {
             if (isAnimatingOffset) {
                 isAnimatingOffset = false
                 dragOffset = offsetAnimatable.value
             }
         }
-
-        /** The absolute distance between [fromScene] and [toScene]. */
-        var absoluteDistance = 0f
-
-        /**
-         * The signed distance between [fromScene] and [toScene]. It is negative if [fromScene] is
-         * above or to the left of [toScene].
-         */
-        var _distance by mutableFloatStateOf(0f)
-        val distance: Float
-            get() = _distance
-
-        /** The [UserAction]s associated to this swipe. */
-        var actionUpOrLeft: UserAction = Back
-        var actionDownOrRight: UserAction = Back
-        var actionUpOrLeftNoEdge: UserAction? = null
-        var actionDownOrRightNoEdge: UserAction? = null
-
-        fun upOrLeft(scene: Scene): SceneKey? {
-            return scene.userActions[actionUpOrLeft]
-                ?: actionUpOrLeftNoEdge?.let { scene.userActions[it] }
-        }
-
-        fun downOrRight(scene: Scene): SceneKey? {
-            return scene.userActions[actionDownOrRight]
-                ?: actionDownOrRightNoEdge?.let { scene.userActions[it] }
-        }
     }
 
     companion object {
@@ -509,9 +506,9 @@
 private class SceneDraggableHandler(
     private val gestureHandler: SceneGestureHandler,
 ) : DraggableHandler {
-    override fun onDragStarted(layoutSize: IntSize, startedPosition: Offset, pointersDown: Int) {
+    override fun onDragStarted(startedPosition: Offset, overSlop: Float, pointersDown: Int) {
         gestureHandler.gestureWithPriority = this
-        gestureHandler.onDragStarted(pointersDown, layoutSize, startedPosition)
+        gestureHandler.onDragStarted(pointersDown, startedPosition, overSlop)
     }
 
     override fun onDelta(pixels: Float) {
@@ -529,10 +526,14 @@
 }
 
 internal class SceneNestedScrollHandler(
-    private val gestureHandler: SceneGestureHandler,
-    private val startBehavior: NestedScrollBehavior,
-    private val endBehavior: NestedScrollBehavior,
+    private val layoutImpl: SceneTransitionLayoutImpl,
+    private val orientation: Orientation,
+    private val topOrLeftBehavior: NestedScrollBehavior,
+    private val bottomOrRightBehavior: NestedScrollBehavior,
 ) : NestedScrollHandler {
+    private val layoutState = layoutImpl.state
+    private val gestureHandler = layoutImpl.gestureHandler(orientation)
+
     override val connection: PriorityNestedScrollConnection = nestedScrollConnection()
 
     private fun nestedScrollConnection(): PriorityNestedScrollConnection {
@@ -543,7 +544,7 @@
         val actionUpOrLeft =
             Swipe(
                 direction =
-                    when (gestureHandler.orientation) {
+                    when (orientation) {
                         Orientation.Horizontal -> SwipeDirection.Left
                         Orientation.Vertical -> SwipeDirection.Up
                     },
@@ -553,7 +554,7 @@
         val actionDownOrRight =
             Swipe(
                 direction =
-                    when (gestureHandler.orientation) {
+                    when (orientation) {
                         Orientation.Horizontal -> SwipeDirection.Right
                         Orientation.Vertical -> SwipeDirection.Down
                     },
@@ -561,7 +562,7 @@
             )
 
         fun hasNextScene(amount: Float): Boolean {
-            val fromScene = gestureHandler.currentScene
+            val fromScene = layoutImpl.scene(layoutState.transitionState.currentScene)
             val nextScene =
                 when {
                     amount < 0f -> fromScene.userActions[actionUpOrLeft]
@@ -572,7 +573,7 @@
         }
 
         return PriorityNestedScrollConnection(
-            orientation = gestureHandler.orientation,
+            orientation = orientation,
             canStartPreScroll = { offsetAvailable, offsetBeforeStart ->
                 canChangeScene = offsetBeforeStart == 0f
 
@@ -580,8 +581,9 @@
                     canChangeScene && gestureHandler.isDrivingTransition && offsetAvailable != 0f
                 if (!canInterceptSwipeTransition) return@PriorityNestedScrollConnection false
 
-                val progress = gestureHandler.swipeTransition.progress
-                val threshold = gestureHandler.layoutImpl.transitionInterceptionThreshold
+                val swipeTransition = gestureHandler.swipeTransition
+                val progress = swipeTransition.progress
+                val threshold = layoutImpl.transitionInterceptionThreshold
                 fun isProgressCloseTo(value: Float) = (progress - value).absoluteValue <= threshold
 
                 // The transition is always between 0 and 1. If it is close to either of these
@@ -589,9 +591,8 @@
                 // The progress value can go beyond this range in the case of overscroll.
                 val shouldSnapToIdle = isProgressCloseTo(0f) || isProgressCloseTo(1f)
                 if (shouldSnapToIdle) {
-                    gestureHandler.swipeTransition.stopOffsetAnimation()
-                    gestureHandler.transitionState =
-                        TransitionState.Idle(gestureHandler.swipeTransition.currentScene)
+                    swipeTransition.cancelOffsetAnimation()
+                    layoutState.finishTransition(swipeTransition, swipeTransition.currentScene)
                 }
 
                 // Start only if we cannot consume this event
@@ -600,8 +601,8 @@
             canStartPostScroll = { offsetAvailable, offsetBeforeStart ->
                 val behavior: NestedScrollBehavior =
                     when {
-                        offsetAvailable > 0f -> startBehavior
-                        offsetAvailable < 0f -> endBehavior
+                        offsetAvailable > 0f -> topOrLeftBehavior
+                        offsetAvailable < 0f -> bottomOrRightBehavior
                         else -> return@PriorityNestedScrollConnection false
                     }
 
@@ -612,15 +613,15 @@
                         canChangeScene = false // unused: added for consistency
                         false
                     }
-                    NestedScrollBehavior.EdgeNoOverscroll -> {
+                    NestedScrollBehavior.EdgeNoPreview -> {
                         canChangeScene = isZeroOffset
                         isZeroOffset && hasNextScene(offsetAvailable)
                     }
-                    NestedScrollBehavior.EdgeWithOverscroll -> {
+                    NestedScrollBehavior.EdgeWithPreview -> {
                         canChangeScene = isZeroOffset
                         hasNextScene(offsetAvailable)
                     }
-                    NestedScrollBehavior.Always -> {
+                    NestedScrollBehavior.EdgeAlways -> {
                         canChangeScene = true
                         hasNextScene(offsetAvailable)
                     }
@@ -629,8 +630,8 @@
             canStartPostFling = { velocityAvailable ->
                 val behavior: NestedScrollBehavior =
                     when {
-                        velocityAvailable > 0f -> startBehavior
-                        velocityAvailable < 0f -> endBehavior
+                        velocityAvailable > 0f -> topOrLeftBehavior
+                        velocityAvailable < 0f -> bottomOrRightBehavior
                         else -> return@PriorityNestedScrollConnection false
                     }
 
@@ -639,12 +640,13 @@
                 behavior.canStartOnPostFling && hasNextScene(velocityAvailable)
             },
             canContinueScroll = { true },
-            onStart = {
+            canScrollOnFling = false,
+            onStart = { offsetAvailable ->
                 gestureHandler.gestureWithPriority = this
                 gestureHandler.onDragStarted(
                     pointersDown = 1,
-                    layoutSize = gestureHandler.currentScene.targetSize,
                     startedPosition = null,
+                    overSlop = offsetAvailable,
                 )
             },
             onScroll = { offsetAvailable ->
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 07add77..3608e37 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
@@ -19,6 +19,8 @@
 import androidx.annotation.FloatRange
 import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.SideEffect
 import androidx.compose.runtime.Stable
 import androidx.compose.runtime.State
 import androidx.compose.runtime.remember
@@ -27,6 +29,7 @@
 import androidx.compose.ui.graphics.Shape
 import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
 import androidx.compose.ui.platform.LocalDensity
+import kotlinx.coroutines.channels.Channel
 
 /**
  * [SceneTransitionLayout] is a container that automatically animates its content whenever
@@ -126,14 +129,24 @@
      * Adds a [NestedScrollConnection] to intercept scroll events not handled by the scrollable
      * component.
      *
-     * @param orientation is used to determine if we handle top/bottom or left/right events.
-     * @param startBehavior when we should perform the overscroll animation at the top/left.
-     * @param endBehavior when we should perform the overscroll animation at the bottom/right.
+     * @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.nestedScrollToScene(
-        orientation: Orientation,
-        startBehavior: NestedScrollBehavior = NestedScrollBehavior.EdgeNoOverscroll,
-        endBehavior: NestedScrollBehavior = NestedScrollBehavior.EdgeNoOverscroll,
+    fun Modifier.horizontalNestedScrollToScene(
+        leftBehavior: NestedScrollBehavior = NestedScrollBehavior.EdgeNoPreview,
+        rightBehavior: NestedScrollBehavior = NestedScrollBehavior.EdgeNoPreview,
+    ): 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.EdgeNoPreview,
+        bottomBehavior: NestedScrollBehavior = NestedScrollBehavior.EdgeNoPreview,
     ): Modifier
 
     /**
@@ -256,24 +269,45 @@
     val coroutineScope = rememberCoroutineScope()
     val layoutImpl = remember {
         SceneTransitionLayoutImpl(
+                state = state as SceneTransitionLayoutStateImpl,
                 onChangeScene = onChangeScene,
-                builder = scenes,
-                transitions = transitions,
-                state = state,
                 density = density,
                 edgeDetector = edgeDetector,
                 transitionInterceptionThreshold = transitionInterceptionThreshold,
+                builder = scenes,
                 coroutineScope = coroutineScope,
             )
             .also { onLayoutImpl?.invoke(it) }
     }
 
-    layoutImpl.onChangeScene = onChangeScene
-    layoutImpl.transitions = transitions
-    layoutImpl.density = density
-    layoutImpl.edgeDetector = edgeDetector
+    val targetSceneChannel = remember { Channel<SceneKey>(Channel.CONFLATED) }
+    SideEffect {
+        if (state != layoutImpl.state) {
+            error(
+                "This SceneTransitionLayout was bound to a different SceneTransitionLayoutState" +
+                    " that was used when creating it, which is not supported"
+            )
+        }
 
-    layoutImpl.setScenes(scenes)
-    layoutImpl.setCurrentScene(currentScene)
+        layoutImpl.onChangeScene = onChangeScene
+        (state as SceneTransitionLayoutStateImpl).transitions = transitions
+        layoutImpl.density = density
+        layoutImpl.edgeDetector = edgeDetector
+        layoutImpl.updateScenes(scenes)
+
+        state.transitions = transitions
+
+        targetSceneChannel.trySend(currentScene)
+    }
+
+    LaunchedEffect(targetSceneChannel) {
+        for (newKey in targetSceneChannel) {
+            // Inspired by AnimateAsState.kt: let's poll the last value to avoid being one frame
+            // late.
+            val newKey = targetSceneChannel.tryReceive().getOrNull() ?: newKey
+            animateToScene(layoutImpl.state, newKey)
+        }
+    }
+
     layoutImpl.Content(modifier)
 }
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 02ddccb..c99c325 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
@@ -22,13 +22,8 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.DisposableEffect
 import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.SideEffect
 import androidx.compose.runtime.Stable
-import androidx.compose.runtime.getValue
 import androidx.compose.runtime.key
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
 import androidx.compose.runtime.snapshots.SnapshotStateMap
 import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.Modifier
@@ -40,36 +35,40 @@
 import androidx.compose.ui.util.fastForEach
 import com.android.compose.ui.util.lerp
 import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.channels.Channel
 
 @Stable
 internal class SceneTransitionLayoutImpl(
-    onChangeScene: (SceneKey) -> Unit,
+    internal val state: SceneTransitionLayoutStateImpl,
+    internal var onChangeScene: (SceneKey) -> Unit,
+    internal var density: Density,
+    internal var edgeDetector: EdgeDetector,
+    internal var transitionInterceptionThreshold: Float,
     builder: SceneTransitionLayoutScope.() -> Unit,
-    transitions: SceneTransitions,
-    internal val state: SceneTransitionLayoutState,
-    density: Density,
-    edgeDetector: EdgeDetector,
-    transitionInterceptionThreshold: Float,
     coroutineScope: CoroutineScope,
 ) {
-    internal val scenes = SnapshotStateMap<SceneKey, Scene>()
+    internal val scenes = mutableMapOf<SceneKey, Scene>()
+
+    /**
+     * The map of [Element]s.
+     *
+     * Note that this map is *mutated* directly during composition, so it is a [SnapshotStateMap] to
+     * make sure that mutations are reverted if composition is cancelled.
+     */
     internal val elements = SnapshotStateMap<ElementKey, Element>()
 
-    /** The scenes that are "ready", i.e. they were composed and fully laid-out at least once. */
+    /**
+     * The scenes that are "ready", i.e. they were composed and fully laid-out at least once.
+     *
+     * Note that this map is *read* during composition, so it is a [SnapshotStateMap] to make sure
+     * that we recompose when modifications are made to this map.
+     */
     private val readyScenes = SnapshotStateMap<SceneKey, Boolean>()
 
-    internal var onChangeScene by mutableStateOf(onChangeScene)
-    internal var transitions by mutableStateOf(transitions)
-    internal var density: Density by mutableStateOf(density)
-    internal var edgeDetector by mutableStateOf(edgeDetector)
-    internal var transitionInterceptionThreshold by mutableStateOf(transitionInterceptionThreshold)
-
     private val horizontalGestureHandler: SceneGestureHandler
     private val verticalGestureHandler: SceneGestureHandler
 
     init {
-        setScenes(builder)
+        updateScenes(builder)
 
         // SceneGestureHandler must wait for the scenes to be initialized, in order to access the
         // current scene (required for SwipeTransition).
@@ -98,7 +97,7 @@
         return scenes[key] ?: error("Scene $key is not configured")
     }
 
-    internal fun setScenes(builder: SceneTransitionLayoutScope.() -> Unit) {
+    internal fun updateScenes(builder: SceneTransitionLayoutScope.() -> Unit) {
         // Keep a reference of the current scenes. After processing [builder], the scenes that were
         // not configured will be removed.
         val scenesToRemove = scenes.keys.toMutableSet()
@@ -141,20 +140,6 @@
     }
 
     @Composable
-    internal fun setCurrentScene(key: SceneKey) {
-        val channel = remember { Channel<SceneKey>(Channel.CONFLATED) }
-        SideEffect { channel.trySend(key) }
-        LaunchedEffect(channel) {
-            for (newKey in channel) {
-                // Inspired by AnimateAsState.kt: let's poll the last value to avoid being one frame
-                // late.
-                val newKey = channel.tryReceive().getOrNull() ?: newKey
-                animateToScene(this@SceneTransitionLayoutImpl, newKey)
-            }
-        }
-    }
-
-    @Composable
     @OptIn(ExperimentalComposeUiApi::class)
     internal fun Content(modifier: Modifier) {
         Box(
@@ -171,14 +156,14 @@
 
                     val width: Int
                     val height: Int
-                    val state = state.transitionState
-                    if (state !is TransitionState.Transition || state.fromScene == state.toScene) {
+                    val transition = state.currentTransition
+                    if (transition == null) {
                         width = placeable.width
                         height = placeable.height
                     } else {
                         // Interpolate the size.
-                        val fromSize = scene(state.fromScene).targetSize
-                        val toSize = scene(state.toScene).targetSize
+                        val fromSize = scene(transition.fromScene).targetSize
+                        val toSize = scene(transition.toScene).targetSize
 
                         // Optimization: make sure we don't read state.progress if fromSize ==
                         // toSize to avoid running this code every frame when the layout size does
@@ -187,7 +172,7 @@
                             width = fromSize.width
                             height = fromSize.height
                         } else {
-                            val size = lerp(fromSize, toSize, state.progress)
+                            val size = lerp(fromSize, toSize, transition.progress)
                             width = size.width.coerceAtLeast(0)
                             height = size.height.coerceAtLeast(0)
                         }
@@ -228,16 +213,12 @@
 
                             scene.Content(
                                 Modifier.drawWithContent {
-                                    when (val state = state.transitionState) {
-                                        is TransitionState.Idle -> drawContent()
-                                        is TransitionState.Transition -> {
-                                            // Don't draw scenes that are not ready yet.
-                                            if (
-                                                readyScenes.containsKey(key) ||
-                                                    state.fromScene == state.toScene
-                                            ) {
-                                                drawContent()
-                                            }
+                                    if (state.currentTransition == null) {
+                                        drawContent()
+                                    } else {
+                                        // Don't draw scenes that are not ready yet.
+                                        if (readyScenes.containsKey(key)) {
+                                            drawContent()
                                         }
                                     }
                                 }
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 f48e914..d1ba582 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
@@ -23,36 +23,32 @@
 
 /** The state of a [SceneTransitionLayout]. */
 @Stable
-class SceneTransitionLayoutState(initialScene: SceneKey) {
+sealed interface SceneTransitionLayoutState {
     /**
      * The current [TransitionState]. All values read here are backed by the Snapshot system.
      *
      * To observe those values outside of Compose/the Snapshot system, use
      * [SceneTransitionLayoutState.observableTransitionState] instead.
      */
-    var transitionState: TransitionState by mutableStateOf(TransitionState.Idle(initialScene))
+    val transitionState: TransitionState
+
+    /** The current transition, or `null` if we are idle. */
+    val currentTransition: TransitionState.Transition?
+        get() = transitionState as? TransitionState.Transition
 
     /**
-     * Whether we are transitioning, optionally restricting the check to the transition between
-     * [from] and [to].
+     * Whether we are transitioning. If [from] or [to] is empty, we will also check that they match
+     * the scenes we are animating from and/or to.
      */
-    fun isTransitioning(from: SceneKey? = null, to: SceneKey? = null): Boolean {
-        val transition = transitionState as? TransitionState.Transition ?: return false
-
-        // TODO(b/310915136): Remove this check.
-        if (transition.fromScene == transition.toScene) {
-            return false
-        }
-
-        return (from == null || transition.fromScene == from) &&
-            (to == null || transition.toScene == to)
-    }
+    fun isTransitioning(from: SceneKey? = null, to: SceneKey? = null): Boolean
 
     /** Whether we are transitioning from [scene] to [other], or from [other] to [scene]. */
-    fun isTransitioningBetween(scene: SceneKey, other: SceneKey): Boolean {
-        return isTransitioning(from = scene, to = other) ||
-            isTransitioning(from = other, to = scene)
-    }
+    fun isTransitioningBetween(scene: SceneKey, other: SceneKey): Boolean
+}
+
+/** Create a new [SceneTransitionLayoutState] that is currently idle at scene [currentScene]. */
+fun SceneTransitionLayoutState(currentScene: SceneKey): SceneTransitionLayoutState {
+    return SceneTransitionLayoutStateImpl(currentScene, SceneTransitions.Empty)
 }
 
 @Stable
@@ -71,32 +67,77 @@
     /** No transition/animation is currently running. */
     data class Idle(override val currentScene: SceneKey) : TransitionState
 
-    /**
-     * There is a transition animating between two scenes.
-     *
-     * Important note: [fromScene] and [toScene] might be the same, in which case this [Transition]
-     * should be treated the same as [Idle]. This is designed on purpose so that a [Transition] can
-     * be started without knowing in advance where it is transitioning to, making the logic of
-     * [swipeToScene] easier to reason about.
-     */
-    interface Transition : TransitionState {
-        /** The scene this transition is starting from. */
-        val fromScene: SceneKey
+    /** There is a transition animating between two scenes. */
+    abstract class Transition(
+        /** The scene this transition is starting from. Can't be the same as toScene */
+        val fromScene: SceneKey,
 
-        /** The scene this transition is going to. */
+        /** The scene this transition is going to. Can't be the same as fromScene */
         val toScene: SceneKey
+    ) : TransitionState {
+
+        init {
+            check(fromScene != toScene)
+        }
 
         /**
          * The progress of the transition. This is usually in the `[0; 1]` range, but it can also be
          * less than `0` or greater than `1` when using transitions with a spring AnimationSpec or
          * when flinging quickly during a swipe gesture.
          */
-        val progress: Float
+        abstract val progress: Float
 
         /** Whether the transition was triggered by user input rather than being programmatic. */
-        val isInitiatedByUserInput: Boolean
+        abstract val isInitiatedByUserInput: Boolean
 
         /** Whether user input is currently driving the transition. */
-        val isUserInputOngoing: Boolean
+        abstract val isUserInputOngoing: Boolean
+    }
+}
+
+internal class SceneTransitionLayoutStateImpl(
+    initialScene: SceneKey,
+    internal var transitions: SceneTransitions,
+) : SceneTransitionLayoutState {
+    override var transitionState: TransitionState by
+        mutableStateOf(TransitionState.Idle(initialScene))
+        private set
+
+    /**
+     * The current [transformationSpec] associated to [transitionState]. Accessing this value makes
+     * sense only if [transitionState] is a [TransitionState.Transition].
+     */
+    internal var transformationSpec: TransformationSpecImpl = TransformationSpec.Empty
+
+    override fun isTransitioning(from: SceneKey?, to: SceneKey?): Boolean {
+        val transition = currentTransition ?: return false
+        return (from == null || transition.fromScene == from) &&
+            (to == null || transition.toScene == to)
+    }
+
+    override fun isTransitioningBetween(scene: SceneKey, other: SceneKey): Boolean {
+        return isTransitioning(from = scene, to = other) ||
+            isTransitioning(from = other, to = scene)
+    }
+
+    /** Start a new [transition], instantly interrupting any ongoing transition if there was one. */
+    internal fun startTransition(transition: TransitionState.Transition) {
+        // Compute the [TransformationSpec] when the transition starts.
+        transformationSpec =
+            transitions
+                .transitionSpec(transition.fromScene, transition.toScene)
+                .transformationSpec()
+
+        transitionState = transition
+    }
+
+    /**
+     * Notify that [transition] was finished and that we should settle to [idleScene]. This will do
+     * nothing if [transition] was interrupted since it was started.
+     */
+    internal fun finishTransition(transition: TransitionState.Transition, idleScene: SceneKey) {
+        if (transitionState == transition) {
+            transitionState = TransitionState.Idle(idleScene)
+        }
     }
 }
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 f91895b..3a55567 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
@@ -18,11 +18,9 @@
 
 import androidx.compose.animation.core.AnimationSpec
 import androidx.compose.animation.core.snap
-import androidx.compose.runtime.Stable
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.unit.IntSize
 import androidx.compose.ui.util.fastForEach
-import androidx.compose.ui.util.fastMap
 import com.android.compose.animation.scene.transformation.AnchoredSize
 import com.android.compose.animation.scene.transformation.AnchoredTranslate
 import com.android.compose.animation.scene.transformation.DrawScale
@@ -36,16 +34,17 @@
 import com.android.compose.animation.scene.transformation.Translate
 
 /** The transitions configuration of a [SceneTransitionLayout]. */
-class SceneTransitions(
-    internal val transitionSpecs: List<TransitionSpec>,
+class SceneTransitions
+internal constructor(
+    internal val transitionSpecs: List<TransitionSpecImpl>,
 ) {
-    private val cache = mutableMapOf<SceneKey, MutableMap<SceneKey, TransitionSpec>>()
+    private val cache = mutableMapOf<SceneKey, MutableMap<SceneKey, TransitionSpecImpl>>()
 
-    internal fun transitionSpec(from: SceneKey, to: SceneKey): TransitionSpec {
+    internal fun transitionSpec(from: SceneKey, to: SceneKey): TransitionSpecImpl {
         return cache.getOrPut(from) { mutableMapOf() }.getOrPut(to) { findSpec(from, to) }
     }
 
-    private fun findSpec(from: SceneKey, to: SceneKey): TransitionSpec {
+    private fun findSpec(from: SceneKey, to: SceneKey): TransitionSpecImpl {
         val spec = transition(from, to) { it.from == from && it.to == to }
         if (spec != null) {
             return spec
@@ -53,7 +52,7 @@
 
         val reversed = transition(from, to) { it.from == to && it.to == from }
         if (reversed != null) {
-            return reversed.reverse()
+            return reversed.reversed()
         }
 
         val relaxedSpec =
@@ -67,16 +66,16 @@
         return transition(from, to) {
                 (it.from == to && it.to == null) || (it.to == from && it.from == null)
             }
-            ?.reverse()
+            ?.reversed()
             ?: defaultTransition(from, to)
     }
 
     private fun transition(
         from: SceneKey,
         to: SceneKey,
-        filter: (TransitionSpec) -> Boolean,
-    ): TransitionSpec? {
-        var match: TransitionSpec? = null
+        filter: (TransitionSpecImpl) -> Boolean,
+    ): TransitionSpecImpl? {
+        var match: TransitionSpecImpl? = null
         transitionSpecs.fastForEach { spec ->
             if (filter(spec)) {
                 if (match != null) {
@@ -89,28 +88,88 @@
     }
 
     private fun defaultTransition(from: SceneKey, to: SceneKey) =
-        TransitionSpec(from, to, emptyList(), snap())
+        TransitionSpecImpl(from, to, TransformationSpec.EmptyProvider)
+
+    companion object {
+        val Empty = SceneTransitions(transitionSpecs = emptyList())
+    }
 }
 
 /** The definition of a transition between [from] and [to]. */
-@Stable
-data class TransitionSpec(
-    val from: SceneKey?,
-    val to: SceneKey?,
-    val transformations: List<Transformation>,
-    val spec: AnimationSpec<Float>,
-) {
-    // TODO(b/302300957): Make sure this cache does not infinitely grow.
-    private val cache = mutableMapOf<ElementKey, MutableMap<SceneKey, ElementTransformations>>()
+interface TransitionSpec {
+    /**
+     * The scene we are transitioning from. If `null`, this spec can be used to animate from any
+     * scene.
+     */
+    val from: SceneKey?
 
-    internal fun reverse(): TransitionSpec {
-        return copy(
+    /**
+     * The scene we are transitioning to. If `null`, this spec can be used to animate from any
+     * scene.
+     */
+    val to: SceneKey?
+
+    /**
+     * Return a reversed version of this [TransitionSpec] for a transition going from [to] to
+     * [from].
+     */
+    fun reversed(): TransitionSpec
+
+    /*
+     * The [TransformationSpec] associated to this [TransitionSpec].
+     *
+     * Note that this is called once every a transition associated to this [TransitionSpec] is
+     * started.
+     */
+    fun transformationSpec(): TransformationSpec
+}
+
+interface TransformationSpec {
+    /** The [AnimationSpec] used to animate the associated transition progress. */
+    val progressSpec: AnimationSpec<Float>
+
+    /** The list of [Transformation] applied to elements during this transition. */
+    val transformations: List<Transformation>
+
+    companion object {
+        internal val Empty =
+            TransformationSpecImpl(progressSpec = snap(), transformations = emptyList())
+        internal val EmptyProvider = { Empty }
+    }
+}
+
+internal class TransitionSpecImpl(
+    override val from: SceneKey?,
+    override val to: SceneKey?,
+    private val transformationSpec: () -> TransformationSpecImpl,
+) : TransitionSpec {
+    override fun reversed(): TransitionSpecImpl {
+        return TransitionSpecImpl(
             from = to,
             to = from,
-            transformations = transformations.fastMap { it.reverse() },
+            transformationSpec = {
+                val reverse = transformationSpec.invoke()
+                TransformationSpecImpl(
+                    progressSpec = reverse.progressSpec,
+                    transformations = reverse.transformations.map { it.reversed() }
+                )
+            }
         )
     }
 
+    override fun transformationSpec(): TransformationSpecImpl = this.transformationSpec.invoke()
+}
+
+/**
+ * An implementation of [TransformationSpec] that allows the quick retrieval of an element
+ * [ElementTransformations].
+ */
+internal class TransformationSpecImpl(
+    override val progressSpec: AnimationSpec<Float>,
+    override val transformations: List<Transformation>,
+) : TransformationSpec {
+    private val cache = mutableMapOf<ElementKey, MutableMap<SceneKey, ElementTransformations>>()
+
     internal fun transformations(element: ElementKey, scene: SceneKey): ElementTransformations {
         return cache
             .getOrPut(element) { mutableMapOf() }
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 2c78dee..0d3bc7d 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
@@ -27,7 +27,8 @@
     fun Scene.shouldEnableSwipes(orientation: Orientation): Boolean =
         userActions.keys.any { it is Swipe && it.direction.orientation == orientation }
 
-    val currentScene = gestureHandler.currentScene
+    val layoutImpl = gestureHandler.layoutImpl
+    val currentScene = layoutImpl.scene(layoutImpl.state.transitionState.currentScene)
     val orientation = gestureHandler.orientation
     val canSwipe = currentScene.shouldEnableSwipes(orientation)
     val canOppositeSwipe =
@@ -46,7 +47,7 @@
         // user can't swipe in the other direction.
         startDragImmediately =
             gestureHandler.isDrivingTransition &&
-                gestureHandler.isAnimatingOffset &&
+                gestureHandler.swipeTransition.isAnimatingOffset &&
                 !canOppositeSwipe,
         onDragStarted = gestureHandler.draggable::onDragStarted,
         onDragDelta = gestureHandler.draggable::onDelta,
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 f820074..dfa2a9a 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
@@ -226,12 +226,17 @@
     )
 
     /**
-     * Scale the element(s) matching [matcher] so that it grows/shrinks to the same size as [anchor]
-     * .
+     * Scale the element(s) matching [matcher] so that it grows/shrinks to the same size as
+     * [anchor].
      *
      * Note: This currently only works if [anchor] is a shared element of this transition.
      */
-    fun anchoredSize(matcher: ElementMatcher, anchor: ElementKey)
+    fun anchoredSize(
+        matcher: ElementMatcher,
+        anchor: ElementKey,
+        anchorWidth: Boolean = true,
+        anchorHeight: Boolean = true,
+    )
 }
 
 /** The edge of a [SceneTransitionLayout]. */
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 8c0a5a3..7046866 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
@@ -44,7 +44,7 @@
 }
 
 private class SceneTransitionsBuilderImpl : SceneTransitionsBuilder {
-    val transitionSpecs = mutableListOf<TransitionSpec>()
+    val transitionSpecs = mutableListOf<TransitionSpecImpl>()
 
     override fun to(to: SceneKey, builder: TransitionBuilder.() -> Unit): TransitionSpec {
         return transition(from = null, to = to, builder)
@@ -63,14 +63,15 @@
         to: SceneKey?,
         builder: TransitionBuilder.() -> Unit,
     ): TransitionSpec {
-        val impl = TransitionBuilderImpl().apply(builder)
-        val spec =
-            TransitionSpec(
-                from,
-                to,
-                impl.transformations,
-                impl.spec,
+        fun transformationSpec(): TransformationSpecImpl {
+            val impl = TransitionBuilderImpl().apply(builder)
+            return TransformationSpecImpl(
+                progressSpec = impl.spec,
+                transformations = impl.transformations,
             )
+        }
+
+        val spec = TransitionSpecImpl(from, to, ::transformationSpec)
         transitionSpecs.add(spec)
         return spec
     }
@@ -143,7 +144,7 @@
 
         transformations.add(
             if (reversed) {
-                transformation.reverse()
+                transformation.reversed()
             } else {
                 transformation
             }
@@ -178,7 +179,12 @@
         transformation(DrawScale(matcher, scaleX, scaleY, pivot))
     }
 
-    override fun anchoredSize(matcher: ElementMatcher, anchor: ElementKey) {
-        transformation(AnchoredSize(matcher, anchor))
+    override fun anchoredSize(
+        matcher: ElementMatcher,
+        anchor: ElementKey,
+        anchorWidth: Boolean,
+        anchorHeight: Boolean,
+    ) {
+        transformation(AnchoredSize(matcher, anchor, anchorWidth, anchorHeight))
     }
 }
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredSize.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredSize.kt
index 95385d5..40c814e 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredSize.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredSize.kt
@@ -29,6 +29,8 @@
 internal class AnchoredSize(
     override val matcher: ElementMatcher,
     private val anchor: ElementKey,
+    private val anchorWidth: Boolean,
+    private val anchorHeight: Boolean,
 ) : PropertyTransformation<IntSize> {
     override fun transform(
         layoutImpl: SceneTransitionLayoutImpl,
@@ -41,7 +43,10 @@
         fun anchorSizeIn(scene: SceneKey): IntSize {
             val size = layoutImpl.elements[anchor]?.sceneValues?.get(scene)?.targetSize
             return if (size != null && size != Element.SizeUnspecified) {
-                size
+                IntSize(
+                    width = if (anchorWidth) size.width else value.width,
+                    height = if (anchorHeight) size.height else value.height,
+                )
             } else {
                 value
             }
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Transformation.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Transformation.kt
index 2069355..0cd11b9 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Transformation.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Transformation.kt
@@ -42,7 +42,7 @@
      * Reverse this transformation. This is called when we use Transition(from = A, to = B) when
      * animating from B to A and there is no Transition(from = B, to = A) defined.
      */
-    fun reverse(): Transformation = this
+    fun reversed(): Transformation = this
 }
 
 internal class SharedElementTransformation(
@@ -77,10 +77,10 @@
     val delegate: PropertyTransformation<T>,
     override val range: TransformationRange,
 ) : PropertyTransformation<T> by delegate {
-    override fun reverse(): Transformation {
+    override fun reversed(): Transformation {
         return RangedPropertyTransformation(
-            delegate.reverse() as PropertyTransformation<T>,
-            range.reverse()
+            delegate.reversed() as PropertyTransformation<T>,
+            range.reversed()
         )
     }
 }
@@ -102,7 +102,7 @@
     }
 
     /** Reverse this range. */
-    fun reverse() = TransformationRange(start = reverseBound(end), end = reverseBound(start))
+    fun reversed() = TransformationRange(start = reverseBound(end), end = reverseBound(start))
 
     /** Get the progress of this range given the global [transitionProgress]. */
     fun progress(transitionProgress: Float): Float {
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/LargeTopAppBarNestedScrollConnection.kt b/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/LargeTopAppBarNestedScrollConnection.kt
index cea8d9a..2c96d0e 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/LargeTopAppBarNestedScrollConnection.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/LargeTopAppBarNestedScrollConnection.kt
@@ -16,9 +16,8 @@
 
 package com.android.compose.nestedscroll
 
-import androidx.compose.ui.geometry.Offset
+import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
-import androidx.compose.ui.input.nestedscroll.NestedScrollSource
 
 /**
  * A [NestedScrollConnection] that listens for all vertical scroll events and responds in the
@@ -34,59 +33,44 @@
  *
  * @sample com.android.compose.animation.scene.demo.Shade
  */
-class LargeTopAppBarNestedScrollConnection(
-    private val height: () -> Float,
-    private val onChangeHeight: (Float) -> Unit,
-    private val minHeight: Float,
-    private val maxHeight: Float,
-) : NestedScrollConnection {
-
-    constructor(
-        height: () -> Float,
-        onHeightChanged: (Float) -> Unit,
-        heightRange: ClosedFloatingPointRange<Float>,
-    ) : this(
-        height = height,
-        onChangeHeight = onHeightChanged,
-        minHeight = heightRange.start,
-        maxHeight = heightRange.endInclusive,
+fun LargeTopAppBarNestedScrollConnection(
+    height: () -> Float,
+    onHeightChanged: (Float) -> Unit,
+    heightRange: ClosedFloatingPointRange<Float>,
+): PriorityNestedScrollConnection {
+    val minHeight = heightRange.start
+    val maxHeight = heightRange.endInclusive
+    return PriorityNestedScrollConnection(
+        orientation = Orientation.Vertical,
+        // When swiping up, the LargeTopAppBar will shrink (to [minHeight]) and the content will
+        // expand. Then, you can then scroll down the content.
+        canStartPreScroll = { offsetAvailable, offsetBeforeStart ->
+            offsetAvailable < 0 && offsetBeforeStart == 0f && height() > minHeight
+        },
+        // When swiping down, the content will scroll up until it reaches the top. Then, the
+        // LargeTopAppBar will expand until it reaches its [maxHeight].
+        canStartPostScroll = { offsetAvailable, _ -> offsetAvailable > 0 && height() < maxHeight },
+        canStartPostFling = { false },
+        canContinueScroll = {
+            val currentHeight = height()
+            minHeight < currentHeight && currentHeight < maxHeight
+        },
+        canScrollOnFling = true,
+        onStart = { /* do nothing */},
+        onScroll = { offsetAvailable ->
+            val currentHeight = height()
+            val amountConsumed =
+                if (offsetAvailable > 0) {
+                    val amountLeft = maxHeight - currentHeight
+                    offsetAvailable.coerceAtMost(amountLeft)
+                } else {
+                    val amountLeft = minHeight - currentHeight
+                    offsetAvailable.coerceAtLeast(amountLeft)
+                }
+            onHeightChanged(currentHeight + amountConsumed)
+            amountConsumed
+        },
+        // Don't consume the velocity on pre/post fling
+        onStop = { 0f },
     )
-
-    /**
-     * When swiping up, the LargeTopAppBar will shrink (to [minHeight]) and the content will expand.
-     * Then, you can then scroll down the content.
-     */
-    override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
-        val y = available.y
-        val currentHeight = height()
-        if (y >= 0 || currentHeight <= minHeight) {
-            return Offset.Zero
-        }
-
-        val amountLeft = minHeight - currentHeight
-        val amountConsumed = y.coerceAtLeast(amountLeft)
-        onChangeHeight(currentHeight + amountConsumed)
-        return Offset(0f, amountConsumed)
-    }
-
-    /**
-     * When swiping down, the content will scroll up until it reaches the top. Then, the
-     * LargeTopAppBar will expand until it reaches its [maxHeight].
-     */
-    override fun onPostScroll(
-        consumed: Offset,
-        available: Offset,
-        source: NestedScrollSource
-    ): Offset {
-        val y = available.y
-        val currentHeight = height()
-        if (y <= 0 || currentHeight >= maxHeight) {
-            return Offset.Zero
-        }
-
-        val amountLeft = maxHeight - currentHeight
-        val amountConsumed = y.coerceAtMost(amountLeft)
-        onChangeHeight(currentHeight + amountConsumed)
-        return Offset(0f, amountConsumed)
-    }
 }
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityNestedScrollConnection.kt b/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityNestedScrollConnection.kt
index a5fd1bf..2841bcf 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityNestedScrollConnection.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityNestedScrollConnection.kt
@@ -38,7 +38,8 @@
     private val canStartPostScroll: (offsetAvailable: Offset, offsetBeforeStart: Offset) -> Boolean,
     private val canStartPostFling: (velocityAvailable: Velocity) -> Boolean,
     private val canContinueScroll: () -> Boolean,
-    private val onStart: () -> Unit,
+    private val canScrollOnFling: Boolean,
+    private val onStart: (offsetAvailable: Offset) -> Unit,
     private val onScroll: (offsetAvailable: Offset) -> Offset,
     private val onStop: (velocityAvailable: Velocity) -> Velocity,
 ) : NestedScrollConnection {
@@ -59,7 +60,7 @@
 
         if (
             isPriorityMode ||
-                source == NestedScrollSource.Fling ||
+                (source == NestedScrollSource.Fling && !canScrollOnFling) ||
                 !canStartPostScroll(available, offsetBeforeStart)
         ) {
             // The priority mode cannot start so we won't consume the available offset.
@@ -71,7 +72,7 @@
 
     override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
         if (!isPriorityMode) {
-            if (source != NestedScrollSource.Fling) {
+            if (source != NestedScrollSource.Fling || canScrollOnFling) {
                 if (canStartPreScroll(available, offsetScrolledBeforePriorityMode)) {
                     return onPriorityStart(available)
                 }
@@ -98,12 +99,20 @@
     }
 
     override suspend fun onPreFling(available: Velocity): Velocity {
+        if (isPriorityMode && canScrollOnFling) {
+            // We don't want to consume the velocity, we prefer to continue receiving scroll events.
+            return Velocity.Zero
+        }
         // Step 3b: The finger is lifted, we can stop intercepting scroll events and use the speed
         // of the fling gesture.
         return onPriorityStop(velocity = available)
     }
 
     override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {
+        if (isPriorityMode) {
+            return onPriorityStop(velocity = available)
+        }
+
         if (!canStartPostFling(available)) {
             return Velocity.Zero
         }
@@ -131,7 +140,7 @@
 
         // Note: onStop will be called if we cannot continue to scroll (step 3a), or the finger is
         // lifted (step 3b), or this object has been destroyed (step 3c).
-        onStart()
+        onStart(available)
 
         return onScroll(available)
     }
@@ -156,7 +165,8 @@
     canStartPostScroll: (offsetAvailable: Float, offsetBeforeStart: Float) -> Boolean,
     canStartPostFling: (velocityAvailable: Float) -> Boolean,
     canContinueScroll: () -> Boolean,
-    onStart: () -> Unit,
+    canScrollOnFling: Boolean,
+    onStart: (offsetAvailable: Float) -> Unit,
     onScroll: (offsetAvailable: Float) -> Float,
     onStop: (velocityAvailable: Float) -> Float,
 ) =
@@ -172,7 +182,8 @@
                 canStartPostFling(velocityAvailable.toFloat())
             },
             canContinueScroll = canContinueScroll,
-            onStart = onStart,
+            canScrollOnFling = canScrollOnFling,
+            onStart = { offsetAvailable -> onStart(offsetAvailable.toFloat()) },
             onScroll = { offsetAvailable: Offset ->
                 onScroll(offsetAvailable.toFloat()).toOffset()
             },
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 ce3e1db..439dc00 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,16 +17,21 @@
 package com.android.compose.animation.scene
 
 import androidx.compose.animation.core.tween
+import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.offset
 import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.pager.HorizontalPager
+import androidx.compose.foundation.pager.PagerState
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.SideEffect
 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
 import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.Modifier
@@ -36,6 +41,9 @@
 import androidx.compose.ui.unit.dp
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.runTest
 import org.junit.Assert.assertThrows
 import org.junit.Rule
 import org.junit.Test
@@ -430,6 +438,97 @@
     }
 
     @Test
+    @OptIn(ExperimentalFoundationApi::class)
+    fun elementModifierNodeIsRecycledInLazyLayouts() = runTest {
+        val nPages = 2
+        val pagerState = PagerState(currentPage = 0) { nPages }
+        var nullableLayoutImpl: SceneTransitionLayoutImpl? = null
+
+        // This is how we scroll a pager inside a test, as explained in b/315457147#comment2.
+        lateinit var scrollScope: CoroutineScope
+        fun scrollToPage(page: Int) {
+            var animationFinished by mutableStateOf(false)
+            rule.runOnIdle {
+                scrollScope.launch {
+                    pagerState.scrollToPage(page)
+                    animationFinished = true
+                }
+            }
+            rule.waitUntil(timeoutMillis = 10_000) { animationFinished }
+        }
+
+        rule.setContent {
+            scrollScope = rememberCoroutineScope()
+
+            SceneTransitionLayoutForTesting(
+                currentScene = TestScenes.SceneA,
+                onChangeScene = {},
+                transitions = remember { transitions {} },
+                state = remember { SceneTransitionLayoutState(TestScenes.SceneA) },
+                edgeDetector = DefaultEdgeDetector,
+                modifier = Modifier,
+                transitionInterceptionThreshold = 0f,
+                onLayoutImpl = { nullableLayoutImpl = it },
+            ) {
+                scene(TestScenes.SceneA) {
+                    // The pages are full-size and beyondBoundsPageCount is 0, so at rest only one
+                    // page should be composed.
+                    HorizontalPager(
+                        pagerState,
+                        beyondBoundsPageCount = 0,
+                    ) { page ->
+                        when (page) {
+                            0 -> Box(Modifier.element(TestElements.Foo).fillMaxSize())
+                            1 -> Box(Modifier.fillMaxSize())
+                            else -> error("page $page < nPages $nPages")
+                        }
+                    }
+                }
+            }
+        }
+
+        assertThat(nullableLayoutImpl).isNotNull()
+        val layoutImpl = nullableLayoutImpl!!
+
+        // There is only Foo in the elements map.
+        assertThat(layoutImpl.elements.keys).containsExactly(TestElements.Foo)
+        val element = layoutImpl.elements.getValue(TestElements.Foo)
+        val sceneValues = element.sceneValues
+        assertThat(sceneValues.keys).containsExactly(TestScenes.SceneA)
+
+        // Get the ElementModifier node that should be reused later on when coming back to this
+        // page.
+        val nodes = sceneValues.getValue(TestScenes.SceneA).nodes
+        assertThat(nodes).hasSize(1)
+        val node = nodes.single()
+
+        // Go to the second page.
+        scrollToPage(1)
+        rule.waitForIdle()
+
+        assertThat(nodes).isEmpty()
+        assertThat(sceneValues).isEmpty()
+        assertThat(layoutImpl.elements).isEmpty()
+
+        // Go back to the first page.
+        scrollToPage(0)
+        rule.waitForIdle()
+
+        assertThat(layoutImpl.elements.keys).containsExactly(TestElements.Foo)
+        val newElement = layoutImpl.elements.getValue(TestElements.Foo)
+        val newSceneValues = newElement.sceneValues
+        assertThat(newElement).isNotEqualTo(element)
+        assertThat(newSceneValues).isNotEqualTo(sceneValues)
+        assertThat(newSceneValues.keys).containsExactly(TestScenes.SceneA)
+
+        // The ElementModifier node should be the same as before.
+        val newNodes = newSceneValues.getValue(TestScenes.SceneA).nodes
+        assertThat(newNodes).hasSize(1)
+        val newNode = newNodes.single()
+        assertThat(newNode).isSameInstanceAs(node)
+    }
+
+    @Test
     fun existingElementsDontRecomposeWhenTransitionStateChanges() {
         var fooCompositions = 0
 
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneGestureHandlerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneGestureHandlerTest.kt
index 49ef31b..d9ce519 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneGestureHandlerTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneGestureHandlerTest.kt
@@ -29,10 +29,10 @@
 import androidx.compose.ui.unit.IntSize
 import androidx.compose.ui.unit.Velocity
 import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.compose.animation.scene.NestedScrollBehavior.Always
 import com.android.compose.animation.scene.NestedScrollBehavior.DuringTransitionBetweenScenes
-import com.android.compose.animation.scene.NestedScrollBehavior.EdgeNoOverscroll
-import com.android.compose.animation.scene.NestedScrollBehavior.EdgeWithOverscroll
+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.TestScenes.SceneA
 import com.android.compose.animation.scene.TestScenes.SceneB
 import com.android.compose.animation.scene.TestScenes.SceneC
@@ -55,57 +55,80 @@
     ) {
         private var internalCurrentScene: SceneKey by mutableStateOf(SceneA)
 
-        private val layoutState: SceneTransitionLayoutState =
-            SceneTransitionLayoutState(internalCurrentScene)
+        private val layoutState =
+            SceneTransitionLayoutStateImpl(internalCurrentScene, EmptyTestTransitions)
+
+        val mutableUserActionsA: MutableMap<UserAction, SceneKey> =
+            mutableMapOf(Swipe.Up to SceneB, Swipe.Down to SceneC)
+
+        val mutableUserActionsB: MutableMap<UserAction, SceneKey> =
+            mutableMapOf(Swipe.Up to SceneC, Swipe.Down to SceneA)
 
         private val scenesBuilder: SceneTransitionLayoutScope.() -> Unit = {
             scene(
                 key = SceneA,
-                userActions = mapOf(Swipe.Up to SceneB, Swipe.Down to SceneC),
+                userActions = mutableUserActionsA,
             ) {
                 Text("SceneA")
             }
-            scene(SceneB) { Text("SceneB") }
-            scene(SceneC) { Text("SceneC") }
+            scene(
+                key = SceneB,
+                userActions = mutableUserActionsB,
+            ) {
+                Text("SceneB")
+            }
+            scene(
+                key = SceneC,
+                userActions =
+                    mapOf(
+                        Swipe.Up to SceneB,
+                        Swipe(SwipeDirection.Up, fromEdge = Edge.Bottom) to SceneA
+                    ),
+            ) {
+                Text("SceneC")
+            }
         }
 
         val transitionInterceptionThreshold = 0.05f
 
-        val sceneGestureHandler =
-            SceneGestureHandler(
-                layoutImpl =
-                    SceneTransitionLayoutImpl(
-                            onChangeScene = { internalCurrentScene = it },
-                            builder = scenesBuilder,
-                            transitions = EmptyTestTransitions,
-                            state = layoutState,
-                            density = Density(1f),
-                            edgeDetector = DefaultEdgeDetector,
-                            transitionInterceptionThreshold = transitionInterceptionThreshold,
-                            coroutineScope = coroutineScope,
-                        )
-                        .apply { setScenesTargetSizeForTest(LAYOUT_SIZE) },
-                orientation = Orientation.Vertical,
-                coroutineScope = coroutineScope,
-            )
+        private val layoutImpl =
+            SceneTransitionLayoutImpl(
+                    state = layoutState,
+                    onChangeScene = { internalCurrentScene = it },
+                    density = Density(1f),
+                    edgeDetector = DefaultEdgeDetector,
+                    transitionInterceptionThreshold = transitionInterceptionThreshold,
+                    builder = scenesBuilder,
+                    coroutineScope = coroutineScope,
+                )
+                .apply { setScenesTargetSizeForTest(LAYOUT_SIZE) }
 
+        val sceneGestureHandler = layoutImpl.gestureHandler(Orientation.Vertical)
+        val horizontalSceneGestureHandler = layoutImpl.gestureHandler(Orientation.Horizontal)
         val draggable = sceneGestureHandler.draggable
 
         fun nestedScrollConnection(nestedScrollBehavior: NestedScrollBehavior) =
             SceneNestedScrollHandler(
-                    gestureHandler = sceneGestureHandler,
-                    startBehavior = nestedScrollBehavior,
-                    endBehavior = nestedScrollBehavior,
+                    layoutImpl,
+                    orientation = sceneGestureHandler.orientation,
+                    topOrLeftBehavior = nestedScrollBehavior,
+                    bottomOrRightBehavior = nestedScrollBehavior,
                 )
                 .connection
 
         val velocityThreshold = sceneGestureHandler.velocityThreshold
 
-        // 10% of the screen
-        val deltaInPixels10 = SCREEN_SIZE * 0.1f
+        fun down(fractionOfScreen: Float) =
+            if (fractionOfScreen < 0f) error("use up()") else SCREEN_SIZE * fractionOfScreen
+
+        fun up(fractionOfScreen: Float) =
+            if (fractionOfScreen < 0f) error("use down()") else -down(fractionOfScreen)
+
+        // Float tolerance for comparisons
+        val tolerance = 0.00001f
 
         // Offset y: 10% of the screen
-        val offsetY10 = Offset(x = 0f, y = deltaInPixels10)
+        val offsetY10 = Offset(x = 0f, y = down(0.1f))
 
         val transitionState: TransitionState
             get() = layoutState.transitionState
@@ -121,12 +144,39 @@
             coroutineScope.testScheduler.runCurrent()
         }
 
-        fun assertScene(currentScene: SceneKey, isIdle: Boolean) {
-            val idleMsg = if (isIdle) "MUST" else "MUST NOT"
-            assertWithMessage("transitionState $idleMsg be Idle")
-                .that(transitionState is Idle)
-                .isEqualTo(isIdle)
-            assertThat(transitionState.currentScene).isEqualTo(currentScene)
+        fun assertIdle(currentScene: SceneKey) {
+            assertWithMessage("transitionState must be Idle").that(transitionState is Idle).isTrue()
+            assertWithMessage("currentScene does not match")
+                .that(transitionState.currentScene)
+                .isEqualTo(currentScene)
+        }
+
+        fun assertTransition(
+            currentScene: SceneKey? = null,
+            fromScene: SceneKey? = null,
+            toScene: SceneKey? = null,
+            progress: Float? = null,
+        ) {
+            assertWithMessage("transitionState must be Transition")
+                .that(transitionState is Transition)
+                .isTrue()
+            if (currentScene != null)
+                assertWithMessage("currentScene does not match")
+                    .that(transitionState.currentScene)
+                    .isEqualTo(currentScene)
+            if (fromScene != null)
+                assertWithMessage("fromScene does not match")
+                    .that((transitionState as? Transition)?.fromScene)
+                    .isEqualTo(fromScene)
+            if (toScene != null)
+                assertWithMessage("toScene does not match")
+                    .that((transitionState as? Transition)?.toScene)
+                    .isEqualTo(toScene)
+            if (progress != null)
+                assertWithMessage("progress does not match")
+                    .that((transitionState as? Transition)?.progress)
+                    .isWithin(tolerance)
+                    .of(progress)
         }
     }
 
@@ -135,111 +185,326 @@
         runMonotonicClockTest { TestGestureScope(coroutineScope = this).block() }
     }
 
-    private fun DraggableHandler.onDragStarted() =
-        onDragStarted(layoutSize = LAYOUT_SIZE, startedPosition = Offset.Zero)
+    private fun DraggableHandler.onDragStarted(
+        overSlop: Float = 0f,
+        startedPosition: Offset = Offset.Zero,
+    ) {
+        onDragStarted(startedPosition, overSlop)
+        // MultiPointerDraggable will always call onDelta with the initial overSlop right after
+        onDelta(overSlop)
+    }
 
-    @Test
-    fun testPreconditions() = runGestureTest { assertScene(currentScene = SceneA, isIdle = true) }
+    @Test fun testPreconditions() = runGestureTest { assertIdle(currentScene = SceneA) }
 
     @Test
     fun onDragStarted_shouldStartATransition() = runGestureTest {
         draggable.onDragStarted()
-        assertScene(currentScene = SceneA, isIdle = false)
+        assertTransition(currentScene = SceneA)
     }
 
     @Test
     fun afterSceneTransitionIsStarted_interceptDragEvents() = runGestureTest {
         draggable.onDragStarted()
-        assertScene(currentScene = SceneA, isIdle = false)
+        assertTransition(currentScene = SceneA)
 
-        draggable.onDelta(pixels = deltaInPixels10)
+        draggable.onDelta(pixels = down(0.1f))
         assertThat(progress).isEqualTo(0.1f)
 
-        draggable.onDelta(pixels = deltaInPixels10)
+        draggable.onDelta(pixels = down(0.1f))
         assertThat(progress).isEqualTo(0.2f)
     }
 
     @Test
     fun onDragStoppedAfterDrag_velocityLowerThanThreshold_remainSameScene() = runGestureTest {
         draggable.onDragStarted()
-        assertScene(currentScene = SceneA, isIdle = false)
+        assertTransition(currentScene = SceneA)
 
-        draggable.onDelta(pixels = deltaInPixels10)
-        assertScene(currentScene = SceneA, isIdle = false)
+        draggable.onDelta(pixels = down(0.1f))
+        assertTransition(currentScene = SceneA)
 
         draggable.onDragStopped(
             velocity = velocityThreshold - 0.01f,
         )
-        assertScene(currentScene = SceneA, isIdle = false)
+        assertTransition(currentScene = SceneA)
 
         // wait for the stop animation
         advanceUntilIdle()
-        assertScene(currentScene = SceneA, isIdle = true)
+        assertIdle(currentScene = SceneA)
     }
 
     @Test
     fun onDragStoppedAfterDrag_velocityAtLeastThreshold_goToNextScene() = runGestureTest {
         draggable.onDragStarted()
-        assertScene(currentScene = SceneA, isIdle = false)
+        assertTransition(currentScene = SceneA)
 
-        draggable.onDelta(pixels = deltaInPixels10)
-        assertScene(currentScene = SceneA, isIdle = false)
+        draggable.onDelta(pixels = down(0.1f))
+        assertTransition(currentScene = SceneA)
 
-        draggable.onDragStopped(
-            velocity = velocityThreshold,
-        )
-        assertScene(currentScene = SceneC, isIdle = false)
+        draggable.onDragStopped(velocity = velocityThreshold)
+
+        assertTransition(currentScene = SceneC)
 
         // wait for the stop animation
         advanceUntilIdle()
-        assertScene(currentScene = SceneC, isIdle = true)
+        assertIdle(currentScene = SceneC)
     }
 
     @Test
-    fun onDragStoppedAfterStarted_returnImmediatelyToIdle() = runGestureTest {
+    fun onDragStoppedAfterStarted_returnToIdle() = runGestureTest {
         draggable.onDragStarted()
-        assertScene(currentScene = SceneA, isIdle = false)
+        assertTransition(currentScene = SceneA)
 
         draggable.onDragStopped(velocity = 0f)
-        assertScene(currentScene = SceneA, isIdle = true)
+        advanceUntilIdle()
+        assertIdle(currentScene = SceneA)
+    }
+
+    @Test
+    fun onDragReversedDirection_changeToScene() = runGestureTest {
+        // Drag A -> B with progress 0.6
+        draggable.onDragStarted()
+        draggable.onDelta(up(0.6f))
+        assertTransition(
+            currentScene = SceneA,
+            fromScene = SceneA,
+            toScene = SceneB,
+            progress = 0.6f
+        )
+
+        // Reverse direction such that A -> C now with 0.4
+        draggable.onDelta(down(1f))
+        assertTransition(
+            currentScene = SceneA,
+            fromScene = SceneA,
+            toScene = SceneC,
+            progress = 0.4f
+        )
+
+        // After the drag stopped scene C should be committed
+        draggable.onDragStopped(velocity = velocityThreshold)
+        assertTransition(currentScene = SceneC, fromScene = SceneA, toScene = SceneC)
+
+        // wait for the stop animation
+        advanceUntilIdle()
+        assertIdle(currentScene = SceneC)
+    }
+
+    @Test
+    fun onDragStartedWithoutActionsInBothDirections_stayIdle() = runGestureTest {
+        horizontalSceneGestureHandler.draggable.onDragStarted(up(0.3f))
+        assertIdle(currentScene = SceneA)
+        horizontalSceneGestureHandler.draggable.onDragStarted(down(0.3f))
+        assertIdle(currentScene = SceneA)
+    }
+
+    @Test
+    fun onDragIntoNoAction_startTransitionToOppositeDirection() = runGestureTest {
+        navigateToSceneC()
+
+        // We are on SceneC which has no action in Down direction
+        draggable.onDragStarted(down(0.1f))
+        assertTransition(
+            currentScene = SceneC,
+            fromScene = SceneC,
+            toScene = SceneB,
+            progress = -0.1f
+        )
+
+        // Reverse drag direction, it will consume the previous drag
+        draggable.onDelta(up(0.1f))
+        assertTransition(
+            currentScene = SceneC,
+            fromScene = SceneC,
+            toScene = SceneB,
+            progress = 0.0f
+        )
+
+        // Continue reverse drag direction, it should record progress to Scene B
+        draggable.onDelta(up(0.1f))
+        assertTransition(
+            currentScene = SceneC,
+            fromScene = SceneC,
+            toScene = SceneB,
+            progress = 0.1f
+        )
+    }
+
+    @Test
+    fun onDragFromEdge_startTransitionToEdgeAction() = runGestureTest {
+        navigateToSceneC()
+
+        // Start dragging from the bottom
+        draggable.onDragStarted(up(0.1f), Offset(SCREEN_SIZE * 0.5f, SCREEN_SIZE))
+        assertTransition(
+            currentScene = SceneC,
+            fromScene = SceneC,
+            toScene = SceneA,
+            progress = 0.1f
+        )
+    }
+
+    @Test
+    fun onDragToExactlyZero_toSceneIsSet() = runGestureTest {
+        draggable.onDragStarted(down(0.3f))
+        assertTransition(
+            currentScene = SceneA,
+            fromScene = SceneA,
+            toScene = SceneC,
+            progress = 0.3f
+        )
+        draggable.onDelta(up(0.3f))
+        assertTransition(
+            currentScene = SceneA,
+            fromScene = SceneA,
+            toScene = SceneC,
+            progress = 0.0f
+        )
+    }
+
+    private fun TestGestureScope.navigateToSceneC() {
+        assertIdle(currentScene = SceneA)
+        draggable.onDragStarted(down(1f))
+        draggable.onDragStopped(0f)
+        advanceUntilIdle()
+        assertIdle(currentScene = SceneC)
+    }
+
+    @Test
+    fun onAccelaratedScroll_scrollToThirdScene() = runGestureTest {
+        // Drag A -> B with progress 0.2
+        draggable.onDragStarted()
+        draggable.onDelta(up(0.2f))
+        assertTransition(
+            currentScene = SceneA,
+            fromScene = SceneA,
+            toScene = SceneB,
+            progress = 0.2f
+        )
+
+        // Start animation A -> B with progress 0.2 -> 1.0
+        draggable.onDragStopped(velocity = -velocityThreshold)
+        assertTransition(currentScene = SceneB, fromScene = SceneA, toScene = SceneB)
+
+        // While at A -> B do a 100% screen drag (progress 1.2). This should go past B and change
+        // the transition to B -> C with progress 0.2
+        draggable.onDragStarted()
+        draggable.onDelta(up(1f))
+        assertTransition(
+            currentScene = SceneB,
+            fromScene = SceneB,
+            toScene = SceneC,
+            progress = 0.2f
+        )
+
+        // After the drag stopped scene C should be committed
+        draggable.onDragStopped(velocity = -velocityThreshold)
+        assertTransition(currentScene = SceneC, fromScene = SceneB, toScene = SceneC)
+
+        // wait for the stop animation
+        advanceUntilIdle()
+        assertIdle(currentScene = SceneC)
+    }
+
+    @Test
+    fun onAccelaratedScrollBothTargetsBecomeNull_settlesToIdle() = runGestureTest {
+        draggable.onDragStarted()
+        draggable.onDelta(up(0.2f))
+
+        draggable.onDelta(up(0.2f))
+        draggable.onDragStopped(velocity = -velocityThreshold)
+        assertTransition(currentScene = SceneB, fromScene = SceneA, toScene = SceneB)
+
+        mutableUserActionsA.remove(Swipe.Up)
+        mutableUserActionsA.remove(Swipe.Down)
+        mutableUserActionsB.remove(Swipe.Up)
+        mutableUserActionsB.remove(Swipe.Down)
+
+        // start accelaratedScroll and scroll over to B -> null
+        draggable.onDragStarted()
+        draggable.onDelta(up(0.5f))
+        draggable.onDelta(up(0.5f))
+
+        // here onDragStopped is already triggered, but subsequent onDelta/onDragStopped calls may
+        // still be called. Make sure that they don't crash or change the scene
+        draggable.onDelta(up(0.5f))
+        draggable.onDragStopped(0f)
+
+        advanceUntilIdle()
+        assertIdle(SceneB)
+
+        // These events can still come in after the animation has settled
+        draggable.onDelta(up(0.5f))
+        draggable.onDragStopped(0f)
+        assertIdle(SceneB)
+    }
+
+    @Test
+    fun onDragTargetsChanged_targetStaysTheSame() = runGestureTest {
+        draggable.onDragStarted(up(0.1f))
+        assertTransition(fromScene = SceneA, toScene = SceneB, progress = 0.1f)
+
+        mutableUserActionsA[Swipe.Up] = SceneC
+        draggable.onDelta(up(0.1f))
+        // target stays B even though UserActions changed
+        assertTransition(fromScene = SceneA, toScene = SceneB, progress = 0.2f)
+        draggable.onDragStopped(down(0.1f))
+        advanceUntilIdle()
+
+        // now target changed to C for new drag
+        draggable.onDragStarted(up(0.1f))
+        assertTransition(fromScene = SceneA, toScene = SceneC, progress = 0.1f)
+    }
+
+    @Test
+    fun onDragTargetsChanged_targetsChangeWhenStartingNewDrag() = runGestureTest {
+        draggable.onDragStarted(up(0.1f))
+        assertTransition(fromScene = SceneA, toScene = SceneB, progress = 0.1f)
+
+        mutableUserActionsA[Swipe.Up] = SceneC
+        draggable.onDelta(up(0.1f))
+        draggable.onDragStopped(down(0.1f))
+
+        // now target changed to C for new drag that started before previous drag settled to Idle
+        draggable.onDragStarted(up(0.1f))
+        assertTransition(fromScene = SceneA, toScene = SceneC, progress = 0.3f)
     }
 
     @Test
     fun startGestureDuringAnimatingOffset_shouldImmediatelyStopTheAnimation() = runGestureTest {
         draggable.onDragStarted()
-        assertScene(currentScene = SceneA, isIdle = false)
+        assertTransition(currentScene = SceneA)
 
-        draggable.onDelta(pixels = deltaInPixels10)
-        assertScene(currentScene = SceneA, isIdle = false)
+        draggable.onDelta(pixels = down(0.1f))
+        assertTransition(currentScene = SceneA)
 
         draggable.onDragStopped(
             velocity = velocityThreshold,
         )
 
         // The stop animation is not started yet
-        assertThat(sceneGestureHandler.isAnimatingOffset).isFalse()
+        assertThat(sceneGestureHandler.swipeTransition.isAnimatingOffset).isFalse()
 
         runCurrent()
 
-        assertThat(sceneGestureHandler.isAnimatingOffset).isTrue()
+        assertThat(sceneGestureHandler.swipeTransition.isAnimatingOffset).isTrue()
         assertThat(sceneGestureHandler.isDrivingTransition).isTrue()
-        assertScene(currentScene = SceneC, isIdle = false)
+        assertTransition(currentScene = SceneC)
 
         // Start a new gesture while the offset is animating
         draggable.onDragStarted()
-        assertThat(sceneGestureHandler.isAnimatingOffset).isFalse()
+        assertThat(sceneGestureHandler.swipeTransition.isAnimatingOffset).isFalse()
     }
 
     @Test
     fun onInitialPreScroll_EdgeWithOverscroll_doNotChangeState() = runGestureTest {
-        val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeWithOverscroll)
+        val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeWithPreview)
         nestedScroll.onPreScroll(available = offsetY10, source = NestedScrollSource.Drag)
-        assertScene(currentScene = SceneA, isIdle = true)
+        assertIdle(currentScene = SceneA)
     }
 
     @Test
     fun onPostScrollWithNothingAvailable_EdgeWithOverscroll_doNotChangeState() = runGestureTest {
-        val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeWithOverscroll)
+        val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeWithPreview)
         val consumed =
             nestedScroll.onPostScroll(
                 consumed = Offset.Zero,
@@ -247,13 +512,13 @@
                 source = NestedScrollSource.Drag
             )
 
-        assertScene(currentScene = SceneA, isIdle = true)
+        assertIdle(currentScene = SceneA)
         assertThat(consumed).isEqualTo(Offset.Zero)
     }
 
     @Test
     fun onPostScrollWithSomethingAvailable_startSceneTransition() = runGestureTest {
-        val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeWithOverscroll)
+        val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeWithPreview)
         val consumed =
             nestedScroll.onPostScroll(
                 consumed = Offset.Zero,
@@ -261,7 +526,7 @@
                 source = NestedScrollSource.Drag
             )
 
-        assertScene(currentScene = SceneA, isIdle = false)
+        assertTransition(currentScene = SceneA)
         assertThat(progress).isEqualTo(0.1f)
         assertThat(consumed).isEqualTo(offsetY10)
     }
@@ -282,9 +547,9 @@
 
     @Test
     fun afterSceneTransitionIsStarted_interceptPreScrollEvents() = runGestureTest {
-        val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeWithOverscroll)
+        val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeWithPreview)
         nestedScroll.scroll(available = offsetY10)
-        assertScene(currentScene = SceneA, isIdle = false)
+        assertTransition(currentScene = SceneA)
 
         assertThat(progress).isEqualTo(0.1f)
 
@@ -303,14 +568,14 @@
 
         nestedScroll.scroll(available = offsetY10)
         assertThat(progress).isEqualTo(0.3f)
-        assertScene(currentScene = SceneA, isIdle = false)
+        assertTransition(currentScene = SceneA)
     }
 
     private suspend fun TestGestureScope.preScrollAfterSceneTransition(
         firstScroll: Float,
         secondScroll: Float
     ) {
-        val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeWithOverscroll)
+        val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeWithPreview)
         // start scene transition
         nestedScroll.scroll(available = Offset(0f, SCREEN_SIZE * firstScroll))
 
@@ -321,9 +586,6 @@
         nestedScroll.onPreScroll(Offset(0f, SCREEN_SIZE * secondScroll), NestedScrollSource.Drag)
     }
 
-    // Float tolerance for comparisons
-    private val tolerance = 0.00001f
-
     @Test
     fun scrollAndFling_scrollLessThanInterceptable_goToIdleOnCurrentScene() = runGestureTest {
         val first = transitionInterceptionThreshold - tolerance
@@ -331,7 +593,7 @@
 
         preScrollAfterSceneTransition(firstScroll = first, secondScroll = second)
 
-        assertScene(SceneA, isIdle = true)
+        assertIdle(SceneA)
     }
 
     @Test
@@ -341,7 +603,7 @@
 
         preScrollAfterSceneTransition(firstScroll = first, secondScroll = second)
 
-        assertThat(progress).isWithin(tolerance).of(first + second)
+        assertTransition(progress = first + second)
     }
 
     @Test
@@ -351,7 +613,7 @@
 
         preScrollAfterSceneTransition(firstScroll = first, secondScroll = second)
 
-        assertThat(progress).isWithin(tolerance).of(first + second)
+        assertTransition(progress = first + second)
     }
 
     @Test
@@ -361,21 +623,21 @@
 
         preScrollAfterSceneTransition(firstScroll = first, secondScroll = second)
 
-        assertScene(SceneC, isIdle = true)
+        assertIdle(SceneC)
     }
 
     @Test
     fun onPreFling_velocityLowerThanThreshold_remainSameScene() = runGestureTest {
-        val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeWithOverscroll)
+        val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeWithPreview)
         nestedScroll.scroll(available = offsetY10)
-        assertScene(currentScene = SceneA, isIdle = false)
+        assertTransition(currentScene = SceneA)
 
         nestedScroll.onPreFling(available = Velocity.Zero)
-        assertScene(currentScene = SceneA, isIdle = false)
+        assertTransition(currentScene = SceneA)
 
         // wait for the stop animation
         advanceUntilIdle()
-        assertScene(currentScene = SceneA, isIdle = true)
+        assertIdle(currentScene = SceneA)
     }
 
     private suspend fun TestGestureScope.flingAfterScroll(
@@ -384,7 +646,7 @@
     ) {
         val nestedScroll = nestedScrollConnection(nestedScrollBehavior = use)
         nestedScroll.scroll(available = offsetY10)
-        assertScene(currentScene = SceneA, isIdle = idleAfterScroll)
+        if (idleAfterScroll) assertIdle(SceneA) else assertTransition(SceneA)
 
         nestedScroll.onPreFling(available = Velocity(0f, velocityThreshold))
     }
@@ -393,40 +655,40 @@
     fun flingAfterScroll_DuringTransitionBetweenScenes_doNothing() = runGestureTest {
         flingAfterScroll(use = DuringTransitionBetweenScenes, idleAfterScroll = true)
 
-        assertScene(currentScene = SceneA, isIdle = true)
+        assertIdle(currentScene = SceneA)
     }
 
     @Test
     fun flingAfterScroll_EdgeNoOverscroll_goToNextScene() = runGestureTest {
-        flingAfterScroll(use = EdgeNoOverscroll, idleAfterScroll = false)
+        flingAfterScroll(use = EdgeNoPreview, idleAfterScroll = false)
 
-        assertScene(currentScene = SceneC, isIdle = false)
+        assertTransition(currentScene = SceneC)
 
         // wait for the stop animation
         advanceUntilIdle()
-        assertScene(currentScene = SceneC, isIdle = true)
+        assertIdle(currentScene = SceneC)
     }
 
     @Test
     fun flingAfterScroll_EdgeWithOverscroll_goToNextScene() = runGestureTest {
-        flingAfterScroll(use = EdgeWithOverscroll, idleAfterScroll = false)
+        flingAfterScroll(use = EdgeWithPreview, idleAfterScroll = false)
 
-        assertScene(currentScene = SceneC, isIdle = false)
+        assertTransition(currentScene = SceneC)
 
         // wait for the stop animation
         advanceUntilIdle()
-        assertScene(currentScene = SceneC, isIdle = true)
+        assertIdle(currentScene = SceneC)
     }
 
     @Test
     fun flingAfterScroll_Always_goToNextScene() = runGestureTest {
-        flingAfterScroll(use = Always, idleAfterScroll = false)
+        flingAfterScroll(use = EdgeAlways, idleAfterScroll = false)
 
-        assertScene(currentScene = SceneC, isIdle = false)
+        assertTransition(currentScene = SceneC)
 
         // wait for the stop animation
         advanceUntilIdle()
-        assertScene(currentScene = SceneC, isIdle = true)
+        assertIdle(currentScene = SceneC)
     }
 
     /** we started the scroll in the scene, then fling with the velocityThreshold */
@@ -440,7 +702,7 @@
 
         // scroll offsetY10 is all available for parents
         nestedScroll.scroll(available = offsetY10)
-        assertScene(currentScene = SceneA, isIdle = idleAfterScroll)
+        if (idleAfterScroll) assertIdle(SceneA) else assertTransition(SceneA)
 
         nestedScroll.onPreFling(available = Velocity(0f, velocityThreshold))
     }
@@ -449,64 +711,64 @@
     fun flingAfterScrollStartedInScene_DuringTransitionBetweenScenes_doNothing() = runGestureTest {
         flingAfterScrollStartedInScene(use = DuringTransitionBetweenScenes, idleAfterScroll = true)
 
-        assertScene(currentScene = SceneA, isIdle = true)
+        assertIdle(currentScene = SceneA)
     }
 
     @Test
     fun flingAfterScrollStartedInScene_EdgeNoOverscroll_doNothing() = runGestureTest {
-        flingAfterScrollStartedInScene(use = EdgeNoOverscroll, idleAfterScroll = true)
+        flingAfterScrollStartedInScene(use = EdgeNoPreview, idleAfterScroll = true)
 
-        assertScene(currentScene = SceneA, isIdle = true)
+        assertIdle(currentScene = SceneA)
     }
 
     @Test
     fun flingAfterScrollStartedInScene_EdgeWithOverscroll_doOverscrollAnimation() = runGestureTest {
-        flingAfterScrollStartedInScene(use = EdgeWithOverscroll, idleAfterScroll = false)
+        flingAfterScrollStartedInScene(use = EdgeWithPreview, idleAfterScroll = false)
 
-        assertScene(currentScene = SceneA, isIdle = false)
+        assertTransition(currentScene = SceneA)
 
         // wait for the stop animation
         advanceUntilIdle()
-        assertScene(currentScene = SceneA, isIdle = true)
+        assertIdle(currentScene = SceneA)
     }
 
     @Test
     fun flingAfterScrollStartedInScene_Always_goToNextScene() = runGestureTest {
-        flingAfterScrollStartedInScene(use = Always, idleAfterScroll = false)
+        flingAfterScrollStartedInScene(use = EdgeAlways, idleAfterScroll = false)
 
-        assertScene(currentScene = SceneC, isIdle = false)
+        assertTransition(currentScene = SceneC)
 
         // wait for the stop animation
         advanceUntilIdle()
-        assertScene(currentScene = SceneC, isIdle = true)
+        assertIdle(currentScene = SceneC)
     }
 
     @Test
     fun beforeDraggableStart_drag_shouldBeIgnored() = runGestureTest {
-        draggable.onDelta(deltaInPixels10)
-        assertScene(currentScene = SceneA, isIdle = true)
+        draggable.onDelta(down(0.1f))
+        assertIdle(currentScene = SceneA)
     }
 
     @Test
     fun beforeDraggableStart_stop_shouldBeIgnored() = runGestureTest {
         draggable.onDragStopped(velocityThreshold)
-        assertScene(currentScene = SceneA, isIdle = true)
+        assertIdle(currentScene = SceneA)
     }
 
     @Test
     fun beforeNestedScrollStart_stop_shouldBeIgnored() = runGestureTest {
-        val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeWithOverscroll)
+        val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeWithPreview)
         nestedScroll.onPreFling(Velocity(0f, velocityThreshold))
-        assertScene(currentScene = SceneA, isIdle = true)
+        assertIdle(currentScene = SceneA)
     }
 
     @Test
     fun startNestedScrollWhileDragging() = runGestureTest {
-        val nestedScroll = nestedScrollConnection(nestedScrollBehavior = Always)
+        val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeAlways)
         draggable.onDragStarted()
-        assertScene(currentScene = SceneA, isIdle = false)
+        assertTransition(currentScene = SceneA)
 
-        draggable.onDelta(deltaInPixels10)
+        draggable.onDelta(down(0.1f))
         assertThat(progress).isEqualTo(0.1f)
 
         // now we can intercept the scroll events
@@ -515,7 +777,7 @@
 
         // this should be ignored, we are scrolling now!
         draggable.onDragStopped(velocityThreshold)
-        assertScene(currentScene = SceneA, isIdle = false)
+        assertTransition(currentScene = SceneA)
 
         nestedScroll.scroll(available = offsetY10)
         assertThat(progress).isEqualTo(0.3f)
@@ -524,10 +786,10 @@
         assertThat(progress).isEqualTo(0.4f)
 
         nestedScroll.onPreFling(available = Velocity(0f, velocityThreshold))
-        assertScene(currentScene = SceneC, isIdle = false)
+        assertTransition(currentScene = SceneC)
 
         // wait for the stop animation
         advanceUntilIdle()
-        assertScene(currentScene = SceneC, isIdle = true)
+        assertIdle(currentScene = SceneC)
     }
 }
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 94c51ca..c5b8d9a 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
@@ -39,21 +39,9 @@
     }
 
     @Test
-    fun isTransitioningTo_fromSceneEqualToToScene() {
-        val state = SceneTransitionLayoutState(TestScenes.SceneA)
-        state.transitionState = transition(from = TestScenes.SceneA, to = TestScenes.SceneA)
-
-        assertThat(state.isTransitioning()).isFalse()
-        assertThat(state.isTransitioning(from = TestScenes.SceneA)).isFalse()
-        assertThat(state.isTransitioning(to = TestScenes.SceneB)).isFalse()
-        assertThat(state.isTransitioning(from = TestScenes.SceneA, to = TestScenes.SceneB))
-            .isFalse()
-    }
-
-    @Test
     fun isTransitioningTo_transition() {
-        val state = SceneTransitionLayoutState(TestScenes.SceneA)
-        state.transitionState = transition(from = TestScenes.SceneA, to = TestScenes.SceneB)
+        val state = SceneTransitionLayoutStateImpl(TestScenes.SceneA, SceneTransitions.Empty)
+        state.startTransition(transition(from = TestScenes.SceneA, to = TestScenes.SceneB))
 
         assertThat(state.isTransitioning()).isTrue()
         assertThat(state.isTransitioning(from = TestScenes.SceneA)).isTrue()
@@ -64,10 +52,8 @@
     }
 
     private fun transition(from: SceneKey, to: SceneKey): TransitionState.Transition {
-        return object : TransitionState.Transition {
+        return object : TransitionState.Transition(from, to) {
             override val currentScene: SceneKey = from
-            override val fromScene: SceneKey = from
-            override val toScene: SceneKey = to
             override val progress: Float = 0f
             override val isInitiatedByUserInput: Boolean = false
             override val isUserInputOngoing: Boolean = false
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 fa94b250..ef72992 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
@@ -55,7 +55,7 @@
 
         assertThat(transitions.transitionSpecs)
             .comparingElementsUsing(
-                Correspondence.transforming<TransitionSpec, Pair<SceneKey?, SceneKey?>>(
+                Correspondence.transforming<TransitionSpecImpl, Pair<SceneKey?, SceneKey?>>(
                     { it?.from to it?.to },
                     "has (from, to) equal to"
                 )
@@ -70,8 +70,8 @@
     @Test
     fun defaultTransitionSpec() {
         val transitions = transitions { from(TestScenes.SceneA, to = TestScenes.SceneB) }
-        val transition = transitions.transitionSpecs.single()
-        assertThat(transition.spec).isInstanceOf(SpringSpec::class.java)
+        val transformationSpec = transitions.transitionSpecs.single().transformationSpec()
+        assertThat(transformationSpec.progressSpec).isInstanceOf(SpringSpec::class.java)
     }
 
     @Test
@@ -79,9 +79,9 @@
         val transitions = transitions {
             from(TestScenes.SceneA, to = TestScenes.SceneB) { spec = tween(durationMillis = 42) }
         }
-        val transition = transitions.transitionSpecs.single()
-        assertThat(transition.spec).isInstanceOf(TweenSpec::class.java)
-        assertThat((transition.spec as TweenSpec).durationMillis).isEqualTo(42)
+        val transformationSpec = transitions.transitionSpecs.single().transformationSpec()
+        assertThat(transformationSpec.progressSpec).isInstanceOf(TweenSpec::class.java)
+        assertThat((transformationSpec.progressSpec as TweenSpec).durationMillis).isEqualTo(42)
     }
 
     @Test
@@ -90,9 +90,10 @@
             from(TestScenes.SceneA, to = TestScenes.SceneB) { fade(TestElements.Foo) }
         }
 
-        val transition = transitions.transitionSpecs.single()
-        assertThat(transition.transformations.size).isEqualTo(1)
-        assertThat(transition.transformations.single().range).isEqualTo(null)
+        val transformations =
+            transitions.transitionSpecs.single().transformationSpec().transformations
+        assertThat(transformations.size).isEqualTo(1)
+        assertThat(transformations.single().range).isEqualTo(null)
     }
 
     @Test
@@ -105,8 +106,9 @@
             }
         }
 
-        val transition = transitions.transitionSpecs.single()
-        assertThat(transition.transformations)
+        val transformations =
+            transitions.transitionSpecs.single().transformationSpec().transformations
+        assertThat(transformations)
             .comparingElementsUsing(TRANSFORMATION_RANGE)
             .containsExactly(
                 TransformationRange(start = 0.1f, end = 0.8f),
@@ -127,8 +129,9 @@
             }
         }
 
-        val transition = transitions.transitionSpecs.single()
-        assertThat(transition.transformations)
+        val transformations =
+            transitions.transitionSpecs.single().transformationSpec().transformations
+        assertThat(transformations)
             .comparingElementsUsing(TRANSFORMATION_RANGE)
             .containsExactly(
                 TransformationRange(start = 100 / 500f, end = 300 / 500f),
@@ -149,8 +152,9 @@
             }
         }
 
-        val transition = transitions.transitionSpecs.single()
-        assertThat(transition.transformations)
+        val transformations =
+            transitions.transitionSpecs.single().transformationSpec().transformations
+        assertThat(transformations)
             .comparingElementsUsing(TRANSFORMATION_RANGE)
             .containsExactly(
                 TransformationRange(start = 1f - 0.8f, end = 1f - 0.1f),
@@ -170,9 +174,13 @@
 
         // Fetch the transition from B to A, which will automatically reverse the transition from A
         // to B we defined.
-        val transition =
-            transitions.transitionSpec(from = TestScenes.SceneB, to = TestScenes.SceneA)
-        assertThat(transition.transformations)
+        val transformations =
+            transitions
+                .transitionSpec(from = TestScenes.SceneB, to = TestScenes.SceneA)
+                .transformationSpec()
+                .transformations
+
+        assertThat(transformations)
             .comparingElementsUsing(TRANSFORMATION_RANGE)
             .containsExactly(
                 TransformationRange(start = 1f - 0.8f, end = 1f - 0.1f),
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/transformation/AnchoredSizeTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/transformation/AnchoredSizeTest.kt
index 8ef6757..e555a01 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/transformation/AnchoredSizeTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/transformation/AnchoredSizeTest.kt
@@ -85,4 +85,50 @@
             after { onElement(TestElements.Bar).assertDoesNotExist() }
         }
     }
+
+    @Test
+    fun testAnchoredWidthOnly() {
+        rule.testTransition(
+            fromSceneContent = { Box(Modifier.size(100.dp, 100.dp).element(TestElements.Foo)) },
+            toSceneContent = {
+                Box(Modifier.size(50.dp, 50.dp).element(TestElements.Foo))
+                Box(Modifier.size(200.dp, 60.dp).element(TestElements.Bar))
+            },
+            transition = {
+                spec = tween(16 * 4, easing = LinearEasing)
+                anchoredSize(TestElements.Bar, TestElements.Foo, anchorHeight = false)
+            },
+        ) {
+            before { onElement(TestElements.Bar).assertDoesNotExist() }
+            at(0) { onElement(TestElements.Bar).assertSizeIsEqualTo(100.dp, 60.dp) }
+            at(16) { onElement(TestElements.Bar).assertSizeIsEqualTo(125.dp, 60.dp) }
+            at(32) { onElement(TestElements.Bar).assertSizeIsEqualTo(150.dp, 60.dp) }
+            at(48) { onElement(TestElements.Bar).assertSizeIsEqualTo(175.dp, 60.dp) }
+            at(64) { onElement(TestElements.Bar).assertSizeIsEqualTo(200.dp, 60.dp) }
+            after { onElement(TestElements.Bar).assertSizeIsEqualTo(200.dp, 60.dp) }
+        }
+    }
+
+    @Test
+    fun testAnchoredHeightOnly() {
+        rule.testTransition(
+            fromSceneContent = { Box(Modifier.size(100.dp, 100.dp).element(TestElements.Foo)) },
+            toSceneContent = {
+                Box(Modifier.size(50.dp, 50.dp).element(TestElements.Foo))
+                Box(Modifier.size(200.dp, 60.dp).element(TestElements.Bar))
+            },
+            transition = {
+                spec = tween(16 * 4, easing = LinearEasing)
+                anchoredSize(TestElements.Bar, TestElements.Foo, anchorWidth = false)
+            },
+        ) {
+            before { onElement(TestElements.Bar).assertDoesNotExist() }
+            at(0) { onElement(TestElements.Bar).assertSizeIsEqualTo(200.dp, 100.dp) }
+            at(16) { onElement(TestElements.Bar).assertSizeIsEqualTo(200.dp, 90.dp) }
+            at(32) { onElement(TestElements.Bar).assertSizeIsEqualTo(200.dp, 80.dp) }
+            at(48) { onElement(TestElements.Bar).assertSizeIsEqualTo(200.dp, 70.dp) }
+            at(64) { onElement(TestElements.Bar).assertSizeIsEqualTo(200.dp, 60.dp) }
+            after { onElement(TestElements.Bar).assertSizeIsEqualTo(200.dp, 60.dp) }
+        }
+    }
 }
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 03d231a..e2974cd 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
@@ -17,6 +17,7 @@
 package com.android.compose.nestedscroll
 
 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
@@ -36,6 +37,15 @@
             heightRange = heightRange,
         )
 
+    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)
@@ -50,6 +60,41 @@
     }
 
     @Test
+    fun onScrollUpAfterContentScrolled_ignoreUpEvent() {
+        val scrollConnection = buildScrollConnection(heightRange = 0f..2f)
+        height = 1f
+
+        // scroll down consumed by a child
+        scrollConnection.scroll(available = Offset(0f, 1f), consumedByScroll = Offset(0f, 1f))
+
+        val offsetConsumed =
+            scrollConnection.onPreScroll(available = Offset(x = 0f, y = -1f), source = scrollSource)
+
+        // It should ignore all onPreScroll events
+        assertThat(offsetConsumed).isEqualTo(Offset.Zero)
+        assertThat(height).isEqualTo(1f)
+    }
+
+    @Test
+    fun onScrollUpAfterContentReturnedToZero_consumeHeight() {
+        val scrollConnection = buildScrollConnection(heightRange = 0f..2f)
+        height = 1f
+
+        // scroll down consumed by a child
+        scrollConnection.scroll(available = Offset(0f, 1f), consumedByScroll = Offset(0f, 1f))
+
+        // scroll up consumed by a child, the child is in its original position
+        scrollConnection.scroll(available = Offset(0f, -1f), consumedByScroll = Offset(0f, -1f))
+
+        val offsetConsumed =
+            scrollConnection.onPreScroll(available = Offset(x = 0f, y = -1f), source = scrollSource)
+
+        // It should ignore all onPreScroll events
+        assertThat(offsetConsumed).isEqualTo(Offset(0f, -1f))
+        assertThat(height).isEqualTo(0f)
+    }
+
+    @Test
     fun onScrollUp_consumeDownToMin() {
         val scrollConnection = buildScrollConnection(heightRange = 0f..2f)
         height = 0f
@@ -110,6 +155,27 @@
     }
 
     @Test
+    fun onScrollDownAfterPostScroll_consumeHeightPreScroll() {
+        val scrollConnection = buildScrollConnection(heightRange = 0f..2f)
+        height = 1f
+        scrollConnection.onPostScroll(
+            consumed = Offset.Zero,
+            available = Offset(x = 0f, y = 0.5f),
+            source = scrollSource
+        )
+
+        val offsetConsumed =
+            scrollConnection.onPreScroll(
+                available = Offset(x = 0f, y = 0.5f),
+                source = scrollSource
+            )
+        assertThat(offsetConsumed).isEqualTo(Offset(0f, 0.5f))
+
+        // It can increase by 1 (0.5f + 0.5f) the height
+        assertThat(height).isEqualTo(2f)
+    }
+
+    @Test
     fun onScrollDown_consumeUpToMax() {
         val scrollConnection = buildScrollConnection(heightRange = 0f..2f)
         height = 2f
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/nestedscroll/PriorityNestedScrollConnectionTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/nestedscroll/PriorityNestedScrollConnectionTest.kt
index 122774b..8a9a92e 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/nestedscroll/PriorityNestedScrollConnectionTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/nestedscroll/PriorityNestedScrollConnectionTest.kt
@@ -46,6 +46,7 @@
             canStartPostScroll = { _, _ -> canStartPostScroll },
             canStartPostFling = { canStartPostFling },
             canContinueScroll = { canContinueScroll },
+            canScrollOnFling = false,
             onStart = { isStarted = true },
             onScroll = {
                 lastScroll = it
diff --git a/packages/SystemUI/docs/executors.md b/packages/SystemUI/docs/executors.md
index 8520ce2..2d9438c 100644
--- a/packages/SystemUI/docs/executors.md
+++ b/packages/SystemUI/docs/executors.md
@@ -14,10 +14,10 @@
 [FakeExecutor][FakeExecutor] is available.
 
 [Executor]: https://developer.android.com/reference/java/util/concurrent/Executor.html
-[Handler]: https://developer.android.com/reference/android/os/Handler
+[Handler]: https://developer.android.com/reference/android/os/Handler.html
 [Runnable]: https://developer.android.com/reference/java/lang/Runnable.html
 [DelayableExecutor]: /packages/SystemUI/src/com/android/systemui/util/concurrency/DelayableExecutor.java
-[FakeExecutor]: /packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutor.java
+[FakeExecutor]: /packages/SystemUI/tests/utils/src/com/android/systemui/util/concurrency/FakeExecutor.java
 
 ## Rationale
 
@@ -117,7 +117,7 @@
 postDelayed() | `none`    | executeDelayed()
 postAtTime()  | `none`    | executeAtTime()
 
-There is one notable gap in this implementation: `Handler.postAtFrontOfQueue()`.
+There are some notable gaps in this implementation: `Handler.postAtFrontOfQueue()`.
 If you require this method, or similar, please reach out. The idea of a
 PriorityQueueExecutor has been floated, but will not be implemented until there
 is a clear need.
@@ -173,13 +173,20 @@
 
 If you feel that you have a use case that this does not cover, please reach out.
 
+### ContentObserver
+
+One notable place where Handlers have been a requirement in the past is with
+[ContentObserver], which takes a Handler as an argument. However, we have created
+[ExecutorContentObserver], which is a hidden API that accepts an [Executor] in its
+constructor instead of a [Handler], and is otherwise identical.
+
+[ContentObserver]: https://developer.android.com/reference/android/database/ContentObserver.html
+[ExecutorContentObserver]: /core/java/android/database/ExecutorContentObserver.java
+
 ### Handlers Are Still Necessary
 
-Handlers aren't going away. There are Android APIs that still require them (even
-if future API development discourages them). A simple example is
-[ContentObserver][ContentObserver]. Use them where necessary.
-
-[ContentObserver]: https://developer.android.com/reference/android/database/ContentObserver
+Handlers aren't going away. There are other Android APIs that still require them.
+Avoid Handlers when possible, but use them where necessary.
 
 ## Testing (FakeExecutor)
 
@@ -314,6 +321,15 @@
 The Runnables _will not_ interleave. All of one Executor's callbacks will run,
 then all of the other's.
 
+### Testing Handlers without Loopers
+
+If a [Handler] is required because it is used by Android APIs, but is only
+used in simple ways (i.e. just `Handler.post(Runnable)`), you may still
+want the benefits of [FakeExecutor] when writing your tests, which
+you can get by wrapping the [Executor] in a mock for testing. This can be
+done with `com.android.systemui.util.concurrency.mockExecutorHandler` in
+`MockExecutorHandler.kt`.
+
 ### TestableLooper.RunWithLooper
 
 As long as you're using FakeExecutors in all the code under test (and no
diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
index 543b291..f170135 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
@@ -18,7 +18,7 @@
 package com.android.keyguard
 
 import android.content.res.Configuration
-import android.hardware.biometrics.BiometricOverlayConstants
+import android.hardware.biometrics.BiometricRequestConstants
 import android.media.AudioManager
 import android.telephony.TelephonyManager
 import android.testing.TestableLooper.RunWithLooper
@@ -59,6 +59,7 @@
 import com.android.systemui.scene.shared.model.ObservableTransitionState
 import com.android.systemui.scene.shared.model.SceneKey
 import com.android.systemui.scene.shared.model.SceneModel
+import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.statusbar.policy.DevicePostureController
 import com.android.systemui.statusbar.policy.DeviceProvisionedController
@@ -235,6 +236,7 @@
                 sceneInteractor = sceneInteractor,
             )
 
+        mSetFlagsRule.disableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
         underTest =
             KeyguardSecurityContainerController(
                 view,
@@ -465,29 +467,6 @@
     }
 
     @Test
-    fun showNextSecurityScreenOrFinish_setsSecurityScreenToPinAfterSimPinUnlock() {
-        // GIVEN the current security method is SimPin
-        whenever(keyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(false)
-        whenever(keyguardUpdateMonitor.getUserUnlockedWithBiometric(TARGET_USER_ID))
-            .thenReturn(false)
-        underTest.showSecurityScreen(SecurityMode.SimPin)
-
-        // WHEN a request is made from the SimPin screens to show the next security method
-        whenever(keyguardSecurityModel.getSecurityMode(TARGET_USER_ID)).thenReturn(SecurityMode.PIN)
-        underTest.showNextSecurityScreenOrFinish(
-            /* authenticated= */ true,
-            TARGET_USER_ID,
-            /* bypassSecondaryLockScreen= */ true,
-            SecurityMode.SimPin
-        )
-
-        // THEN the next security method of PIN is set, and the keyguard is not marked as done
-        verify(viewMediatorCallback, never()).keyguardDonePending(anyInt())
-        verify(viewMediatorCallback, never()).keyguardDone(anyInt())
-        Truth.assertThat(underTest.currentSecurityMode).isEqualTo(SecurityMode.PIN)
-    }
-
-    @Test
     fun showNextSecurityScreenOrFinish_DeviceNotSecure() {
         // GIVEN the current security method is SimPin
         whenever(keyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(false)
@@ -578,6 +557,57 @@
     }
 
     @Test
+    fun showNextSecurityScreenOrFinish_SimPin_Password() {
+        // GIVEN the current security method is SimPin
+        whenever(keyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(false)
+        whenever(keyguardUpdateMonitor.getUserUnlockedWithBiometric(TARGET_USER_ID))
+            .thenReturn(false)
+        underTest.showSecurityScreen(SecurityMode.SimPin)
+
+        // WHEN a request is made from the SimPin screens to show the next security method
+        whenever(keyguardSecurityModel.getSecurityMode(TARGET_USER_ID))
+            .thenReturn(SecurityMode.Password)
+        // WHEN security method is SWIPE
+        whenever(lockPatternUtils.isLockScreenDisabled(anyInt())).thenReturn(false)
+        whenever(deviceProvisionedController.isUserSetup(anyInt())).thenReturn(false)
+        underTest.showNextSecurityScreenOrFinish(
+            /* authenticated= */ true,
+            TARGET_USER_ID,
+            /* bypassSecondaryLockScreen= */ true,
+            SecurityMode.SimPin
+        )
+
+        // THEN we will not show the password screen.
+        verify(viewFlipperController, never())
+            .getSecurityView(eq(SecurityMode.Password), any(), any())
+    }
+
+    @Test
+    fun showNextSecurityScreenOrFinish_SimPin_SimPin() {
+        // GIVEN the current security method is SimPin
+        whenever(keyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(false)
+        whenever(keyguardUpdateMonitor.getUserUnlockedWithBiometric(TARGET_USER_ID))
+            .thenReturn(false)
+        underTest.showSecurityScreen(SecurityMode.SimPin)
+
+        // WHEN a request is made from the SimPin screens to show the next security method
+        whenever(keyguardSecurityModel.getSecurityMode(TARGET_USER_ID))
+            .thenReturn(SecurityMode.SimPin)
+        // WHEN security method is SWIPE
+        whenever(lockPatternUtils.isLockScreenDisabled(anyInt())).thenReturn(false)
+        whenever(deviceProvisionedController.isUserSetup(anyInt())).thenReturn(false)
+        underTest.showNextSecurityScreenOrFinish(
+            /* authenticated= */ true,
+            TARGET_USER_ID,
+            /* bypassSecondaryLockScreen= */ true,
+            SecurityMode.SimPin
+        )
+
+        // THEN we will not show the password screen.
+        verify(viewFlipperController).getSecurityView(eq(SecurityMode.SimPin), any(), any())
+    }
+
+    @Test
     fun onSwipeUp_forwardsItToFaceAuthInteractor() {
         val registeredSwipeListener = registeredSwipeListener
         setupGetSecurityView(SecurityMode.Password)
@@ -735,16 +765,18 @@
 
     @Test
     fun sideFpsControllerShow() {
+        mSetFlagsRule.disableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
         underTest.updateSideFpsVisibility(/* isVisible= */ true)
         verify(sideFpsController)
             .show(
                 SideFpsUiRequestSource.PRIMARY_BOUNCER,
-                BiometricOverlayConstants.REASON_AUTH_KEYGUARD
+                BiometricRequestConstants.REASON_AUTH_KEYGUARD
             )
     }
 
     @Test
     fun sideFpsControllerHide() {
+        mSetFlagsRule.disableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
         underTest.updateSideFpsVisibility(/* isVisible= */ false)
         verify(sideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER)
     }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt
index 94c3bde..84d73543 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt
@@ -34,11 +34,14 @@
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
 import org.mockito.ArgumentMatchers.anyString
 import org.mockito.Mock
 import org.mockito.Mockito
 import org.mockito.Mockito.anyInt
 import org.mockito.Mockito.mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.reset
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.`when`
 import org.mockito.MockitoAnnotations
@@ -63,6 +66,8 @@
     @Mock
     private lateinit var keyguardMessageAreaController:
         KeyguardMessageAreaController<BouncerKeyguardMessageArea>
+    private val updateMonitorCallbackArgumentCaptor =
+        ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
 
     @Before
     fun setup() {
@@ -95,6 +100,9 @@
                 mSelectedUserInteractor
             )
         underTest.init()
+        underTest.onResume(0)
+        verify(keyguardUpdateMonitor)
+            .registerCallback(updateMonitorCallbackArgumentCaptor.capture())
     }
 
     @Test
@@ -111,6 +119,7 @@
 
     @Test
     fun onResume() {
+        reset(keyguardUpdateMonitor)
         underTest.onResume(KeyguardSecurityView.VIEW_REVEALED)
         verify(keyguardUpdateMonitor)
             .registerCallback(any(KeyguardUpdateMonitorCallback::class.java))
@@ -137,4 +146,22 @@
         underTest.resetState()
         verify(keyguardMessageAreaController).setMessage("")
     }
+
+    @Test
+    fun onSimStateChangedFromPinToPuk_showsCurrentSecurityScreen() {
+        updateMonitorCallbackArgumentCaptor.value.onSimStateChanged(
+            /* subId= */ 0,
+            /* slotId= */ 0,
+            TelephonyManager.SIM_STATE_PIN_REQUIRED
+        )
+        verify(keyguardSecurityCallback, never()).showCurrentSecurityScreen()
+
+        updateMonitorCallbackArgumentCaptor.value.onSimStateChanged(
+            /* subId= */ 0,
+            /* slotId= */ 0,
+            TelephonyManager.SIM_STATE_PUK_REQUIRED
+        )
+
+        verify(keyguardSecurityCallback).showCurrentSecurityScreen()
+    }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/data/repository/ColorCorrectionRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/data/repository/ColorCorrectionRepositoryImplTest.kt
new file mode 100644
index 0000000..74f50d8
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/data/repository/ColorCorrectionRepositoryImplTest.kt
@@ -0,0 +1,171 @@
+/*
+ * 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.accessibility.data.repository
+
+import android.os.UserHandle
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.settings.FakeSettings
+import com.google.common.truth.Truth
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class ColorCorrectionRepositoryImplTest : SysuiTestCase() {
+    companion object {
+        val TEST_USER_1 = UserHandle.of(1)!!
+        val TEST_USER_2 = UserHandle.of(2)!!
+    }
+
+    private val testDispatcher = StandardTestDispatcher()
+    private val scope = TestScope(testDispatcher)
+    private val settings: FakeSettings = FakeSettings()
+
+    private lateinit var underTest: ColorCorrectionRepository
+
+    @Before
+    fun setUp() {
+        underTest =
+            ColorCorrectionRepositoryImpl(
+                testDispatcher,
+                settings,
+            )
+    }
+
+    @Test
+    fun isEnabled_initiallyGetsSettingsValue() =
+        scope.runTest {
+            settings.putIntForUser(
+                ColorCorrectionRepositoryImpl.SETTING_NAME,
+                1,
+                TEST_USER_1.identifier
+            )
+
+            underTest =
+                ColorCorrectionRepositoryImpl(
+                    testDispatcher,
+                    settings,
+                )
+
+            underTest.isEnabled(TEST_USER_1).launchIn(backgroundScope)
+            runCurrent()
+
+            val actualValue: Boolean = underTest.isEnabled(TEST_USER_1).first()
+            Truth.assertThat(actualValue).isTrue()
+        }
+
+    @Test
+    fun isEnabled_settingUpdated_valueUpdated() =
+        scope.runTest {
+            underTest.isEnabled(TEST_USER_1).launchIn(backgroundScope)
+
+            settings.putIntForUser(
+                ColorCorrectionRepositoryImpl.SETTING_NAME,
+                ColorCorrectionRepositoryImpl.DISABLED,
+                TEST_USER_1.identifier
+            )
+            runCurrent()
+            Truth.assertThat(underTest.isEnabled(TEST_USER_1).first()).isFalse()
+
+            settings.putIntForUser(
+                ColorCorrectionRepositoryImpl.SETTING_NAME,
+                ColorCorrectionRepositoryImpl.ENABLED,
+                TEST_USER_1.identifier
+            )
+            runCurrent()
+            Truth.assertThat(underTest.isEnabled(TEST_USER_1).first()).isTrue()
+
+            settings.putIntForUser(
+                ColorCorrectionRepositoryImpl.SETTING_NAME,
+                ColorCorrectionRepositoryImpl.DISABLED,
+                TEST_USER_1.identifier
+            )
+            runCurrent()
+            Truth.assertThat(underTest.isEnabled(TEST_USER_1).first()).isFalse()
+        }
+
+    @Test
+    fun isEnabled_settingForUserOneOnly_valueUpdatedForUserOneOnly() =
+        scope.runTest {
+            underTest.isEnabled(TEST_USER_1).launchIn(backgroundScope)
+            settings.putIntForUser(
+                ColorCorrectionRepositoryImpl.SETTING_NAME,
+                ColorCorrectionRepositoryImpl.DISABLED,
+                TEST_USER_1.identifier
+            )
+            underTest.isEnabled(TEST_USER_2).launchIn(backgroundScope)
+            settings.putIntForUser(
+                ColorCorrectionRepositoryImpl.SETTING_NAME,
+                ColorCorrectionRepositoryImpl.DISABLED,
+                TEST_USER_2.identifier
+            )
+
+            runCurrent()
+            Truth.assertThat(underTest.isEnabled(TEST_USER_1).first()).isFalse()
+            Truth.assertThat(underTest.isEnabled(TEST_USER_2).first()).isFalse()
+
+            settings.putIntForUser(
+                ColorCorrectionRepositoryImpl.SETTING_NAME,
+                ColorCorrectionRepositoryImpl.ENABLED,
+                TEST_USER_1.identifier
+            )
+            runCurrent()
+            Truth.assertThat(underTest.isEnabled(TEST_USER_1).first()).isTrue()
+            Truth.assertThat(underTest.isEnabled(TEST_USER_2).first()).isFalse()
+        }
+
+    @Test
+    fun setEnabled() =
+        scope.runTest {
+            val success = underTest.setIsEnabled(true, TEST_USER_1)
+            runCurrent()
+            Truth.assertThat(success).isTrue()
+
+            val actualValue =
+                settings.getIntForUser(
+                    ColorCorrectionRepositoryImpl.SETTING_NAME,
+                    TEST_USER_1.identifier
+                )
+            Truth.assertThat(actualValue).isEqualTo(ColorCorrectionRepositoryImpl.ENABLED)
+        }
+
+    @Test
+    fun setDisabled() =
+        scope.runTest {
+            val success = underTest.setIsEnabled(false, TEST_USER_1)
+            runCurrent()
+            Truth.assertThat(success).isTrue()
+
+            val actualValue =
+                settings.getIntForUser(
+                    ColorCorrectionRepositoryImpl.SETTING_NAME,
+                    TEST_USER_1.identifier
+                )
+            Truth.assertThat(actualValue).isEqualTo(ColorCorrectionRepositoryImpl.DISABLED)
+        }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt
index d968c1b..08cd7ed 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt
@@ -21,14 +21,12 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository
+import com.android.systemui.authentication.shared.model.AuthenticationLockoutModel
 import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.authentication.shared.model.AuthenticationPatternCoordinate
-import com.android.systemui.authentication.shared.model.AuthenticationThrottlingModel
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.scene.SceneTestUtils
 import com.google.common.truth.Truth.assertThat
-import kotlin.time.Duration.Companion.milliseconds
-import kotlin.time.Duration.Companion.seconds
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.test.advanceTimeBy
 import kotlinx.coroutines.test.runCurrent
@@ -78,12 +76,13 @@
     @Test
     fun authenticate_withCorrectPin_succeeds() =
         testScope.runTest {
-            val throttling by collectLastValue(underTest.throttling)
+            val lockout by collectLastValue(underTest.lockout)
             utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
 
             assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN))
                 .isEqualTo(AuthenticationResult.SUCCEEDED)
-            assertThat(throttling).isNull()
+            assertThat(lockout).isNull()
+            assertThat(utils.authenticationRepository.lockoutStartedReportCount).isEqualTo(0)
         }
 
     @Test
@@ -131,14 +130,15 @@
     @Test
     fun authenticate_withCorrectPassword_succeeds() =
         testScope.runTest {
-            val throttling by collectLastValue(underTest.throttling)
+            val lockout by collectLastValue(underTest.lockout)
             utils.authenticationRepository.setAuthenticationMethod(
                 AuthenticationMethodModel.Password
             )
 
             assertThat(underTest.authenticate("password".toList()))
                 .isEqualTo(AuthenticationResult.SUCCEEDED)
-            assertThat(throttling).isNull()
+            assertThat(lockout).isNull()
+            assertThat(utils.authenticationRepository.lockoutStartedReportCount).isEqualTo(0)
         }
 
     @Test
@@ -187,7 +187,7 @@
     fun tryAutoConfirm_withAutoConfirmPinAndShorterPin_returnsNull() =
         testScope.runTest {
             val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled)
-            val throttling by collectLastValue(underTest.throttling)
+            val lockout by collectLastValue(underTest.lockout)
             utils.authenticationRepository.apply {
                 setAuthenticationMethod(AuthenticationMethodModel.Pin)
                 setAutoConfirmFeatureEnabled(true)
@@ -203,7 +203,8 @@
                     )
                 )
                 .isEqualTo(AuthenticationResult.SKIPPED)
-            assertThat(throttling).isNull()
+            assertThat(lockout).isNull()
+            assertThat(utils.authenticationRepository.lockoutStartedReportCount).isEqualTo(0)
         }
 
     @Test
@@ -264,7 +265,7 @@
         }
 
     @Test
-    fun tryAutoConfirm_withAutoConfirmCorrectPinButDuringThrottling_returnsNull() =
+    fun tryAutoConfirm_withAutoConfirmCorrectPinButDuringLockout_returnsNull() =
         testScope.runTest {
             val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled)
             val isUnlocked by collectLastValue(utils.deviceEntryRepository.isUnlocked)
@@ -272,7 +273,7 @@
             utils.authenticationRepository.apply {
                 setAuthenticationMethod(AuthenticationMethodModel.Pin)
                 setAutoConfirmFeatureEnabled(true)
-                setThrottleDuration(42)
+                setLockoutDuration(42)
             }
 
             val authResult =
@@ -315,69 +316,121 @@
         }
 
     @Test
-    fun throttling() =
+    fun isAutoConfirmEnabled_featureDisabled_returnsFalse() =
         testScope.runTest {
-            val throttling by collectLastValue(underTest.throttling)
+            val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled)
+            utils.authenticationRepository.setAutoConfirmFeatureEnabled(false)
+
+            assertThat(isAutoConfirmEnabled).isFalse()
+        }
+
+    @Test
+    fun isAutoConfirmEnabled_featureEnabled_returnsTrue() =
+        testScope.runTest {
+            val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled)
+            utils.authenticationRepository.setAutoConfirmFeatureEnabled(true)
+
+            assertThat(isAutoConfirmEnabled).isTrue()
+        }
+
+    @Test
+    fun isAutoConfirmEnabled_featureEnabledButDisabledByLockout() =
+        testScope.runTest {
+            val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled)
+            val lockout by collectLastValue(underTest.lockout)
+            utils.authenticationRepository.setAutoConfirmFeatureEnabled(true)
+
+            // The feature is enabled.
+            assertThat(isAutoConfirmEnabled).isTrue()
+
+            // Make many wrong attempts to trigger lockout.
+            repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT) {
+                underTest.authenticate(listOf(5, 6, 7)) // Wrong PIN
+            }
+            assertThat(lockout).isNotNull()
+            assertThat(utils.authenticationRepository.lockoutStartedReportCount).isEqualTo(1)
+
+            // Lockout disabled auto-confirm.
+            assertThat(isAutoConfirmEnabled).isFalse()
+
+            // Move the clock forward one more second, to completely finish the lockout period:
+            advanceTimeBy(FakeAuthenticationRepository.LOCKOUT_DURATION_MS + 1000L)
+            assertThat(lockout).isNull()
+
+            // Auto-confirm is still disabled, because lockout occurred at least once in this
+            // session.
+            assertThat(isAutoConfirmEnabled).isFalse()
+
+            // Correct PIN and unlocks successfully, resetting the 'session'.
+            assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN))
+                .isEqualTo(AuthenticationResult.SUCCEEDED)
+
+            // Auto-confirm is re-enabled.
+            assertThat(isAutoConfirmEnabled).isTrue()
+
+            assertThat(utils.authenticationRepository.lockoutStartedReportCount).isEqualTo(1)
+        }
+
+    @Test
+    fun lockout() =
+        testScope.runTest {
+            val lockout by collectLastValue(underTest.lockout)
             utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
             underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN)
-            assertThat(throttling).isNull()
+            assertThat(lockout).isNull()
 
-            // Make many wrong attempts, but just shy of what's needed to get throttled:
-            repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING - 1) {
+            // Make many wrong attempts, but just shy of what's needed to get locked out:
+            repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT - 1) {
                 underTest.authenticate(listOf(5, 6, 7)) // Wrong PIN
-                assertThat(throttling).isNull()
+                assertThat(lockout).isNull()
             }
 
-            // Make one more wrong attempt, leading to throttling:
+            // Make one more wrong attempt, leading to lockout:
             underTest.authenticate(listOf(5, 6, 7)) // Wrong PIN
-            assertThat(throttling)
+            assertThat(lockout)
                 .isEqualTo(
-                    AuthenticationThrottlingModel(
+                    AuthenticationLockoutModel(
                         failedAttemptCount =
-                            FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING,
-                        remainingMs = FakeAuthenticationRepository.THROTTLE_DURATION_MS,
+                            FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT,
+                        remainingSeconds = FakeAuthenticationRepository.LOCKOUT_DURATION_SECONDS,
                     )
                 )
+            assertThat(utils.authenticationRepository.lockoutStartedReportCount).isEqualTo(1)
 
-            // Correct PIN, but throttled, so doesn't attempt it:
+            // Correct PIN, but locked out, so doesn't attempt it:
             assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN))
                 .isEqualTo(AuthenticationResult.SKIPPED)
-            assertThat(throttling)
+            assertThat(lockout)
                 .isEqualTo(
-                    AuthenticationThrottlingModel(
+                    AuthenticationLockoutModel(
                         failedAttemptCount =
-                            FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING,
-                        remainingMs = FakeAuthenticationRepository.THROTTLE_DURATION_MS,
+                            FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT,
+                        remainingSeconds = FakeAuthenticationRepository.LOCKOUT_DURATION_SECONDS,
                     )
                 )
 
-            // Move the clock forward to ALMOST skip the throttling, leaving one second to go:
-            val throttleTimeoutSec =
-                FakeAuthenticationRepository.THROTTLE_DURATION_MS.milliseconds.inWholeSeconds
-                    .toInt()
-            repeat(throttleTimeoutSec - 1) { time ->
+            // Move the clock forward to ALMOST skip the lockout, leaving one second to go:
+            val lockoutTimeoutSec = FakeAuthenticationRepository.LOCKOUT_DURATION_SECONDS
+            repeat(FakeAuthenticationRepository.LOCKOUT_DURATION_SECONDS - 1) { time ->
                 advanceTimeBy(1000)
-                assertThat(throttling)
+                assertThat(lockout)
                     .isEqualTo(
-                        AuthenticationThrottlingModel(
+                        AuthenticationLockoutModel(
                             failedAttemptCount =
-                                FakeAuthenticationRepository
-                                    .MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING,
-                            remainingMs =
-                                ((throttleTimeoutSec - (time + 1)).seconds.inWholeMilliseconds)
-                                    .toInt(),
+                                FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT,
+                            remainingSeconds = lockoutTimeoutSec - (time + 1),
                         )
                     )
             }
 
-            // Move the clock forward one more second, to completely finish the throttling period:
+            // Move the clock forward one more second, to completely finish the lockout period:
             advanceTimeBy(1000)
-            assertThat(throttling).isNull()
+            assertThat(lockout).isNull()
 
-            // Correct PIN and no longer throttled so unlocks successfully:
+            // Correct PIN and no longer locked out so unlocks successfully:
             assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN))
                 .isEqualTo(AuthenticationResult.SUCCEEDED)
-            assertThat(throttling).isNull()
+            assertThat(lockout).isNull()
         }
 
     @Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
index a1b801c..f8321b7 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
@@ -22,9 +22,9 @@
 import android.content.ComponentName
 import android.graphics.Insets
 import android.graphics.Rect
-import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_KEYGUARD
-import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_SETTINGS
-import android.hardware.biometrics.BiometricOverlayConstants.REASON_UNKNOWN
+import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_KEYGUARD
+import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_SETTINGS
+import android.hardware.biometrics.BiometricRequestConstants.REASON_UNKNOWN
 import android.hardware.biometrics.SensorLocationInternal
 import android.hardware.biometrics.SensorProperties
 import android.hardware.display.DisplayManager
@@ -65,6 +65,7 @@
 import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.res.R
+import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.time.FakeSystemClock
@@ -144,6 +145,7 @@
 
     @Before
     fun setup() {
+        mSetFlagsRule.disableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
         displayRepository = FakeDisplayRepository()
         displayStateRepository = FakeDisplayStateRepository()
         keyguardBouncerRepository = FakeKeyguardBouncerRepository()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
index 90d36e7..a726b7c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
@@ -17,12 +17,12 @@
 package com.android.systemui.biometrics
 
 import android.graphics.Rect
-import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_BP
-import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_KEYGUARD
-import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_OTHER
-import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_SETTINGS
-import android.hardware.biometrics.BiometricOverlayConstants.REASON_ENROLL_ENROLLING
-import android.hardware.biometrics.BiometricOverlayConstants.ShowReason
+import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_BP
+import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_KEYGUARD
+import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_OTHER
+import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_SETTINGS
+import android.hardware.biometrics.BiometricRequestConstants.REASON_ENROLL_ENROLLING
+import android.hardware.biometrics.BiometricRequestConstants.RequestReason
 import android.hardware.fingerprint.IUdfpsOverlayControllerCallback
 import android.testing.TestableLooper.RunWithLooper
 import android.view.LayoutInflater
@@ -135,7 +135,7 @@
     }
 
     private fun withReason(
-        @ShowReason reason: Int,
+        @RequestReason reason: Int,
         isDebuggable: Boolean = false,
         enableDeviceEntryUdfpsRefactor: Boolean = false,
         block: () -> Unit,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index 97ee526..dddcf18 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -43,7 +43,7 @@
 
 import android.graphics.Rect;
 import android.hardware.biometrics.BiometricFingerprintConstants;
-import android.hardware.biometrics.BiometricOverlayConstants;
+import android.hardware.biometrics.BiometricRequestConstants;
 import android.hardware.biometrics.ComponentInfoInternal;
 import android.hardware.biometrics.SensorProperties;
 import android.hardware.display.DisplayManager;
@@ -359,7 +359,7 @@
     @Test
     public void dozeTimeTick() throws RemoteException {
         mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, mOpticalProps.sensorId,
-                BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
+                BiometricRequestConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
         mFgExecutor.runAllReady();
         mUdfpsController.dozeTimeTick();
         verify(mUdfpsView).dozeTimeTick();
@@ -455,7 +455,7 @@
     public void hideUdfpsOverlay_resetsAltAuthBouncerWhenShowing() throws RemoteException {
         // GIVEN overlay was showing and the udfps bouncer is showing
         mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, mOpticalProps.sensorId,
-                BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
+                BiometricRequestConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
         when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
 
         // WHEN the overlay is hidden
@@ -469,7 +469,7 @@
     @Test
     public void showUdfpsOverlay_callsListener() throws RemoteException {
         mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, mOpticalProps.sensorId,
-                BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
+                BiometricRequestConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
         mFgExecutor.runAllReady();
 
         verify(mFingerprintManager).onUdfpsUiEvent(FingerprintManager.UDFPS_UI_OVERLAY_SHOWN,
@@ -479,7 +479,7 @@
     @Test
     public void testSubscribesToOrientationChangesWhenShowingOverlay() throws Exception {
         mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, mOpticalProps.sensorId,
-                BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
+                BiometricRequestConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
         mFgExecutor.runAllReady();
 
         verify(mDisplayManager).registerDisplayListener(any(), eq(mHandler), anyLong());
@@ -520,7 +520,7 @@
                             reset(mWindowManager);
                             mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID,
                                     mOpticalProps.sensorId,
-                                    BiometricOverlayConstants.REASON_ENROLL_ENROLLING,
+                                    BiometricRequestConstants.REASON_ENROLL_ENROLLING,
                                     mUdfpsOverlayControllerCallback);
                             mFgExecutor.runAllReady();
                             verify(mWindowManager).addView(any(), any());
@@ -555,7 +555,7 @@
 
         // Show the overlay.
         mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, mOpticalProps.sensorId,
-                BiometricOverlayConstants.REASON_ENROLL_ENROLLING, mUdfpsOverlayControllerCallback);
+                BiometricRequestConstants.REASON_ENROLL_ENROLLING, mUdfpsOverlayControllerCallback);
         mFgExecutor.runAllReady();
         verify(mWindowManager).addView(any(), any());
 
@@ -637,7 +637,7 @@
 
         // Show the overlay.
         mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, testParams.sensorProps.sensorId,
-                BiometricOverlayConstants.REASON_ENROLL_ENROLLING, mUdfpsOverlayControllerCallback);
+                BiometricRequestConstants.REASON_ENROLL_ENROLLING, mUdfpsOverlayControllerCallback);
         mFgExecutor.runAllReady();
         verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture());
 
@@ -720,7 +720,7 @@
 
         initUdfpsController(testParams.sensorProps);
         mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, testParams.sensorProps.sensorId,
-                BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
+                BiometricRequestConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
         mFgExecutor.runAllReady();
 
         // WHEN ACTION_DOWN is received
@@ -778,7 +778,7 @@
 
         // GIVEN that the overlay is showing and screen is on and fp is running
         mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, testParams.sensorProps.sensorId,
-                BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
+                BiometricRequestConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
         mScreenObserver.onScreenTurnedOn();
         mFgExecutor.runAllReady();
         // WHEN fingerprint is requested because of AOD interrupt
@@ -808,7 +808,7 @@
 
         // GIVEN AOD interrupt
         mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, testParams.sensorProps.sensorId,
-                BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
+                BiometricRequestConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
         mScreenObserver.onScreenTurnedOn();
         mFgExecutor.runAllReady();
         mUdfpsController.onAodInterrupt(0, 0, 0f, 0f);
@@ -886,7 +886,7 @@
 
         // GIVEN overlay is showing
         mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, testParams.sensorProps.sensorId,
-                BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
+                BiometricRequestConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
         mFgExecutor.runAllReady();
         if (testParams.sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) {
             when(mUdfpsView.isDisplayConfigured()).thenReturn(true);
@@ -917,7 +917,7 @@
 
         // GIVEN AOD interrupt
         mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, testParams.sensorProps.sensorId,
-                BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
+                BiometricRequestConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
         mScreenObserver.onScreenTurnedOn();
         mFgExecutor.runAllReady();
         mUdfpsController.onAodInterrupt(0, 0, 0f, 0f);
@@ -958,7 +958,7 @@
         final Pair<TouchProcessorResult, TouchProcessorResult> touchProcessorResult =
                 givenFingerEvent(InteractionEvent.DOWN, InteractionEvent.UP, false);
         mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, testParams.sensorProps.sensorId,
-                BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
+                BiometricRequestConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
 
         if (testParams.sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) {
             // Configure UdfpsView to accept the ACTION_UP event
@@ -1019,7 +1019,7 @@
 
         // GIVEN screen off
         mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, testParams.sensorProps.sensorId,
-                BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
+                BiometricRequestConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
         mScreenObserver.onScreenTurnedOff();
         mFgExecutor.runAllReady();
 
@@ -1041,7 +1041,7 @@
 
         // GIVEN showing overlay
         mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, testParams.sensorProps.sensorId,
-                BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
+                BiometricRequestConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
         mScreenObserver.onScreenTurnedOn();
         mFgExecutor.runAllReady();
 
@@ -1126,7 +1126,7 @@
         // GIVEN that the overlay is showing and a11y touch exploration NOT enabled
         when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(a11y);
         mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, mOpticalProps.sensorId,
-                BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
+                BiometricRequestConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
         mFgExecutor.runAllReady();
 
         if (a11y) {
@@ -1148,7 +1148,7 @@
         // GIVEN that the overlay is showing and a11y touch exploration NOT enabled
         when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
         mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, mOpticalProps.sensorId,
-                BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
+                BiometricRequestConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
         mFgExecutor.runAllReady();
 
         verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture());
@@ -1197,7 +1197,7 @@
                         -1 /* pointerId */, touchData);
 
         mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, mOpticalProps.sensorId,
-                BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
+                BiometricRequestConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
         mFgExecutor.runAllReady();
 
         verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture());
@@ -1289,7 +1289,7 @@
     public void onAodInterrupt_onAcquiredGood_fingerNoLongerDown() throws RemoteException {
         // GIVEN UDFPS overlay is showing
         mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, mOpticalProps.sensorId,
-                BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
+                BiometricRequestConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
         mFgExecutor.runAllReady();
 
         // GIVEN there's been an AoD interrupt
@@ -1316,7 +1316,7 @@
             throws RemoteException {
         // GIVEN UDFPS overlay is showing
         mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, mOpticalProps.sensorId,
-                BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
+                BiometricRequestConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
         mFgExecutor.runAllReady();
 
         // GIVEN there's been an AoD interrupt
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerWithCoroutinesTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerWithCoroutinesTest.kt
index cbb772f..0ab596c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerWithCoroutinesTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerWithCoroutinesTest.kt
@@ -21,6 +21,8 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.keyguard.KeyguardSecurityModel
+import com.android.systemui.biometrics.UdfpsKeyguardViewLegacy.ANIMATE_APPEAR_ON_SCREEN_OFF
+import com.android.systemui.biometrics.UdfpsKeyguardViewLegacy.ANIMATION_BETWEEN_AOD_AND_LOCKSCREEN
 import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository
 import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepository
 import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepositoryImpl
@@ -56,10 +58,12 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.ArgumentMatchers.any
+import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.ArgumentMatchers.eq
 import org.mockito.Mock
 import org.mockito.Mockito
 import org.mockito.Mockito.mock
+import org.mockito.Mockito.never
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
 
@@ -539,4 +543,77 @@
                 .onDozeAmountChanged(eq(0f), eq(0f), eq(UdfpsKeyguardViewLegacy.ANIMATION_NONE))
             job.cancel()
         }
+
+    @Test
+    fun cancelledLockscreenToAod_dozeAmountNotUpdatedToZero() =
+        testScope.runTest {
+            // GIVEN view is attached
+            mController.onViewAttached()
+            Mockito.reset(mView)
+
+            val job = mController.listenForLockscreenAodTransitions(this)
+            // WHEN lockscreen to aod transition is cancelled
+            transitionRepository.sendTransitionStep(
+                TransitionStep(
+                    from = KeyguardState.LOCKSCREEN,
+                    to = KeyguardState.AOD,
+                    value = 1f,
+                    transitionState = TransitionState.CANCELED
+                )
+            )
+            runCurrent()
+
+            // THEN doze amount is NOT updated to zero
+            verify(mView, never()).onDozeAmountChanged(eq(0f), eq(0f), anyInt())
+            job.cancel()
+        }
+
+    @Test
+    fun dreamingToAod_dozeAmountChanged() =
+        testScope.runTest {
+            // GIVEN view is attached
+            mController.onViewAttached()
+            Mockito.reset(mView)
+
+            val job = mController.listenForDreamingToAodTransitions(this)
+            // WHEN dreaming to aod transition in progress
+            transitionRepository.sendTransitionStep(
+                TransitionStep(
+                    from = KeyguardState.DREAMING,
+                    to = KeyguardState.AOD,
+                    value = .3f,
+                    transitionState = TransitionState.RUNNING
+                )
+            )
+            runCurrent()
+
+            // THEN doze amount is updated to
+            verify(mView).onDozeAmountChanged(eq(.3f), eq(.3f), eq(ANIMATE_APPEAR_ON_SCREEN_OFF))
+            job.cancel()
+        }
+
+    @Test
+    fun alternateBouncerToAod_dozeAmountChanged() =
+        testScope.runTest {
+            // GIVEN view is attached
+            mController.onViewAttached()
+            Mockito.reset(mView)
+
+            val job = mController.listenForAlternateBouncerToAodTransitions(this)
+            // WHEN alternate bouncer to aod transition in progress
+            transitionRepository.sendTransitionStep(
+                TransitionStep(
+                    from = KeyguardState.ALTERNATE_BOUNCER,
+                    to = KeyguardState.AOD,
+                    value = .3f,
+                    transitionState = TransitionState.RUNNING
+                )
+            )
+            runCurrent()
+
+            // THEN doze amount is updated to
+            verify(mView)
+                .onDozeAmountChanged(eq(.3f), eq(.3f), eq(ANIMATION_BETWEEN_AOD_AND_LOCKSCREEN))
+            job.cancel()
+        }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
index 04f6cd3..9b1df7c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
@@ -21,15 +21,14 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository
 import com.android.systemui.authentication.domain.interactor.AuthenticationResult
+import com.android.systemui.authentication.shared.model.AuthenticationLockoutModel
 import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.authentication.shared.model.AuthenticationPatternCoordinate
-import com.android.systemui.authentication.shared.model.AuthenticationThrottlingModel
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor
 import com.android.systemui.res.R
 import com.android.systemui.scene.SceneTestUtils
 import com.google.common.truth.Truth.assertThat
-import kotlin.math.ceil
 import kotlin.time.Duration.Companion.milliseconds
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.test.advanceTimeBy
@@ -247,47 +246,42 @@
         }
 
     @Test
-    fun throttling() =
+    fun lockout() =
         testScope.runTest {
-            val throttling by collectLastValue(underTest.throttling)
+            val lockout by collectLastValue(underTest.lockout)
             val message by collectLastValue(underTest.message)
             utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
-            assertThat(throttling).isNull()
-            repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING) { times ->
+            assertThat(lockout).isNull()
+            repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT) { times ->
                 // Wrong PIN.
                 assertThat(underTest.authenticate(listOf(6, 7, 8, 9)))
                     .isEqualTo(AuthenticationResult.FAILED)
-                if (
-                    times < FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING - 1
-                ) {
+                if (times < FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT - 1) {
                     assertThat(message).isEqualTo(MESSAGE_WRONG_PIN)
                 }
             }
-            assertThat(throttling)
+            assertThat(lockout)
                 .isEqualTo(
-                    AuthenticationThrottlingModel(
+                    AuthenticationLockoutModel(
                         failedAttemptCount =
-                            FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING,
-                        remainingMs = FakeAuthenticationRepository.THROTTLE_DURATION_MS,
+                            FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT,
+                        remainingSeconds = FakeAuthenticationRepository.LOCKOUT_DURATION_SECONDS,
                     )
                 )
             assertTryAgainMessage(
                 message,
-                FakeAuthenticationRepository.THROTTLE_DURATION_MS.milliseconds.inWholeSeconds
-                    .toInt()
+                FakeAuthenticationRepository.LOCKOUT_DURATION_MS.milliseconds.inWholeSeconds.toInt()
             )
 
-            // Correct PIN, but throttled, so doesn't change away from the bouncer scene:
+            // Correct PIN, but locked out, so doesn't change away from the bouncer scene:
             assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN))
                 .isEqualTo(AuthenticationResult.SKIPPED)
             assertTryAgainMessage(
                 message,
-                FakeAuthenticationRepository.THROTTLE_DURATION_MS.milliseconds.inWholeSeconds
-                    .toInt()
+                FakeAuthenticationRepository.LOCKOUT_DURATION_MS.milliseconds.inWholeSeconds.toInt()
             )
 
-            throttling?.remainingMs?.let { remainingMs ->
-                val seconds = ceil(remainingMs / 1000f).toInt()
+            lockout?.remainingSeconds?.let { seconds ->
                 repeat(seconds) { time ->
                     advanceTimeBy(1000)
                     val remainingTimeSec = seconds - time - 1
@@ -297,12 +291,12 @@
                 }
             }
             assertThat(message).isEqualTo("")
-            assertThat(throttling).isNull()
+            assertThat(lockout).isNull()
 
-            // Correct PIN and no longer throttled so changes to the Gone scene:
+            // Correct PIN and no longer locked out so changes to the Gone scene:
             assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN))
                 .isEqualTo(AuthenticationResult.SUCCEEDED)
-            assertThat(throttling).isNull()
+            assertThat(lockout).isNull()
         }
 
     @Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt
index 45c186d..2f0843b 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt
@@ -35,7 +35,6 @@
 
     private val utils = SceneTestUtils(this)
     private val testScope = utils.testScope
-    private val sceneInteractor = utils.sceneInteractor()
     private val bouncerInteractor =
         utils.bouncerInteractor(
             authenticationInteractor = utils.authenticationInteractor(),
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt
index 75d6a00..16a9359 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt
@@ -26,6 +26,7 @@
 import com.android.systemui.scene.SceneTestUtils
 import com.google.common.truth.Truth.assertThat
 import com.google.common.truth.Truth.assertWithMessage
+import kotlin.time.Duration.Companion.seconds
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.emptyFlow
 import kotlinx.coroutines.flow.flatMapLatest
@@ -134,17 +135,19 @@
     fun message() =
         testScope.runTest {
             val message by collectLastValue(underTest.message)
-            val throttling by collectLastValue(bouncerInteractor.throttling)
+            val lockout by collectLastValue(bouncerInteractor.lockout)
             utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
             assertThat(message?.isUpdateAnimated).isTrue()
 
-            repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING) {
+            repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT) {
                 // Wrong PIN.
                 bouncerInteractor.authenticate(listOf(3, 4, 5, 6))
             }
             assertThat(message?.isUpdateAnimated).isFalse()
 
-            throttling?.remainingMs?.let { remainingMs -> advanceTimeBy(remainingMs.toLong()) }
+            lockout?.remainingSeconds?.let { remainingSeconds ->
+                advanceTimeBy(remainingSeconds.seconds.inWholeMilliseconds)
+            }
             assertThat(message?.isUpdateAnimated).isTrue()
         }
 
@@ -157,35 +160,37 @@
                         authViewModel?.isInputEnabled ?: emptyFlow()
                     }
                 )
-            val throttling by collectLastValue(bouncerInteractor.throttling)
+            val lockout by collectLastValue(bouncerInteractor.lockout)
             utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
             assertThat(isInputEnabled).isTrue()
 
-            repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING) {
+            repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT) {
                 // Wrong PIN.
                 bouncerInteractor.authenticate(listOf(3, 4, 5, 6))
             }
             assertThat(isInputEnabled).isFalse()
 
-            throttling?.remainingMs?.let { milliseconds -> advanceTimeBy(milliseconds.toLong()) }
+            lockout?.remainingSeconds?.let { remainingSeconds ->
+                advanceTimeBy(remainingSeconds.seconds.inWholeMilliseconds)
+            }
             assertThat(isInputEnabled).isTrue()
         }
 
     @Test
-    fun throttlingDialogMessage() =
+    fun dialogMessage() =
         testScope.runTest {
-            val throttlingDialogMessage by collectLastValue(underTest.throttlingDialogMessage)
+            val dialogMessage by collectLastValue(underTest.dialogMessage)
             utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
 
-            repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING) {
+            repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT) {
                 // Wrong PIN.
-                assertThat(throttlingDialogMessage).isNull()
+                assertThat(dialogMessage).isNull()
                 bouncerInteractor.authenticate(listOf(3, 4, 5, 6))
             }
-            assertThat(throttlingDialogMessage).isNotEmpty()
+            assertThat(dialogMessage).isNotEmpty()
 
-            underTest.onThrottlingDialogDismissed()
-            assertThat(throttlingDialogMessage).isNull()
+            underTest.onDialogDismissed()
+            assertThat(dialogMessage).isNull()
         }
 
     @Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModelTest.kt
index 90e0c19..a3bf3f4 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModelTest.kt
@@ -33,6 +33,7 @@
 import com.android.systemui.keyguard.DismissCallbackRegistry
 import com.android.systemui.keyguard.data.repository.TrustRepository
 import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor
+import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.user.domain.interactor.SelectedUserInteractor
 import com.android.systemui.utils.os.FakeHandler
@@ -105,8 +106,10 @@
         job.cancel()
     }
 
+    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
     @Test
     fun shouldUpdateSideFps_show() = runTest {
+        mSetFlagsRule.disableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
         var count = 0
         val job = underTest.shouldUpdateSideFps.onEach { count++ }.launchIn(this)
         repository.setPrimaryShow(true)
@@ -116,8 +119,10 @@
         job.cancel()
     }
 
+    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
     @Test
     fun shouldUpdateSideFps_hide() = runTest {
+        mSetFlagsRule.disableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
         repository.setPrimaryShow(true)
         var count = 0
         val job = underTest.shouldUpdateSideFps.onEach { count++ }.launchIn(this)
@@ -128,8 +133,10 @@
         job.cancel()
     }
 
+    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
     @Test
     fun sideFpsShowing() = runTest {
+        mSetFlagsRule.disableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
         var sideFpsIsShowing = false
         val job = underTest.sideFpsShowing.onEach { sideFpsIsShowing = it }.launchIn(this)
         repository.setSideFpsShowing(true)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt
index 64f2946..6d6baa5 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt
@@ -19,8 +19,8 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.authentication.shared.model.AuthenticationLockoutModel
 import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
-import com.android.systemui.authentication.shared.model.AuthenticationThrottlingModel
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.coroutines.collectValues
 import com.android.systemui.res.R
@@ -243,12 +243,12 @@
         }
 
     @Test
-    fun onImeVisibilityChanged_falseAfterTrue_whileThrottling_doesNothing() =
+    fun onImeVisibilityChanged_falseAfterTrue_whileLockedOut_doesNothing() =
         testScope.runTest {
             val events by collectValues(bouncerInteractor.onImeHiddenByUser)
             assertThat(events).isEmpty()
             underTest.onImeVisibilityChanged(isVisible = true)
-            setThrottling(true)
+            setLockout(true)
 
             underTest.onImeVisibilityChanged(isVisible = false)
 
@@ -284,11 +284,11 @@
         }
 
     @Test
-    fun isTextFieldFocusRequested_focusLostWhileThrottling_staysFalse() =
+    fun isTextFieldFocusRequested_focusLostWhileLockedOut_staysFalse() =
         testScope.runTest {
             val isTextFieldFocusRequested by collectLastValue(underTest.isTextFieldFocusRequested)
             underTest.onTextFieldFocusChanged(isFocused = true)
-            setThrottling(true)
+            setLockout(true)
 
             underTest.onTextFieldFocusChanged(isFocused = false)
 
@@ -296,14 +296,14 @@
         }
 
     @Test
-    fun isTextFieldFocusRequested_throttlingCountdownEnds_becomesTrue() =
+    fun isTextFieldFocusRequested_lockoutCountdownEnds_becomesTrue() =
         testScope.runTest {
             val isTextFieldFocusRequested by collectLastValue(underTest.isTextFieldFocusRequested)
             underTest.onTextFieldFocusChanged(isFocused = true)
-            setThrottling(true)
+            setLockout(true)
             underTest.onTextFieldFocusChanged(isFocused = false)
 
-            setThrottling(false)
+            setLockout(false)
 
             assertThat(isTextFieldFocusRequested).isTrue()
         }
@@ -327,24 +327,24 @@
         switchToScene(SceneKey.Bouncer)
     }
 
-    private suspend fun TestScope.setThrottling(
-        isThrottling: Boolean,
+    private suspend fun TestScope.setLockout(
+        isLockedOut: Boolean,
         failedAttemptCount: Int = 5,
     ) {
-        if (isThrottling) {
+        if (isLockedOut) {
             repeat(failedAttemptCount) {
                 authenticationRepository.reportAuthenticationAttempt(false)
             }
-            val remainingTimeMs = 30_000
-            authenticationRepository.setThrottleDuration(remainingTimeMs)
-            authenticationRepository.throttling.value =
-                AuthenticationThrottlingModel(
+            val remainingTimeSeconds = 30
+            authenticationRepository.setLockoutDuration(remainingTimeSeconds * 1000)
+            authenticationRepository.lockout.value =
+                AuthenticationLockoutModel(
                     failedAttemptCount = failedAttemptCount,
-                    remainingMs = remainingTimeMs,
+                    remainingSeconds = remainingTimeSeconds,
                 )
         } else {
             authenticationRepository.reportAuthenticationAttempt(true)
-            authenticationRepository.throttling.value = null
+            authenticationRepository.lockout.value = null
         }
 
         runCurrent()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt
index 862c39c..8971423 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt
@@ -304,13 +304,12 @@
     fun onDragEnd_whenPatternTooShort() =
         testScope.runTest {
             val message by collectLastValue(bouncerViewModel.message)
-            val throttlingDialogMessage by
-                collectLastValue(bouncerViewModel.throttlingDialogMessage)
+            val dialogMessage by collectLastValue(bouncerViewModel.dialogMessage)
             lockDeviceAndOpenPatternBouncer()
 
             // Enter a pattern that's too short more than enough times that would normally trigger
-            // throttling if the pattern were not too short and wrong:
-            val attempts = FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING + 1
+            // lockout if the pattern were not too short and wrong:
+            val attempts = FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT + 1
             repeat(attempts) { attempt ->
                 underTest.onDragStart()
                 CORRECT_PATTERN.subList(
@@ -328,7 +327,7 @@
                 underTest.onDragEnd()
 
                 assertWithMessage("Attempt #$attempt").that(message?.text).isEqualTo(WRONG_PATTERN)
-                assertWithMessage("Attempt #$attempt").that(throttlingDialogMessage).isNull()
+                assertWithMessage("Attempt #$attempt").that(dialogMessage).isNull()
             }
         }
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalRepositoryImplTest.kt
index 7196de6..65176e1 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalRepositoryImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalRepositoryImplTest.kt
@@ -20,6 +20,7 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.communal.shared.model.CommunalSceneKey
+import com.android.systemui.communal.shared.model.ObservableCommunalTransitionState
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.flags.FakeFeatureFlagsClassic
 import com.android.systemui.flags.Flags
@@ -29,6 +30,8 @@
 import com.android.systemui.scene.shared.model.SceneKey
 import com.android.systemui.scene.shared.model.SceneModel
 import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.test.StandardTestDispatcher
 import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
@@ -40,29 +43,30 @@
 class CommunalRepositoryImplTest : SysuiTestCase() {
     private lateinit var underTest: CommunalRepositoryImpl
 
-    private lateinit var testScope: TestScope
+    private val testDispatcher = StandardTestDispatcher()
+    private val testScope = TestScope(testDispatcher)
 
     private lateinit var featureFlagsClassic: FakeFeatureFlagsClassic
-    private lateinit var sceneContainerFlags: FakeSceneContainerFlags
     private lateinit var sceneContainerRepository: SceneContainerRepository
 
     @Before
     fun setUp() {
-        testScope = TestScope()
-
         val sceneTestUtils = SceneTestUtils(this)
-        sceneContainerFlags = FakeSceneContainerFlags(enabled = false)
         sceneContainerRepository = sceneTestUtils.fakeSceneContainerRepository()
         featureFlagsClassic = FakeFeatureFlagsClassic()
 
         featureFlagsClassic.set(Flags.COMMUNAL_SERVICE_ENABLED, true)
 
-        underTest =
-            CommunalRepositoryImpl(
-                featureFlagsClassic,
-                sceneContainerFlags,
-                sceneContainerRepository,
-            )
+        underTest = createRepositoryImpl(false)
+    }
+
+    private fun createRepositoryImpl(sceneContainerEnabled: Boolean): CommunalRepositoryImpl {
+        return CommunalRepositoryImpl(
+            testScope.backgroundScope,
+            featureFlagsClassic,
+            FakeSceneContainerFlags(enabled = sceneContainerEnabled),
+            sceneContainerRepository,
+        )
     }
 
     @Test
@@ -86,13 +90,7 @@
     @Test
     fun isCommunalShowing_sceneContainerEnabled_onCommunalScene_true() =
         testScope.runTest {
-            sceneContainerFlags = FakeSceneContainerFlags(enabled = true)
-            underTest =
-                CommunalRepositoryImpl(
-                    featureFlagsClassic,
-                    sceneContainerFlags,
-                    sceneContainerRepository,
-                )
+            underTest = createRepositoryImpl(true)
 
             sceneContainerRepository.setDesiredScene(SceneModel(key = SceneKey.Communal))
 
@@ -103,17 +101,49 @@
     @Test
     fun isCommunalShowing_sceneContainerEnabled_onLockscreenScene_false() =
         testScope.runTest {
-            sceneContainerFlags = FakeSceneContainerFlags(enabled = true)
-            underTest =
-                CommunalRepositoryImpl(
-                    featureFlagsClassic,
-                    sceneContainerFlags,
-                    sceneContainerRepository,
-                )
+            underTest = createRepositoryImpl(true)
 
             sceneContainerRepository.setDesiredScene(SceneModel(key = SceneKey.Lockscreen))
 
             val isCommunalHubShowing by collectLastValue(underTest.isCommunalHubShowing)
             assertThat(isCommunalHubShowing).isFalse()
         }
+
+    @Test
+    fun transitionState_idleByDefault() =
+        testScope.runTest {
+            val transitionState by collectLastValue(underTest.transitionState)
+            assertThat(transitionState)
+                .isEqualTo(ObservableCommunalTransitionState.Idle(CommunalSceneKey.DEFAULT))
+        }
+
+    @Test
+    fun transitionState_setTransitionState_returnsNewValue() =
+        testScope.runTest {
+            val expectedSceneKey = CommunalSceneKey.Communal
+            underTest.setTransitionState(
+                flowOf(ObservableCommunalTransitionState.Idle(expectedSceneKey))
+            )
+
+            val transitionState by collectLastValue(underTest.transitionState)
+            assertThat(transitionState)
+                .isEqualTo(ObservableCommunalTransitionState.Idle(expectedSceneKey))
+        }
+
+    @Test
+    fun transitionState_setNullTransitionState_returnsDefaultValue() =
+        testScope.runTest {
+            // Set a value for the transition state flow.
+            underTest.setTransitionState(
+                flowOf(ObservableCommunalTransitionState.Idle(CommunalSceneKey.Communal))
+            )
+
+            // Set the transition state flow back to null.
+            underTest.setTransitionState(null)
+
+            // Flow returns default scene key.
+            val transitionState by collectLastValue(underTest.transitionState)
+            assertThat(transitionState)
+                .isEqualTo(ObservableCommunalTransitionState.Idle(CommunalSceneKey.DEFAULT))
+        }
 }
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 16cfa23..1f8e29a 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
@@ -161,7 +161,7 @@
             whenever(target1.remoteViews).thenReturn(mock(RemoteViews::class.java))
 
             val targets = listOf(target1, target2, target3)
-            smartspaceRepository.setLockscreenSmartspaceTargets(targets)
+            smartspaceRepository.setCommunalSmartspaceTargets(targets)
 
             val smartspaceContent by collectLastValue(underTest.smartspaceContent)
             assertThat(smartspaceContent?.size).isEqualTo(1)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt
index 8896e6e..314dfdf 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt
@@ -116,7 +116,7 @@
             whenever(target.smartspaceTargetId).thenReturn("target")
             whenever(target.featureType).thenReturn(SmartspaceTarget.FEATURE_TIMER)
             whenever(target.remoteViews).thenReturn(Mockito.mock(RemoteViews::class.java))
-            smartspaceRepository.setLockscreenSmartspaceTargets(listOf(target))
+            smartspaceRepository.setCommunalSmartspaceTargets(listOf(target))
 
             // Media playing.
             mediaRepository.mediaPlaying.value = true
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt
index 7fbcae0..8a71168 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt
@@ -135,7 +135,7 @@
             whenever(target.smartspaceTargetId).thenReturn("target")
             whenever(target.featureType).thenReturn(SmartspaceTarget.FEATURE_TIMER)
             whenever(target.remoteViews).thenReturn(Mockito.mock(RemoteViews::class.java))
-            smartspaceRepository.setLockscreenSmartspaceTargets(listOf(target))
+            smartspaceRepository.setCommunalSmartspaceTargets(listOf(target))
 
             // Media playing.
             mediaRepository.mediaPlaying.value = true
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepositoryTest.kt
index 97ac8c6..d3049d9 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepositoryTest.kt
@@ -6,6 +6,7 @@
 import com.android.internal.widget.LockPatternUtils
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.scene.SceneTestUtils
 import com.android.systemui.statusbar.phone.KeyguardBypassController
 import com.android.systemui.statusbar.policy.KeyguardStateController
@@ -38,6 +39,7 @@
     private val testUtils = SceneTestUtils(this)
     private val testScope = testUtils.testScope
     private val userRepository = FakeUserRepository()
+    private val keyguardRepository = FakeKeyguardRepository()
 
     private lateinit var underTest: DeviceEntryRepository
 
@@ -55,6 +57,7 @@
                 lockPatternUtils = lockPatternUtils,
                 keyguardBypassController = keyguardBypassController,
                 keyguardStateController = keyguardStateController,
+                keyguardRepository = keyguardRepository,
             )
         testScope.runCurrent()
     }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
index 45aca17..d6d5b23 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
@@ -827,25 +827,6 @@
         }
 
     @Test
-    fun isAuthenticatedIsResetToFalseWhenKeyguardIsGoingAway() =
-        testScope.runTest {
-            initCollectors()
-            allPreconditionsToRunFaceAuthAreTrue()
-
-            triggerFaceAuth(false)
-
-            authenticationCallback.value.onAuthenticationSucceeded(
-                mock(FaceManager.AuthenticationResult::class.java)
-            )
-
-            assertThat(authenticated()).isTrue()
-
-            keyguardRepository.setKeyguardGoingAway(true)
-
-            assertThat(authenticated()).isFalse()
-        }
-
-    @Test
     fun isAuthenticatedIsResetToFalseWhenDeviceStartsGoingToSleep() =
         testScope.runTest {
             initCollectors()
@@ -906,6 +887,25 @@
         }
 
     @Test
+    fun isAuthenticatedIsResetToFalseWhenKeyguardDoneAnimationsFinished() =
+        testScope.runTest {
+            initCollectors()
+            allPreconditionsToRunFaceAuthAreTrue()
+
+            triggerFaceAuth(false)
+
+            authenticationCallback.value.onAuthenticationSucceeded(
+                mock(FaceManager.AuthenticationResult::class.java)
+            )
+
+            assertThat(authenticated()).isTrue()
+
+            keyguardRepository.keyguardDoneAnimationsFinished()
+
+            assertThat(authenticated()).isFalse()
+        }
+
+    @Test
     fun detectDoesNotRunWhenFaceIsNotUsuallyAllowed() =
         testScope.runTest {
             testGatingCheckForDetect {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt
index 2b7221e..6b7d263 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt
@@ -304,4 +304,34 @@
             )
             assertThat(authenticationStatus).isNull()
         }
+
+    @Test
+    fun onBiometricRunningStateChanged_shouldUpdateIndicatorVisibility() =
+        testScope.runTest {
+            val shouldUpdateIndicatorVisibility by
+                collectLastValue(underTest.shouldUpdateIndicatorVisibility)
+            runCurrent()
+
+            verify(keyguardUpdateMonitor).registerCallback(updateMonitorCallback.capture())
+            assertThat(shouldUpdateIndicatorVisibility).isFalse()
+
+            invokeOnCallback {
+                it.onBiometricRunningStateChanged(false, BiometricSourceType.FINGERPRINT)
+            }
+            assertThat(shouldUpdateIndicatorVisibility).isTrue()
+        }
+
+    @Test
+    fun onStrongAuthStateChanged_shouldUpdateIndicatorVisibility() =
+        testScope.runTest {
+            val shouldUpdateIndicatorVisibility by
+                collectLastValue(underTest.shouldUpdateIndicatorVisibility)
+            runCurrent()
+
+            verify(keyguardUpdateMonitor).registerCallback(updateMonitorCallback.capture())
+            assertThat(shouldUpdateIndicatorVisibility).isFalse()
+
+            invokeOnCallback { it.onStrongAuthStateChanged(0) }
+            assertThat(shouldUpdateIndicatorVisibility).isTrue()
+        }
 }
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 bc4bae0..34f703b 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
@@ -49,8 +49,10 @@
 import com.android.systemui.res.R
 import com.android.systemui.settings.UserFileManager
 import com.android.systemui.settings.UserTracker
+import com.android.systemui.shade.domain.interactor.shadeInteractor
 import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
 import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.testKosmos
 import com.android.systemui.util.FakeSharedPreferences
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
@@ -93,6 +95,8 @@
     private lateinit var dockManager: DockManagerFake
     private lateinit var biometricSettingsRepository: FakeBiometricSettingsRepository
 
+    private val kosmos = testKosmos()
+
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
@@ -179,6 +183,7 @@
         underTest =
             KeyguardQuickAffordanceInteractor(
                 keyguardInteractor = withDeps.keyguardInteractor,
+                shadeInteractor = kosmos.shadeInteractor,
                 lockPatternUtils = lockPatternUtils,
                 keyguardStateController = keyguardStateController,
                 userTracker = userTracker,
@@ -339,6 +344,31 @@
         }
 
     @Test
+    fun quickAffordanceAlwaysVisible_notVisible_restrictedByPolicyManager() =
+        testScope.runTest {
+            whenever(devicePolicyManager.getKeyguardDisabledFeatures(null, userTracker.userId))
+                .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL)
+
+            repository.setKeyguardShowing(false)
+            repository.setIsDozing(true)
+            homeControls.setState(
+                KeyguardQuickAffordanceConfig.LockScreenState.Visible(
+                    icon = ICON,
+                    activationState = ActivationState.Active,
+                )
+            )
+
+            val collectedValue by
+                collectLastValue(
+                    underTest.quickAffordanceAlwaysVisible(
+                        KeyguardQuickAffordancePosition.BOTTOM_START
+                    )
+                )
+
+            assertThat(collectedValue).isInstanceOf(KeyguardQuickAffordanceModel.Hidden::class.java)
+        }
+
+    @Test
     fun quickAffordanceAlwaysVisible_evenWhenLockScreenNotShowingAndDozing() =
         testScope.runTest {
             repository.setKeyguardShowing(false)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/preview/KeyguardRemotePreviewManagerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/preview/KeyguardRemotePreviewManagerTest.kt
new file mode 100644
index 0000000..e850456
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/preview/KeyguardRemotePreviewManagerTest.kt
@@ -0,0 +1,40 @@
+package com.android.systemui.keyguard.ui.preview
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.mockito.mock
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class KeyguardRemotePreviewManagerTest : SysuiTestCase() {
+
+    private val testDispatcher = StandardTestDispatcher()
+    private val testScope = TestScope(testDispatcher)
+
+    @Test
+    fun onDestroy_clearsReferencesToRenderer() =
+        testScope.runTest {
+            val renderer = mock<KeyguardPreviewRenderer>()
+            val onDestroy: (PreviewLifecycleObserver) -> Unit = {}
+
+            val observer = PreviewLifecycleObserver(this, testDispatcher, renderer, onDestroy)
+
+            // Precondition check.
+            assertThat(observer.renderer).isNotNull()
+            assertThat(observer.onDestroy).isNotNull()
+
+            observer.onDestroy()
+
+            // The verification checks renderer/requestDestruction lambda because they-re
+            // non-singletons which can't leak KeyguardPreviewRenderer.
+            assertThat(observer.renderer).isNull()
+            assertThat(observer.onDestroy).isNull()
+        }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt
index 9226c0d..a346e8b 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt
@@ -24,7 +24,7 @@
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.coroutines.collectValues
 import com.android.systemui.flags.Flags
-import com.android.systemui.flags.featureFlagsClassic
+import com.android.systemui.flags.fakeFeatureFlagsClassic
 import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
 import com.android.systemui.keyguard.shared.model.KeyguardState
@@ -48,7 +48,7 @@
 
     private val kosmos =
         testKosmos().apply {
-            featureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) }
+            fakeFeatureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) }
         }
     private val testScope = kosmos.testScope
     private val repository = kosmos.fakeKeyguardTransitionRepository
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt
index bcad72b..274bde1 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt
@@ -25,7 +25,7 @@
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.coroutines.collectValues
 import com.android.systemui.flags.Flags
-import com.android.systemui.flags.featureFlagsClassic
+import com.android.systemui.flags.fakeFeatureFlagsClassic
 import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
 import com.android.systemui.keyguard.shared.model.KeyguardState
@@ -49,7 +49,7 @@
 class LockscreenToOccludedTransitionViewModelTest : SysuiTestCase() {
     private val kosmos =
         testKosmos().apply {
-            featureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) }
+            fakeFeatureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) }
         }
     private val testScope = kosmos.testScope
     private val repository = kosmos.fakeKeyguardTransitionRepository
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt
index 78d87a6..f027bc8 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt
@@ -22,7 +22,7 @@
 import com.android.systemui.bouncer.domain.interactor.primaryBouncerInteractor
 import com.android.systemui.coroutines.collectValues
 import com.android.systemui.flags.Flags
-import com.android.systemui.flags.featureFlagsClassic
+import com.android.systemui.flags.fakeFeatureFlagsClassic
 import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.TransitionState
@@ -43,7 +43,7 @@
 class PrimaryBouncerToGoneTransitionViewModelTest : SysuiTestCase() {
     val kosmos =
         testKosmos().apply {
-            featureFlagsClassic.apply {
+            fakeFeatureFlagsClassic.apply {
                 set(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT, false)
                 set(Flags.FULL_SCREEN_USER_SWITCHER, false)
             }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/OWNERS b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/OWNERS
new file mode 100644
index 0000000..cd04e82
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/OWNERS
@@ -0,0 +1,3 @@
+set noparent
+
+include /packages/SystemUI/src/com/android/systemui/qs/OWNERS
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/restoreprocessors/WorkTileRestoreProcessorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/restoreprocessors/WorkTileRestoreProcessorTest.kt
new file mode 100644
index 0000000..30d1822
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/restoreprocessors/WorkTileRestoreProcessorTest.kt
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.pipeline.data.restoreprocessors
+
+import android.os.UserHandle
+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.qs.pipeline.data.model.RestoreData
+import com.android.systemui.qs.pipeline.shared.TileSpec
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@OptIn(ExperimentalCoroutinesApi::class)
+class WorkTileRestoreProcessorTest : SysuiTestCase() {
+
+    private val underTest = WorkTileRestoreProcessor()
+    @Test
+    fun restoreWithWorkTile_removeTracking() = runTest {
+        val removeTracking by collectLastValue(underTest.removeTrackingForUser(UserHandle.of(USER)))
+        runCurrent()
+
+        val restoreData =
+            RestoreData(
+                restoredTiles = listOf(TILE_SPEC),
+                restoredAutoAddedTiles = setOf(TILE_SPEC),
+                USER,
+            )
+
+        underTest.postProcessRestore(restoreData)
+
+        assertThat(removeTracking).isEqualTo(Unit)
+    }
+
+    @Test
+    fun restoreWithWorkTile_otherUser_noRemoveTracking() = runTest {
+        val removeTracking by
+            collectLastValue(underTest.removeTrackingForUser(UserHandle.of(USER + 1)))
+        runCurrent()
+
+        val restoreData =
+            RestoreData(
+                restoredTiles = listOf(TILE_SPEC),
+                restoredAutoAddedTiles = setOf(TILE_SPEC),
+                USER,
+            )
+
+        underTest.postProcessRestore(restoreData)
+
+        assertThat(removeTracking).isNull()
+    }
+
+    @Test
+    fun restoreWithoutWorkTile_noSignal() = runTest {
+        val removeTracking by collectLastValue(underTest.removeTrackingForUser(UserHandle.of(USER)))
+        runCurrent()
+
+        val restoreData =
+            RestoreData(
+                restoredTiles = emptyList(),
+                restoredAutoAddedTiles = emptySet(),
+                USER,
+            )
+
+        underTest.postProcessRestore(restoreData)
+
+        assertThat(removeTracking).isNull()
+    }
+
+    companion object {
+        private const val USER = 10
+        private val TILE_SPEC = TileSpec.Companion.create("work")
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/WorkTileAutoAddableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/WorkTileAutoAddableTest.kt
index adccc84..c7e7845 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/WorkTileAutoAddableTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/WorkTileAutoAddableTest.kt
@@ -25,6 +25,11 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.coroutines.collectValues
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.qs.pipeline.data.model.RestoreData
+import com.android.systemui.qs.pipeline.data.model.RestoreProcessor
+import com.android.systemui.qs.pipeline.data.model.workTileRestoreProcessor
 import com.android.systemui.qs.pipeline.domain.model.AutoAddSignal
 import com.android.systemui.qs.pipeline.domain.model.AutoAddTracking
 import com.android.systemui.qs.pipeline.shared.TileSpec
@@ -32,25 +37,28 @@
 import com.android.systemui.settings.FakeUserTracker
 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
-import org.mockito.MockitoAnnotations
 
 @OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class WorkTileAutoAddableTest : SysuiTestCase() {
 
+    private val kosmos = Kosmos()
+
+    private val restoreProcessor: RestoreProcessor
+        get() = kosmos.workTileRestoreProcessor
+
     private lateinit var userTracker: FakeUserTracker
 
     private lateinit var underTest: WorkTileAutoAddable
 
     @Before
     fun setup() {
-        MockitoAnnotations.initMocks(this)
-
         userTracker =
             FakeUserTracker(
                 _userId = USER_INFO_0.id,
@@ -58,7 +66,7 @@
                 _userProfiles = listOf(USER_INFO_0)
             )
 
-        underTest = WorkTileAutoAddable(userTracker)
+        underTest = WorkTileAutoAddable(userTracker, kosmos.workTileRestoreProcessor)
     }
 
     @Test
@@ -114,10 +122,80 @@
         assertThat(underTest.autoAddTracking).isEqualTo(AutoAddTracking.Always)
     }
 
+    @Test
+    fun restoreDataWithWorkTile_noCurrentManagedProfile_triggersRemove() = runTest {
+        val userId = 0
+        val signal by collectLastValue(underTest.autoAddSignal(userId))
+        runCurrent()
+
+        val restoreData = createRestoreWithWorkTile(userId)
+
+        restoreProcessor.postProcessRestore(restoreData)
+
+        assertThat(signal!!).isEqualTo(AutoAddSignal.RemoveTracking(SPEC))
+    }
+
+    @Test
+    fun restoreDataWithWorkTile_currentlyManagedProfile_doesntTriggerRemove() = runTest {
+        userTracker.set(listOf(USER_INFO_0, USER_INFO_WORK), selectedUserIndex = 0)
+        val userId = 0
+        val signals by collectValues(underTest.autoAddSignal(userId))
+        runCurrent()
+
+        val restoreData = createRestoreWithWorkTile(userId)
+
+        restoreProcessor.postProcessRestore(restoreData)
+
+        assertThat(signals).doesNotContain(AutoAddSignal.RemoveTracking(SPEC))
+    }
+
+    @Test
+    fun restoreDataWithoutWorkTile_noManagedProfile_doesntTriggerRemove() = runTest {
+        val userId = 0
+        val signals by collectValues(underTest.autoAddSignal(userId))
+        runCurrent()
+
+        val restoreData = createRestoreWithoutWorkTile(userId)
+
+        restoreProcessor.postProcessRestore(restoreData)
+
+        assertThat(signals).doesNotContain(AutoAddSignal.RemoveTracking(SPEC))
+    }
+
+    @Test
+    fun restoreDataWithoutWorkTile_managedProfile_doesntTriggerRemove() = runTest {
+        userTracker.set(listOf(USER_INFO_0, USER_INFO_WORK), selectedUserIndex = 0)
+        val userId = 0
+        val signals by collectValues(underTest.autoAddSignal(userId))
+        runCurrent()
+
+        val restoreData = createRestoreWithoutWorkTile(userId)
+
+        restoreProcessor.postProcessRestore(restoreData)
+
+        assertThat(signals).doesNotContain(AutoAddSignal.RemoveTracking(SPEC))
+    }
+
     companion object {
         private val SPEC = TileSpec.create(WorkModeTile.TILE_SPEC)
         private val USER_INFO_0 = UserInfo(0, "", FLAG_PRIMARY or FLAG_FULL)
         private val USER_INFO_1 = UserInfo(1, "", FLAG_FULL)
         private val USER_INFO_WORK = UserInfo(10, "", FLAG_PROFILE or FLAG_MANAGED_PROFILE)
+
+        private fun createRestoreWithWorkTile(userId: Int): RestoreData {
+            return RestoreData(
+                listOf(TileSpec.create("a"), SPEC, TileSpec.create("b")),
+                setOf(SPEC),
+                userId,
+            )
+        }
+
+        private fun createRestoreWithoutWorkTile(userId: Int): RestoreData {
+            return RestoreData(
+                listOf(TileSpec.create("a"), TileSpec.create("b")),
+                emptySet(),
+                userId,
+            )
+        }
     }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/AutoAddInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/AutoAddInteractorTest.kt
index 41a7ec0..54b03a9 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/AutoAddInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/AutoAddInteractorTest.kt
@@ -183,6 +183,22 @@
             assertThat(autoAddedTiles).contains(SPEC)
         }
 
+    @Test
+    fun autoAddable_removeTrackingSignal_notRemovedButUnmarked() =
+        testScope.runTest {
+            autoAddRepository.markTileAdded(USER, SPEC)
+            val autoAddedTiles by collectLastValue(autoAddRepository.autoAddedTiles(USER))
+            val fakeAutoAddable = FakeAutoAddable(SPEC, AutoAddTracking.Always)
+
+            underTest = createInteractor(setOf(fakeAutoAddable))
+
+            fakeAutoAddable.sendRemoveTrackingSignal(USER)
+            runCurrent()
+
+            verify(currentTilesInteractor, never()).removeTiles(any())
+            assertThat(autoAddedTiles).doesNotContain(SPEC)
+        }
+
     private fun createInteractor(autoAddables: Set<AutoAddable>): AutoAddInteractor {
         return AutoAddInteractor(
                 autoAddables,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorImplTest.kt
index 8c896a6..1e2784a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorImplTest.kt
@@ -25,11 +25,10 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.Flags.FLAG_QS_NEW_PIPELINE
+import com.android.systemui.Flags.FLAG_QS_NEW_TILES
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.dump.nano.SystemUIProtoDump
-import com.android.systemui.flags.FakeFeatureFlags
-import com.android.systemui.flags.Flags
 import com.android.systemui.plugins.qs.QSTile
 import com.android.systemui.plugins.qs.QSTile.BooleanState
 import com.android.systemui.qs.FakeQSFactory
@@ -81,8 +80,7 @@
     private val tileFactory = FakeQSFactory(::tileCreator)
     private val customTileAddedRepository: CustomTileAddedRepository =
         FakeCustomTileAddedRepository()
-    private val featureFlags = FakeFeatureFlags()
-    private val pipelineFlags = QSPipelineFlagsRepository(featureFlags)
+    private val pipelineFlags = QSPipelineFlagsRepository()
     private val tileLifecycleManagerFactory = TLMFactory()
 
     @Mock private lateinit var customTileStatePersister: CustomTileStatePersister
@@ -100,14 +98,12 @@
 
     private lateinit var underTest: CurrentTilesInteractorImpl
 
-    @OptIn(ExperimentalCoroutinesApi::class)
     @Before
     fun setup() {
         MockitoAnnotations.initMocks(this)
 
         mSetFlagsRule.enableFlags(FLAG_QS_NEW_PIPELINE)
-        // TODO(b/299909337): Add test checking the new factory is used when the flag is on
-        featureFlags.set(Flags.QS_PIPELINE_NEW_TILES, true)
+        mSetFlagsRule.enableFlags(FLAG_QS_NEW_TILES)
 
         userRepository.setUserInfos(listOf(USER_INFO_0, USER_INFO_1))
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/RestoreReconciliationInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/RestoreReconciliationInteractorTest.kt
index f73cab8..b2a9783 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/RestoreReconciliationInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/RestoreReconciliationInteractorTest.kt
@@ -5,10 +5,15 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.qs.pipeline.data.model.RestoreData
+import com.android.systemui.qs.pipeline.data.model.RestoreProcessor
 import com.android.systemui.qs.pipeline.data.repository.FakeAutoAddRepository
 import com.android.systemui.qs.pipeline.data.repository.FakeQSSettingsRestoredRepository
 import com.android.systemui.qs.pipeline.data.repository.FakeTileSpecRepository
 import com.android.systemui.qs.pipeline.data.repository.TilesSettingConverter
+import com.android.systemui.qs.pipeline.domain.interactor.RestoreReconciliationInteractorTest.TestableRestoreProcessor.Companion.POSTPROCESS
+import com.android.systemui.qs.pipeline.domain.interactor.RestoreReconciliationInteractorTest.TestableRestoreProcessor.Companion.PREPROCESS
+import com.android.systemui.qs.pipeline.shared.logging.QSPipelineLogger
+import com.android.systemui.util.mockito.mock
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.test.StandardTestDispatcher
 import kotlinx.coroutines.test.TestScope
@@ -17,7 +22,7 @@
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
-import org.mockito.MockitoAnnotations
+import org.mockito.Mockito.inOrder
 
 @RunWith(AndroidJUnit4::class)
 @SmallTest
@@ -28,6 +33,9 @@
 
     private val qsSettingsRestoredRepository = FakeQSSettingsRestoredRepository()
 
+    private val restoreProcessor: TestableRestoreProcessor = TestableRestoreProcessor()
+    private val qsLogger: QSPipelineLogger = mock()
+
     private lateinit var underTest: RestoreReconciliationInteractor
 
     private val testDispatcher = StandardTestDispatcher()
@@ -35,13 +43,13 @@
 
     @Before
     fun setUp() {
-        MockitoAnnotations.initMocks(this)
-
         underTest =
             RestoreReconciliationInteractor(
                 tileSpecRepository,
                 autoAddRepository,
                 qsSettingsRestoredRepository,
+                setOf(restoreProcessor),
+                qsLogger,
                 testScope.backgroundScope,
                 testDispatcher
             )
@@ -85,6 +93,44 @@
             assertThat(autoAdd).isEqualTo(expectedAutoAdd.toTilesSet())
         }
 
+    @Test
+    fun restoreProcessorsCalled() =
+        testScope.runTest {
+            val user = 10
+
+            val restoredSpecs = "a,c,d,f"
+            val restoredAutoAdded = "d,e"
+
+            val restoreData =
+                RestoreData(
+                    restoredSpecs.toTilesList(),
+                    restoredAutoAdded.toTilesSet(),
+                    user,
+                )
+
+            qsSettingsRestoredRepository.onDataRestored(restoreData)
+            runCurrent()
+
+            assertThat(restoreProcessor.calls).containsExactly(PREPROCESS, POSTPROCESS).inOrder()
+        }
+
+    private class TestableRestoreProcessor : RestoreProcessor {
+        val calls = mutableListOf<Any>()
+
+        override suspend fun preProcessRestore(restoreData: RestoreData) {
+            calls.add(PREPROCESS)
+        }
+
+        override suspend fun postProcessRestore(restoreData: RestoreData) {
+            calls.add(POSTPROCESS)
+        }
+
+        companion object {
+            val PREPROCESS = Any()
+            val POSTPROCESS = Any()
+        }
+    }
+
     companion object {
         private fun String.toTilesList() = TilesSettingConverter.toTilesList(this)
         private fun String.toTilesSet() = TilesSettingConverter.toTilesSet(this)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/WorkProfileAutoAddedAfterRestoreTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/WorkProfileAutoAddedAfterRestoreTest.kt
new file mode 100644
index 0000000..96d5774
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/WorkProfileAutoAddedAfterRestoreTest.kt
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.pipeline.domain.interactor
+
+import android.content.pm.UserInfo
+import android.os.UserManager
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import com.android.systemui.Flags.FLAG_QS_NEW_PIPELINE
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.plugins.qs.QSTile
+import com.android.systemui.qs.FakeQSFactory
+import com.android.systemui.qs.pipeline.data.model.RestoreData
+import com.android.systemui.qs.pipeline.data.repository.fakeRestoreRepository
+import com.android.systemui.qs.pipeline.data.repository.fakeTileSpecRepository
+import com.android.systemui.qs.pipeline.shared.TileSpec
+import com.android.systemui.qs.qsTileFactory
+import com.android.systemui.settings.fakeUserTracker
+import com.android.systemui.settings.userTracker
+import com.google.common.truth.Truth.assertThat
+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
+
+/**
+ * This integration test is for testing the solution to b/314781280. In particular, there are two
+ * issues we want to verify after a restore of a device with a work profile and a work mode tile:
+ * * When the work profile is re-enabled in the target device, it is auto-added.
+ * * The tile is auto-added in the same position that it was in the restored device.
+ */
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+@OptIn(ExperimentalCoroutinesApi::class)
+class WorkProfileAutoAddedAfterRestoreTest : SysuiTestCase() {
+
+    private val kosmos = Kosmos().apply { fakeUserTracker.set(listOf(USER_0_INFO), 0) }
+    // Getter here so it can change when there is a managed profile.
+    private val workTileAvailable: Boolean
+        get() = hasManagedProfile()
+    private val currentUser: Int
+        get() = kosmos.userTracker.userId
+
+    private val testScope: TestScope
+        get() = kosmos.testScope
+
+    @Before
+    fun setUp() {
+        mSetFlagsRule.enableFlags(FLAG_QS_NEW_PIPELINE)
+
+        kosmos.qsTileFactory = FakeQSFactory(::tileCreator)
+        kosmos.restoreReconciliationInteractor.start()
+        kosmos.autoAddInteractor.init(kosmos.currentTilesInteractor)
+    }
+
+    @Test
+    fun workTileRestoredAndPreviouslyAutoAdded_notAvailable_willBeAutoaddedInCorrectPosition() =
+        testScope.runTest {
+            val tiles by collectLastValue(kosmos.currentTilesInteractor.currentTiles)
+
+            // Set up
+            val currentTiles = listOf("a".toTileSpec())
+            kosmos.fakeTileSpecRepository.setTiles(currentUser, currentTiles)
+
+            val restoredTiles =
+                listOf(WORK_TILE_SPEC) + listOf("b", "c", "d").map { it.toTileSpec() }
+            val restoredAutoAdded = setOf(WORK_TILE_SPEC)
+
+            val restoreData = RestoreData(restoredTiles, restoredAutoAdded, currentUser)
+
+            // WHEN we restore tiles that auto-added the WORK tile and it's not available (there
+            // are no managed profiles)
+            kosmos.fakeRestoreRepository.onDataRestored(restoreData)
+
+            // THEN the work tile is not part of the current tiles
+            assertThat(tiles!!).hasSize(3)
+            assertThat(tiles!!.map { it.spec }).doesNotContain(WORK_TILE_SPEC)
+
+            // WHEN we add a work profile
+            createManagedProfileAndAdd()
+
+            // THEN the work profile is added in the correct place
+            assertThat(tiles!!.first().spec).isEqualTo(WORK_TILE_SPEC)
+        }
+
+    @Test
+    fun workTileNotRestoredAndPreviouslyAutoAdded_wontBeAutoAddedWhenWorkProfileIsAdded() =
+        testScope.runTest {
+            val tiles by collectLastValue(kosmos.currentTilesInteractor.currentTiles)
+
+            // Set up
+            val currentTiles = listOf("a".toTileSpec())
+            kosmos.fakeTileSpecRepository.setTiles(currentUser, currentTiles)
+            runCurrent()
+
+            val restoredTiles = listOf("b", "c", "d").map { it.toTileSpec() }
+            val restoredAutoAdded = setOf(WORK_TILE_SPEC)
+
+            val restoreData = RestoreData(restoredTiles, restoredAutoAdded, currentUser)
+
+            // WHEN we restore tiles that auto-added the WORK tile
+            kosmos.fakeRestoreRepository.onDataRestored(restoreData)
+
+            // THEN the work tile is not part of the current tiles
+            assertThat(tiles!!).hasSize(3)
+            assertThat(tiles!!.map { it.spec }).doesNotContain(WORK_TILE_SPEC)
+
+            // WHEN we add a work profile
+            createManagedProfileAndAdd()
+
+            // THEN the work profile is not added because the user had manually removed it in the
+            // past
+            assertThat(tiles!!.map { it.spec }).doesNotContain(WORK_TILE_SPEC)
+        }
+
+    private fun tileCreator(spec: String): QSTile {
+        return if (spec == WORK_TILE_SPEC.spec) {
+            FakeQSTile(currentUser, workTileAvailable)
+        } else {
+            FakeQSTile(currentUser)
+        }
+    }
+
+    private fun hasManagedProfile(): Boolean {
+        return kosmos.userTracker.userProfiles.any { it.isManagedProfile }
+    }
+
+    private fun TestScope.createManagedProfileAndAdd() {
+        kosmos.fakeUserTracker.set(
+            listOf(USER_0_INFO, MANAGED_USER_INFO),
+            0,
+        )
+        runCurrent()
+    }
+
+    private companion object {
+        val WORK_TILE_SPEC = "work".toTileSpec()
+        val USER_0_INFO =
+            UserInfo(
+                0,
+                "zero",
+                "",
+                UserInfo.FLAG_ADMIN or UserInfo.FLAG_FULL,
+            )
+        val MANAGED_USER_INFO =
+            UserInfo(
+                10,
+                "ten-managed",
+                "",
+                0,
+                UserManager.USER_TYPE_PROFILE_MANAGED,
+            )
+
+        fun String.toTileSpec() = TileSpec.create(this)
+    }
+}
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 2b744ac..00405d0 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
@@ -17,6 +17,7 @@
 package com.android.systemui.qs.tiles.impl.alarm.domain
 
 import android.app.AlarmManager
+import android.graphics.drawable.TestStubDrawable
 import android.widget.Switch
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
@@ -40,7 +41,14 @@
     private val kosmos = Kosmos()
     private val alarmTileConfig = kosmos.qsAlarmTileConfig
     // Using lazy (versus =) to make sure we override the right context -- see b/311612168
-    private val mapper by lazy { AlarmTileMapper(context.orCreateTestableResources.resources) }
+    private val mapper by lazy {
+        AlarmTileMapper(
+            context.orCreateTestableResources
+                .apply { addOverride(R.drawable.ic_alarm, TestStubDrawable()) }
+                .resources,
+            context.theme
+        )
+    }
 
     @Test
     fun notAlarmSet() {
@@ -100,7 +108,7 @@
     ): QSTileState {
         val label = context.getString(R.string.status_bar_alarm)
         return QSTileState(
-            { Icon.Resource(R.drawable.ic_alarm, null) },
+            { Icon.Loaded(context.getDrawable(R.drawable.ic_alarm)!!, null) },
             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
new file mode 100644
index 0000000..8ee6d20
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/ColorCorrectionTileMapperTest.kt
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.colorcorrection.domain
+
+import android.graphics.drawable.TestStubDrawable
+import android.widget.Switch
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.qs.tiles.impl.colorcorrection.domain.model.ColorCorrectionTileModel
+import com.android.systemui.qs.tiles.impl.colorcorrection.qsColorCorrectionTileConfig
+import com.android.systemui.qs.tiles.impl.custom.QSTileStateSubject
+import com.android.systemui.qs.tiles.viewmodel.QSTileState
+import com.android.systemui.res.R
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class ColorCorrectionTileMapperTest : SysuiTestCase() {
+    private val kosmos = Kosmos()
+    private val colorCorrectionTileConfig = kosmos.qsColorCorrectionTileConfig
+    private val subtitleArray =
+        context.resources.getStringArray(R.array.tile_states_color_correction)
+    // Using lazy (versus =) to make sure we override the right context -- see b/311612168
+    private val mapper by lazy {
+        ColorCorrectionTileMapper(
+            context.orCreateTestableResources
+                .apply { addOverride(R.drawable.ic_qs_color_correction, TestStubDrawable()) }
+                .resources,
+            context.theme
+        )
+    }
+
+    @Test
+    fun disabledModel() {
+        val inputModel = ColorCorrectionTileModel(false)
+
+        val outputState = mapper.map(colorCorrectionTileConfig, inputModel)
+
+        val expectedState =
+            createColorCorrectionTileState(QSTileState.ActivationState.INACTIVE, subtitleArray[1])
+        QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState)
+    }
+
+    @Test
+    fun enabledModel() {
+        val inputModel = ColorCorrectionTileModel(true)
+
+        val outputState = mapper.map(colorCorrectionTileConfig, inputModel)
+
+        val expectedState =
+            createColorCorrectionTileState(QSTileState.ActivationState.ACTIVE, subtitleArray[2])
+        QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState)
+    }
+
+    private fun createColorCorrectionTileState(
+        activationState: QSTileState.ActivationState,
+        secondaryLabel: String
+    ): 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) },
+            label,
+            activationState,
+            secondaryLabel,
+            setOf(QSTileState.UserAction.CLICK, QSTileState.UserAction.LONG_CLICK),
+            label,
+            null,
+            QSTileState.SideViewIcon.None,
+            QSTileState.EnabledState.ENABLED,
+            Switch::class.qualifiedName
+        )
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/interactor/ColorCorrectionTileDataInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/interactor/ColorCorrectionTileDataInteractorTest.kt
new file mode 100644
index 0000000..8c612ac
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/interactor/ColorCorrectionTileDataInteractorTest.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.colorcorrection.domain.interactor
+
+import android.os.UserHandle
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.accessibility.data.repository.FakeColorCorrectionRepository
+import com.android.systemui.coroutines.collectValues
+import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
+import com.android.systemui.qs.tiles.impl.colorcorrection.domain.model.ColorCorrectionTileModel
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.toCollection
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class ColorCorrectionTileDataInteractorTest : SysuiTestCase() {
+
+    private val colorCorrectionRepository = FakeColorCorrectionRepository()
+    private val underTest: ColorCorrectionTileDataInteractor =
+        ColorCorrectionTileDataInteractor(colorCorrectionRepository)
+
+    @Test
+    fun alwaysAvailable() = runTest {
+        val availability = underTest.availability(TEST_USER).toCollection(mutableListOf())
+
+        assertThat(availability).hasSize(1)
+        assertThat(availability.last()).isTrue()
+    }
+
+    @Test
+    fun dataMatchesTheRepository() = runTest {
+        val dataList: List<ColorCorrectionTileModel> by
+            collectValues(underTest.tileData(TEST_USER, flowOf(DataUpdateTrigger.InitialRequest)))
+        runCurrent()
+
+        colorCorrectionRepository.setIsEnabled(true, TEST_USER)
+        runCurrent()
+
+        colorCorrectionRepository.setIsEnabled(false, TEST_USER)
+        runCurrent()
+
+        assertThat(dataList).hasSize(3)
+        assertThat(dataList.map { it.isEnabled }).isEqualTo(listOf(false, true, false))
+    }
+
+    private companion object {
+        val TEST_USER = UserHandle.of(1)!!
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/interactor/ColorCorrectionTileUserActionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/interactor/ColorCorrectionTileUserActionInteractorTest.kt
new file mode 100644
index 0000000..3049cc0
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/interactor/ColorCorrectionTileUserActionInteractorTest.kt
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.colorcorrection.domain.interactor
+
+import android.os.UserHandle
+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.accessibility.data.repository.FakeColorCorrectionRepository
+import com.android.systemui.qs.tiles.base.actions.FakeQSTileIntentUserInputHandler
+import com.android.systemui.qs.tiles.base.actions.QSTileIntentUserInputHandlerSubject
+import com.android.systemui.qs.tiles.base.interactor.QSTileInputTestKtx
+import com.android.systemui.qs.tiles.impl.colorcorrection.domain.model.ColorCorrectionTileModel
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class ColorCorrectionTileUserActionInteractorTest : SysuiTestCase() {
+
+    private val testUser = UserHandle.CURRENT
+    private val repository = FakeColorCorrectionRepository()
+    private val inputHandler = FakeQSTileIntentUserInputHandler()
+
+    private val underTest =
+        ColorCorrectionUserActionInteractor(
+            repository,
+            inputHandler,
+        )
+
+    @Test
+    fun handleClickWhenEnabled() = runTest {
+        val wasEnabled = true
+        repository.setIsEnabled(wasEnabled, testUser)
+
+        underTest.handleInput(QSTileInputTestKtx.click(ColorCorrectionTileModel(wasEnabled)))
+
+        assertThat(repository.isEnabled(testUser).value).isEqualTo(!wasEnabled)
+    }
+
+    @Test
+    fun handleClickWhenDisabled() = runTest {
+        val wasEnabled = false
+        repository.setIsEnabled(wasEnabled, testUser)
+
+        underTest.handleInput(QSTileInputTestKtx.click(ColorCorrectionTileModel(wasEnabled)))
+
+        assertThat(repository.isEnabled(testUser).value).isEqualTo(!wasEnabled)
+    }
+
+    @Test
+    fun handleLongClickWhenDisabled() = runTest {
+        val enabled = false
+
+        underTest.handleInput(QSTileInputTestKtx.longClick(ColorCorrectionTileModel(enabled)))
+
+        QSTileIntentUserInputHandlerSubject.assertThat(inputHandler).handledOneIntentInput {
+            assertThat(it.intent.action).isEqualTo(Settings.ACTION_COLOR_CORRECTION_SETTINGS)
+        }
+    }
+
+    @Test
+    fun handleLongClickWhenEnabled() = runTest {
+        val enabled = true
+
+        underTest.handleInput(QSTileInputTestKtx.longClick(ColorCorrectionTileModel(enabled)))
+
+        QSTileIntentUserInputHandlerSubject.assertThat(inputHandler).handledOneIntentInput {
+            assertThat(it.intent.action).isEqualTo(Settings.ACTION_COLOR_CORRECTION_SETTINGS)
+        }
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/CustomTilePackageUpdatesRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/CustomTilePackageUpdatesRepositoryTest.kt
index 4a22113..2eeb75e 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/CustomTilePackageUpdatesRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/CustomTilePackageUpdatesRepositoryTest.kt
@@ -16,23 +16,27 @@
 
 package com.android.systemui.qs.tiles.impl.custom
 
+import android.annotation.SuppressLint
+import android.content.BroadcastReceiver
 import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
 import android.os.UserHandle
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.qs.external.TileLifecycleManager
-import com.android.systemui.qs.external.TileServiceManager
+import com.android.systemui.coroutines.collectValues
 import com.android.systemui.qs.pipeline.shared.TileSpec
 import com.android.systemui.qs.tiles.impl.custom.data.repository.CustomTilePackageUpdatesRepository
 import com.android.systemui.qs.tiles.impl.custom.data.repository.CustomTilePackageUpdatesRepositoryImpl
-import com.android.systemui.qs.tiles.impl.custom.data.repository.FakeCustomTileDefaultsRepository
-import com.android.systemui.qs.tiles.impl.custom.data.repository.FakeCustomTileDefaultsRepository.DefaultsRequest
+import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.capture
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.nullable
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.launchIn
-import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.test.StandardTestDispatcher
 import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.runCurrent
@@ -49,14 +53,12 @@
 @OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
 @RunWith(AndroidJUnit4::class)
+@SuppressLint("UnspecifiedRegisterReceiverFlag") // Not needed in the test
 class CustomTilePackageUpdatesRepositoryTest : SysuiTestCase() {
 
-    @Mock private lateinit var tileServiceManager: TileServiceManager
+    @Mock private lateinit var mockedContext: Context
+    @Captor private lateinit var listenerCaptor: ArgumentCaptor<BroadcastReceiver>
 
-    @Captor
-    private lateinit var listenerCaptor: ArgumentCaptor<TileLifecycleManager.TileChangeListener>
-
-    private val defaultsRepository = FakeCustomTileDefaultsRepository()
     private val testDispatcher = StandardTestDispatcher()
     private val testScope = TestScope(testDispatcher)
 
@@ -69,37 +71,29 @@
         underTest =
             CustomTilePackageUpdatesRepositoryImpl(
                 TileSpec.create(COMPONENT_1),
-                USER,
-                tileServiceManager,
-                defaultsRepository,
+                mockedContext,
                 testScope.backgroundScope,
+                testDispatcher,
             )
     }
 
     @Test
-    fun packageChangesUpdatesDefaults() =
+    fun packageChangesEmittedForTilePassing() =
         testScope.runTest {
-            val events = mutableListOf<Unit>()
-            underTest.packageChanges.onEach { events.add(it) }.launchIn(backgroundScope)
+            val events by collectValues(underTest.getPackageChangesForUser(USER_1))
             runCurrent()
-            verify(tileServiceManager).setTileChangeListener(capture(listenerCaptor))
 
-            emitPackageChange()
+            emitPackageChange(COMPONENT_1)
             runCurrent()
 
             assertThat(events).hasSize(1)
-            assertThat(defaultsRepository.defaultsRequests).isNotEmpty()
-            assertThat(defaultsRepository.defaultsRequests.last())
-                .isEqualTo(DefaultsRequest(USER, COMPONENT_1, true))
         }
 
     @Test
-    fun packageChangesEmittedOnlyForTheTile() =
+    fun packageChangesEmittedForAnotherTileIgnored() =
         testScope.runTest {
-            val events = mutableListOf<Unit>()
-            underTest.packageChanges.onEach { events.add(it) }.launchIn(backgroundScope)
+            val events by collectValues(underTest.getPackageChangesForUser(USER_1))
             runCurrent()
-            verify(tileServiceManager).setTileChangeListener(capture(listenerCaptor))
 
             emitPackageChange(COMPONENT_2)
             runCurrent()
@@ -107,12 +101,60 @@
             assertThat(events).isEmpty()
         }
 
-    private fun emitPackageChange(componentName: ComponentName = COMPONENT_1) {
-        listenerCaptor.value.onTileChanged(componentName)
+    @Test
+    fun unsupportedActionDoesntEmmit() =
+        testScope.runTest {
+            val events by collectValues(underTest.getPackageChangesForUser(USER_1))
+            runCurrent()
+
+            verify(mockedContext)
+                .registerReceiverAsUser(
+                    capture(listenerCaptor),
+                    any(),
+                    any(),
+                    nullable(),
+                    nullable()
+                )
+            listenerCaptor.value.onReceive(mockedContext, Intent(Intent.ACTION_MAIN))
+            runCurrent()
+
+            assertThat(events).isEmpty()
+        }
+
+    @Test
+    fun cachesCallsPerUser() =
+        testScope.runTest {
+            underTest.getPackageChangesForUser(USER_1).launchIn(backgroundScope)
+            underTest.getPackageChangesForUser(USER_1).launchIn(backgroundScope)
+            underTest.getPackageChangesForUser(USER_2).launchIn(backgroundScope)
+            underTest.getPackageChangesForUser(USER_2).launchIn(backgroundScope)
+            runCurrent()
+
+            // Register receiver once per each user
+            verify(mockedContext)
+                .registerReceiverAsUser(any(), eq(USER_1), any(), nullable(), nullable())
+            verify(mockedContext)
+                .registerReceiverAsUser(any(), eq(USER_2), any(), nullable(), nullable())
+        }
+
+    private fun emitPackageChange(componentName: ComponentName) {
+        verify(mockedContext)
+            .registerReceiverAsUser(capture(listenerCaptor), any(), any(), nullable(), nullable())
+        listenerCaptor.value.onReceive(
+            mockedContext,
+            Intent(Intent.ACTION_PACKAGE_CHANGED).apply {
+                type = IntentFilter.SCHEME_PACKAGE
+                putExtra(
+                    Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST,
+                    arrayOf(componentName.packageName)
+                )
+            }
+        )
     }
 
     private companion object {
-        val USER = UserHandle(0)
+        val USER_1 = UserHandle(1)
+        val USER_2 = UserHandle(2)
         val COMPONENT_1 = ComponentName("pkg.test.1", "cls.test")
         val COMPONENT_2 = ComponentName("pkg.test.2", "cls.test")
     }
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 7b2ac90..b60f483 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
@@ -16,6 +16,7 @@
 
 package com.android.systemui.qs.tiles.impl.flashlight.domain
 
+import android.graphics.drawable.TestStubDrawable
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
@@ -35,7 +36,17 @@
 class FlashlightMapperTest : SysuiTestCase() {
     private val kosmos = Kosmos()
     private val qsTileConfig = kosmos.qsFlashlightTileConfig
-    private val mapper by lazy { FlashlightMapper(context.orCreateTestableResources.resources) }
+    private val mapper by lazy {
+        FlashlightMapper(
+            context.orCreateTestableResources
+                .apply {
+                    addOverride(R.drawable.qs_flashlight_icon_off, TestStubDrawable())
+                    addOverride(R.drawable.qs_flashlight_icon_on, TestStubDrawable())
+                }
+                .resources,
+            context.theme
+        )
+    }
 
     @Test
     fun mapsDisabledDataToInactiveState() {
@@ -56,20 +67,20 @@
 
     @Test
     fun mapsEnabledDataToOnIconState() {
-        val expectedIcon = Icon.Resource(R.drawable.qs_flashlight_icon_on, null)
-
         val tileState: QSTileState = mapper.map(qsTileConfig, FlashlightTileModel(true))
 
+        val expectedIcon =
+            Icon.Loaded(context.getDrawable(R.drawable.qs_flashlight_icon_on)!!, null)
         val actualIcon = tileState.icon()
         assertThat(actualIcon).isEqualTo(expectedIcon)
     }
 
     @Test
     fun mapsDisabledDataToOffIconState() {
-        val expectedIcon = Icon.Resource(R.drawable.qs_flashlight_icon_off, null)
-
         val tileState: QSTileState = mapper.map(qsTileConfig, FlashlightTileModel(false))
 
+        val expectedIcon =
+            Icon.Loaded(context.getDrawable(R.drawable.qs_flashlight_icon_off)!!, null)
         val actualIcon = tileState.icon()
         assertThat(actualIcon).isEqualTo(expectedIcon)
     }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/flashlight/domain/interactor/FlashlightTileDataInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/flashlight/domain/interactor/FlashlightTileDataInteractorTest.kt
index 00572d3..7f7490d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/flashlight/domain/interactor/FlashlightTileDataInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/flashlight/domain/interactor/FlashlightTileDataInteractorTest.kt
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+package com.android.systemui.qs.tiles.impl.flashlight.domain.interactor
+
 import android.os.UserHandle
 import android.testing.LeakCheck
 import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -22,7 +24,6 @@
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.coroutines.collectValues
 import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
-import com.android.systemui.qs.tiles.impl.flashlight.domain.interactor.FlashlightTileDataInteractor
 import com.android.systemui.qs.tiles.impl.flashlight.domain.model.FlashlightTileModel
 import com.android.systemui.utils.leaks.FakeFlashlightController
 import com.google.common.truth.Truth.assertThat
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/flashlight/domain/interactor/FlashlightTileUserActionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/flashlight/domain/interactor/FlashlightTileUserActionInteractorTest.kt
index f819f53..28d43b3 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/flashlight/domain/interactor/FlashlightTileUserActionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/flashlight/domain/interactor/FlashlightTileUserActionInteractorTest.kt
@@ -14,12 +14,13 @@
  * limitations under the License.
  */
 
+package com.android.systemui.qs.tiles.impl.flashlight.domain.interactor
+
 import android.app.ActivityManager
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.qs.tiles.base.interactor.QSTileInputTestKtx.click
-import com.android.systemui.qs.tiles.impl.flashlight.domain.interactor.FlashlightTileUserActionInteractor
 import com.android.systemui.qs.tiles.impl.flashlight.domain.model.FlashlightTileModel
 import com.android.systemui.statusbar.policy.FlashlightController
 import com.android.systemui.util.mockito.mock
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 8791877..ea74a4c 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
@@ -16,6 +16,7 @@
 
 package com.android.systemui.qs.tiles.impl.location.domain
 
+import android.graphics.drawable.TestStubDrawable
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
@@ -36,7 +37,17 @@
     private val kosmos = Kosmos()
     private val qsTileConfig = kosmos.qsLocationTileConfig
 
-    private val mapper by lazy { LocationTileMapper(context.orCreateTestableResources.resources) }
+    private val mapper by lazy {
+        LocationTileMapper(
+            context.orCreateTestableResources
+                .apply {
+                    addOverride(R.drawable.qs_location_icon_off, TestStubDrawable())
+                    addOverride(R.drawable.qs_location_icon_on, TestStubDrawable())
+                }
+                .resources,
+            context.theme
+        )
+    }
 
     @Test
     fun mapsDisabledDataToInactiveState() {
@@ -56,20 +67,18 @@
 
     @Test
     fun mapsEnabledDataToOnIconState() {
-        val expectedIcon = Icon.Resource(R.drawable.qs_location_icon_on, null)
-
         val tileState: QSTileState = mapper.map(qsTileConfig, LocationTileModel(true))
 
+        val expectedIcon = Icon.Loaded(context.getDrawable(R.drawable.qs_location_icon_on)!!, null)
         val actualIcon = tileState.icon()
         Truth.assertThat(actualIcon).isEqualTo(expectedIcon)
     }
 
     @Test
     fun mapsDisabledDataToOffIconState() {
-        val expectedIcon = Icon.Resource(R.drawable.qs_location_icon_off, null)
-
         val tileState: QSTileState = mapper.map(qsTileConfig, LocationTileModel(false))
 
+        val expectedIcon = Icon.Loaded(context.getDrawable(R.drawable.qs_location_icon_off)!!, null)
         val actualIcon = tileState.icon()
         Truth.assertThat(actualIcon).isEqualTo(expectedIcon)
     }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/saver/domain/DataSaverDialogDelegateTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/saver/domain/DataSaverDialogDelegateTest.kt
new file mode 100644
index 0000000..4b96251
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/saver/domain/DataSaverDialogDelegateTest.kt
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.saver.domain
+
+import android.content.SharedPreferences
+import android.testing.LeakCheck
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.internal.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.utils.leaks.FakeDataSaverController
+import kotlin.coroutines.EmptyCoroutineContext
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.verify
+
+/** Test [DataSaverDialogDelegate]. */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class DataSaverDialogDelegateTest : SysuiTestCase() {
+
+    private val dataSaverController = FakeDataSaverController(LeakCheck())
+
+    private lateinit var sysuiDialogFactory: SystemUIDialog.Factory
+    private lateinit var sysuiDialog: SystemUIDialog
+    private lateinit var dataSaverDialogDelegate: DataSaverDialogDelegate
+
+    @Before
+    fun setup() {
+        sysuiDialog = mock<SystemUIDialog>()
+        sysuiDialogFactory = mock<SystemUIDialog.Factory>()
+
+        dataSaverDialogDelegate =
+            DataSaverDialogDelegate(
+                sysuiDialogFactory,
+                context,
+                EmptyCoroutineContext,
+                dataSaverController,
+                mock<SharedPreferences>()
+            )
+
+        whenever(sysuiDialogFactory.create(eq(dataSaverDialogDelegate), eq(context)))
+            .thenReturn(sysuiDialog)
+    }
+    @Test
+    fun delegateSetsDialogTitleCorrectly() {
+        val expectedResId = R.string.data_saver_enable_title
+
+        dataSaverDialogDelegate.onCreate(sysuiDialog, null)
+
+        verify(sysuiDialog).setTitle(eq(expectedResId))
+    }
+
+    @Test
+    fun delegateSetsDialogMessageCorrectly() {
+        val expectedResId = R.string.data_saver_description
+
+        dataSaverDialogDelegate.onCreate(sysuiDialog, null)
+
+        verify(sysuiDialog).setMessage(expectedResId)
+    }
+
+    @Test
+    fun delegateSetsDialogPositiveButtonCorrectly() {
+        val expectedResId = R.string.data_saver_enable_button
+
+        dataSaverDialogDelegate.onCreate(sysuiDialog, null)
+
+        verify(sysuiDialog).setPositiveButton(eq(expectedResId), any())
+    }
+
+    @Test
+    fun delegateSetsDialogCancelButtonCorrectly() {
+        val expectedResId = R.string.cancel
+
+        dataSaverDialogDelegate.onCreate(sysuiDialog, null)
+
+        verify(sysuiDialog).setNeutralButton(eq(expectedResId), eq(null))
+    }
+}
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
new file mode 100644
index 0000000..d162c77
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/saver/domain/DataSaverTileMapperTest.kt
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.saver.domain
+
+import android.graphics.drawable.TestStubDrawable
+import android.widget.Switch
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.qs.tiles.impl.custom.QSTileStateSubject
+import com.android.systemui.qs.tiles.impl.saver.domain.model.DataSaverTileModel
+import com.android.systemui.qs.tiles.impl.saver.qsDataSaverTileConfig
+import com.android.systemui.qs.tiles.viewmodel.QSTileState
+import com.android.systemui.res.R
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class DataSaverTileMapperTest : SysuiTestCase() {
+    private val kosmos = Kosmos()
+    private val dataSaverTileConfig = kosmos.qsDataSaverTileConfig
+
+    // Using lazy (versus =) to make sure we override the right context -- see b/311612168
+    private val mapper by lazy {
+        DataSaverTileMapper(
+            context.orCreateTestableResources
+                .apply {
+                    addOverride(R.drawable.qs_data_saver_icon_off, TestStubDrawable())
+                    addOverride(R.drawable.qs_data_saver_icon_on, TestStubDrawable())
+                }
+                .resources,
+            context.theme
+        )
+    }
+
+    @Test
+    fun activeStateMatchesEnabledModel() {
+        val inputModel = DataSaverTileModel(true)
+
+        val outputState = mapper.map(dataSaverTileConfig, inputModel)
+
+        val expectedState =
+            createDataSaverTileState(
+                QSTileState.ActivationState.ACTIVE,
+                R.drawable.qs_data_saver_icon_on
+            )
+        QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState)
+    }
+
+    @Test
+    fun inactiveStateMatchesDisabledModel() {
+        val inputModel = DataSaverTileModel(false)
+
+        val outputState = mapper.map(dataSaverTileConfig, inputModel)
+
+        val expectedState =
+            createDataSaverTileState(
+                QSTileState.ActivationState.INACTIVE,
+                R.drawable.qs_data_saver_icon_off
+            )
+        QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState)
+    }
+
+    private fun createDataSaverTileState(
+        activationState: QSTileState.ActivationState,
+        iconRes: Int
+    ): QSTileState {
+        val label = context.getString(R.string.data_saver)
+        val secondaryLabel =
+            if (activationState == QSTileState.ActivationState.ACTIVE)
+                context.resources.getStringArray(R.array.tile_states_saver)[2]
+            else if (activationState == QSTileState.ActivationState.INACTIVE)
+                context.resources.getStringArray(R.array.tile_states_saver)[1]
+            else context.resources.getStringArray(R.array.tile_states_saver)[0]
+
+        return QSTileState(
+            { Icon.Loaded(context.getDrawable(iconRes)!!, null) },
+            label,
+            activationState,
+            secondaryLabel,
+            setOf(QSTileState.UserAction.CLICK, QSTileState.UserAction.LONG_CLICK),
+            label,
+            null,
+            QSTileState.SideViewIcon.None,
+            QSTileState.EnabledState.ENABLED,
+            Switch::class.qualifiedName
+        )
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/saver/domain/interactor/DataSaverTileDataInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/saver/domain/interactor/DataSaverTileDataInteractorTest.kt
new file mode 100644
index 0000000..819bd03
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/saver/domain/interactor/DataSaverTileDataInteractorTest.kt
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.saver.domain.interactor
+
+import android.os.UserHandle
+import android.testing.LeakCheck
+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.coroutines.collectValues
+import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
+import com.android.systemui.qs.tiles.impl.saver.domain.model.DataSaverTileModel
+import com.android.systemui.utils.leaks.FakeDataSaverController
+import com.google.common.truth.Truth
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class DataSaverTileDataInteractorTest : SysuiTestCase() {
+    private val controller: FakeDataSaverController = FakeDataSaverController(LeakCheck())
+    private val underTest: DataSaverTileDataInteractor = DataSaverTileDataInteractor(controller)
+
+    @Test
+    fun isAvailableRegardlessOfController() = runTest {
+        controller.setDataSaverEnabled(false)
+
+        runCurrent()
+        val availability by collectLastValue(underTest.availability(TEST_USER))
+
+        Truth.assertThat(availability).isTrue()
+    }
+
+    @Test
+    fun dataMatchesController() = runTest {
+        controller.setDataSaverEnabled(false)
+        val flowValues: List<DataSaverTileModel> by
+            collectValues(underTest.tileData(TEST_USER, flowOf(DataUpdateTrigger.InitialRequest)))
+
+        runCurrent()
+        controller.setDataSaverEnabled(true)
+        runCurrent()
+        controller.setDataSaverEnabled(false)
+        runCurrent()
+
+        Truth.assertThat(flowValues.size).isEqualTo(3)
+        Truth.assertThat(flowValues.map { it.isEnabled })
+            .containsExactly(false, true, false)
+            .inOrder()
+    }
+
+    private companion object {
+        val TEST_USER = UserHandle.of(1)!!
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/saver/domain/interactor/DataSaverTileUserActionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/saver/domain/interactor/DataSaverTileUserActionInteractorTest.kt
new file mode 100644
index 0000000..7091cb3
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/saver/domain/interactor/DataSaverTileUserActionInteractorTest.kt
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.saver.domain.interactor
+
+import android.content.Context
+import android.content.SharedPreferences
+import android.provider.Settings
+import android.testing.LeakCheck
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.DialogLaunchAnimator
+import com.android.systemui.qs.tiles.base.actions.FakeQSTileIntentUserInputHandler
+import com.android.systemui.qs.tiles.base.actions.intentInputs
+import com.android.systemui.qs.tiles.base.interactor.QSTileInputTestKtx
+import com.android.systemui.qs.tiles.impl.saver.domain.model.DataSaverTileModel
+import com.android.systemui.settings.UserFileManager
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.utils.leaks.FakeDataSaverController
+import com.google.common.truth.Truth.assertThat
+import kotlin.coroutines.EmptyCoroutineContext
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.verify
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class DataSaverTileUserActionInteractorTest : SysuiTestCase() {
+    private val qsTileIntentUserActionHandler = FakeQSTileIntentUserInputHandler()
+    private val dataSaverController = FakeDataSaverController(LeakCheck())
+
+    private lateinit var userFileManager: UserFileManager
+    private lateinit var sharedPreferences: SharedPreferences
+    private lateinit var dialogFactory: SystemUIDialog.Factory
+    private lateinit var underTest: DataSaverTileUserActionInteractor
+
+    @Before
+    fun setup() {
+        userFileManager = mock<UserFileManager>()
+        sharedPreferences = mock<SharedPreferences>()
+        dialogFactory = mock<SystemUIDialog.Factory>()
+        whenever(
+                userFileManager.getSharedPreferences(
+                    eq(DataSaverTileUserActionInteractor.PREFS),
+                    eq(Context.MODE_PRIVATE),
+                    eq(context.userId)
+                )
+            )
+            .thenReturn(sharedPreferences)
+
+        underTest =
+            DataSaverTileUserActionInteractor(
+                context,
+                EmptyCoroutineContext,
+                EmptyCoroutineContext,
+                dataSaverController,
+                qsTileIntentUserActionHandler,
+                mock<DialogLaunchAnimator>(),
+                dialogFactory,
+                userFileManager,
+            )
+    }
+
+    /** Since the dialog was shown before, we expect the click to enable the controller. */
+    @Test
+    fun handleClickToEnableDialogShownBefore() = runTest {
+        whenever(
+                sharedPreferences.getBoolean(
+                    eq(DataSaverTileUserActionInteractor.DIALOG_SHOWN),
+                    any()
+                )
+            )
+            .thenReturn(true)
+        val stateBeforeClick = false
+
+        underTest.handleInput(QSTileInputTestKtx.click(DataSaverTileModel(stateBeforeClick)))
+
+        assertThat(dataSaverController.isDataSaverEnabled).isEqualTo(!stateBeforeClick)
+    }
+
+    /**
+     * The first time the tile is clicked to turn on we expect (1) the enabled state to not change
+     * and (2) the dialog to be shown instead.
+     */
+    @Test
+    fun handleClickToEnableDialogNotShownBefore() = runTest {
+        whenever(
+                sharedPreferences.getBoolean(
+                    eq(DataSaverTileUserActionInteractor.DIALOG_SHOWN),
+                    any()
+                )
+            )
+            .thenReturn(false)
+        val mockDialog = mock<SystemUIDialog>()
+        whenever(dialogFactory.create(any(), any())).thenReturn(mockDialog)
+        val stateBeforeClick = false
+
+        val input = QSTileInputTestKtx.click(DataSaverTileModel(stateBeforeClick))
+        underTest.handleInput(input)
+
+        assertThat(dataSaverController.isDataSaverEnabled).isEqualTo(stateBeforeClick)
+        verify(mockDialog).show()
+    }
+
+    /** Disabling should flip the state, even if the dialog was not shown before. */
+    @Test
+    fun handleClickToDisableDialogNotShownBefore() = runTest {
+        whenever(
+                sharedPreferences.getBoolean(
+                    eq(DataSaverTileUserActionInteractor.DIALOG_SHOWN),
+                    any()
+                )
+            )
+            .thenReturn(false)
+        val enabledBeforeClick = true
+
+        underTest.handleInput(QSTileInputTestKtx.click(DataSaverTileModel(enabledBeforeClick)))
+
+        assertThat(dataSaverController.isDataSaverEnabled).isEqualTo(!enabledBeforeClick)
+    }
+
+    @Test
+    fun handleClickToDisableDialogShownBefore() = runTest {
+        whenever(
+                sharedPreferences.getBoolean(
+                    eq(DataSaverTileUserActionInteractor.DIALOG_SHOWN),
+                    any()
+                )
+            )
+            .thenReturn(true)
+        val enabledBeforeClick = true
+
+        underTest.handleInput(QSTileInputTestKtx.click(DataSaverTileModel(enabledBeforeClick)))
+
+        assertThat(dataSaverController.isDataSaverEnabled).isEqualTo(!enabledBeforeClick)
+    }
+
+    @Test
+    fun handleLongClickWhenEnabled() = runTest {
+        val enabledState = true
+
+        underTest.handleInput(QSTileInputTestKtx.longClick(DataSaverTileModel(enabledState)))
+
+        assertThat(qsTileIntentUserActionHandler.handledInputs).hasSize(1)
+        val intentInput = qsTileIntentUserActionHandler.intentInputs.last()
+        val actualIntentAction = intentInput.intent.action
+        val expectedIntentAction = Settings.ACTION_DATA_SAVER_SETTINGS
+        assertThat(actualIntentAction).isEqualTo(expectedIntentAction)
+    }
+
+    @Test
+    fun handleLongClickWhenDisabled() = runTest {
+        val enabledState = false
+
+        underTest.handleInput(QSTileInputTestKtx.longClick(DataSaverTileModel(enabledState)))
+
+        assertThat(qsTileIntentUserActionHandler.handledInputs).hasSize(1)
+        val intentInput = qsTileIntentUserActionHandler.intentInputs.last()
+        val actualIntentAction = intentInput.intent.action
+        val expectedIntentAction = Settings.ACTION_DATA_SAVER_SETTINGS
+        assertThat(actualIntentAction).isEqualTo(expectedIntentAction)
+    }
+}
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 87f5009..a977606 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
@@ -17,6 +17,7 @@
 package com.android.systemui.qs.tiles.impl.uimodenight.domain
 
 import android.app.UiModeManager
+import android.graphics.drawable.TestStubDrawable
 import android.text.TextUtils
 import android.view.View
 import android.widget.Switch
@@ -41,7 +42,15 @@
     private val qsTileConfig = kosmos.qsUiModeNightTileConfig
 
     private val mapper by lazy {
-        UiModeNightTileMapper(context.orCreateTestableResources.resources)
+        UiModeNightTileMapper(
+            context.orCreateTestableResources
+                .apply {
+                    addOverride(R.drawable.qs_light_dark_theme_icon_off, TestStubDrawable())
+                    addOverride(R.drawable.qs_light_dark_theme_icon_on, TestStubDrawable())
+                }
+                .resources,
+            context.theme
+        )
     }
 
     private fun createUiNightModeTileState(
@@ -60,7 +69,7 @@
         expandedAccessibilityClass: KClass<out View>? = Switch::class,
     ): QSTileState {
         return QSTileState(
-            { Icon.Resource(iconRes, null) },
+            { Icon.Loaded(context.getDrawable(iconRes)!!, null) },
             label,
             activationState,
             secondaryLabel,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
index 3cb97e3..61d55f0 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
@@ -19,6 +19,7 @@
 package com.android.systemui.scene.domain.startable
 
 import android.os.PowerManager
+import android.platform.test.annotations.EnableFlags
 import android.view.Display
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
@@ -45,7 +46,6 @@
 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
 import org.mockito.Mockito.clearInvocations
@@ -55,6 +55,7 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4::class)
+@EnableFlags(AconfigFlags.FLAG_SCENE_CONTAINER)
 class SceneContainerStartableTest : SysuiTestCase() {
 
     private val utils = SceneTestUtils(this)
@@ -93,11 +94,6 @@
             authenticationInteractor = authenticationInteractor,
         )
 
-    @Before
-    fun setUp() {
-        mSetFlagsRule.enableFlags(AconfigFlags.FLAG_SCENE_CONTAINER)
-    }
-
     @Test
     fun hydrateVisibility() =
         testScope.runTest {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/smartspace/CommunalSmartspaceControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/smartspace/CommunalSmartspaceControllerTest.kt
new file mode 100644
index 0000000..ef2046d
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/smartspace/CommunalSmartspaceControllerTest.kt
@@ -0,0 +1,172 @@
+/*
+ * 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.smartspace
+
+import android.app.smartspace.SmartspaceManager
+import android.app.smartspace.SmartspaceSession
+import android.app.smartspace.SmartspaceTarget
+import android.content.Context
+import android.graphics.drawable.Drawable
+import android.testing.TestableLooper
+import android.view.View
+import android.widget.FrameLayout
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.communal.smartspace.CommunalSmartspaceController
+import com.android.systemui.plugins.BcSmartspaceConfigPlugin
+import com.android.systemui.plugins.BcSmartspaceDataPlugin
+import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceView
+import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.util.concurrency.Execution
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.withArgCaptor
+import com.google.common.truth.Truth.assertThat
+import java.util.Optional
+import java.util.concurrent.Executor
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@TestableLooper.RunWithLooper
+class CommunalSmartspaceControllerTest : SysuiTestCase() {
+    @Mock private lateinit var smartspaceManager: SmartspaceManager
+
+    @Mock private lateinit var execution: Execution
+
+    @Mock private lateinit var uiExecutor: Executor
+
+    @Mock private lateinit var targetFilter: SmartspaceTargetFilter
+
+    @Mock private lateinit var plugin: BcSmartspaceDataPlugin
+
+    @Mock private lateinit var precondition: SmartspacePrecondition
+
+    @Mock private lateinit var listener: BcSmartspaceDataPlugin.SmartspaceTargetListener
+
+    @Mock private lateinit var session: SmartspaceSession
+
+    private lateinit var controller: CommunalSmartspaceController
+
+    // TODO(b/272811280): Remove usage of real view
+    private val fakeParent = FrameLayout(context)
+
+    /**
+     * A class which implements SmartspaceView and extends View. This is mocked to provide the right
+     * object inheritance and interface implementation used in CommunalSmartspaceController
+     */
+    private class TestView(context: Context?) : View(context), SmartspaceView {
+        override fun registerDataProvider(plugin: BcSmartspaceDataPlugin?) {}
+
+        override fun registerConfigProvider(plugin: BcSmartspaceConfigPlugin?) {}
+
+        override fun setPrimaryTextColor(color: Int) {}
+
+        override fun setUiSurface(uiSurface: String) {}
+
+        override fun setDozeAmount(amount: Float) {}
+
+        override fun setIntentStarter(intentStarter: BcSmartspaceDataPlugin.IntentStarter?) {}
+
+        override fun setFalsingManager(falsingManager: FalsingManager?) {}
+
+        override fun setDnd(image: Drawable?, description: String?) {}
+
+        override fun setNextAlarm(image: Drawable?, description: String?) {}
+
+        override fun setMediaTarget(target: SmartspaceTarget?) {}
+
+        override fun getSelectedPage(): Int {
+            return 0
+        }
+
+        override fun getCurrentCardTopPadding(): Int {
+            return 0
+        }
+    }
+
+    @Before
+    fun setup() {
+        MockitoAnnotations.initMocks(this)
+        `when`(smartspaceManager.createSmartspaceSession(any())).thenReturn(session)
+
+        controller =
+            CommunalSmartspaceController(
+                context,
+                smartspaceManager,
+                execution,
+                uiExecutor,
+                precondition,
+                Optional.of(targetFilter),
+                Optional.of(plugin)
+            )
+    }
+
+    /** Ensures smartspace session begins on a listener only flow. */
+    @Test
+    fun testConnectOnListen() {
+        `when`(precondition.conditionsMet()).thenReturn(true)
+        controller.addListener(listener)
+
+        verify(smartspaceManager).createSmartspaceSession(any())
+
+        var targetListener =
+            withArgCaptor<SmartspaceSession.OnTargetsAvailableListener> {
+                verify(session).addOnTargetsAvailableListener(any(), capture())
+            }
+
+        `when`(targetFilter.filterSmartspaceTarget(any())).thenReturn(true)
+
+        var target = Mockito.mock(SmartspaceTarget::class.java)
+        targetListener.onTargetsAvailable(listOf(target))
+
+        var targets =
+            withArgCaptor<List<SmartspaceTarget>> { verify(plugin).onTargetsAvailable(capture()) }
+
+        assertThat(targets.contains(target)).isTrue()
+
+        controller.removeListener(listener)
+
+        verify(session).close()
+    }
+
+    /**
+     * Ensures session is closed and weather plugin unregisters the notifier when weather smartspace
+     * view is detached.
+     */
+    @Test
+    fun testDisconnect_emitsEmptyListAndRemovesNotifier() {
+        `when`(precondition.conditionsMet()).thenReturn(true)
+        controller.addListener(listener)
+
+        verify(smartspaceManager).createSmartspaceSession(any())
+
+        controller.removeListener(listener)
+
+        verify(session).close()
+
+        // And the listener receives an empty list of targets and unregisters the notifier
+        verify(plugin).onTargetsAvailable(emptyList())
+        verify(plugin).registerSmartspaceEventNotifier(null)
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationStackAppearanceIntegrationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationStackAppearanceIntegrationTest.kt
index f04dfd1..4cdb08a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationStackAppearanceIntegrationTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationStackAppearanceIntegrationTest.kt
@@ -24,7 +24,7 @@
 import com.android.systemui.common.shared.model.NotificationContainerBounds
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.flags.Flags
-import com.android.systemui.flags.featureFlagsClassic
+import com.android.systemui.flags.fakeFeatureFlagsClassic
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.scene.domain.interactor.sceneInteractor
 import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags
@@ -51,7 +51,7 @@
     private val kosmos =
         testKosmos().apply {
             sceneContainerFlags = FakeSceneContainerFlags(enabled = true)
-            featureFlagsClassic.apply {
+            fakeFeatureFlagsClassic.apply {
                 set(Flags.FULL_SCREEN_USER_SWITCHER, false)
                 set(Flags.NSSL_DEBUG_LINES, false)
             }
@@ -67,9 +67,24 @@
             val bounds by collectLastValue(appearanceViewModel.stackBounds)
 
             val top = 200f
+            val left = 0f
             val bottom = 550f
-            placeholderViewModel.onBoundsChanged(top, bottom)
-            assertThat(bounds).isEqualTo(NotificationContainerBounds(top = top, bottom = bottom))
+            val right = 100f
+            placeholderViewModel.onBoundsChanged(
+                left = left,
+                top = top,
+                right = right,
+                bottom = bottom
+            )
+            assertThat(bounds)
+                .isEqualTo(
+                    NotificationContainerBounds(
+                        left = left,
+                        top = top,
+                        right = right,
+                        bottom = bottom
+                    )
+                )
         }
 
     @Test
diff --git a/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java b/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java
index 64c0f99..c99cb39 100644
--- a/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java
+++ b/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java
@@ -44,6 +44,7 @@
     String UI_SURFACE_HOME_SCREEN = "home";
     String UI_SURFACE_MEDIA = "media_data_manager";
     String UI_SURFACE_DREAM = "dream";
+    String UI_SURFACE_GLANCEABLE_HUB = "glanceable_hub";
 
     String ACTION = "com.android.systemui.action.PLUGIN_BC_SMARTSPACE_DATA";
     int VERSION = 1;
diff --git a/packages/SystemUI/res-keyguard/drawable/bouncer_password_text_view_focused_background.xml b/packages/SystemUI/res-keyguard/drawable/bouncer_password_text_view_focused_background.xml
deleted file mode 100644
index 02e10cd..0000000
--- a/packages/SystemUI/res-keyguard/drawable/bouncer_password_text_view_focused_background.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_focused="true">
-        <shape android:shape="rectangle">
-            <corners android:radius="16dp" />
-            <stroke android:width="3dp"
-                android:color="@color/bouncer_password_focus_color" />
-        </shape>
-    </item>
-</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_bouncer_message_area.xml b/packages/SystemUI/res-keyguard/layout/keyguard_bouncer_message_area.xml
index 0b35559..66c54f2 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_bouncer_message_area.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_bouncer_message_area.xml
@@ -23,7 +23,7 @@
         android:layout_marginTop="@dimen/keyguard_lock_padding"
         android:importantForAccessibility="no"
         android:ellipsize="marquee"
-        android:focusable="false"
+        android:focusable="true"
         android:gravity="center"
         android:singleLine="true" />
 </merge>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_num_pad_key.xml b/packages/SystemUI/res-keyguard/layout/keyguard_num_pad_key.xml
index 48769fd..073f090 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_num_pad_key.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_num_pad_key.xml
@@ -18,8 +18,6 @@
     <TextView
         android:id="@+id/digit_text"
         style="@style/Widget.TextView.NumPadKey.Digit"
-        android:autoSizeMaxTextSize="32sp"
-        android:autoSizeTextType="uniform"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         />
diff --git a/packages/SystemUI/res-keyguard/values-sw/strings.xml b/packages/SystemUI/res-keyguard/values-sw/strings.xml
index 72f1fc3..9bc6c22 100644
--- a/packages/SystemUI/res-keyguard/values-sw/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sw/strings.xml
@@ -87,10 +87,10 @@
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Weka PIN ya SIM."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Weka PIN ya SIM ya \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Zima eSIM ili utumie kifaa bila huduma ya vifaa vya mkononi."</string>
-    <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM sasa imefungwa. Weka nambari ya PUK ili uendelee. Wasiliana na mtoa huduma za mtandao kwa maelezo."</string>
-    <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM ya \"<xliff:g id="CARRIER">%1$s</xliff:g>\" sasa imezimwa. Weka nambari ya PUK ili uendelee. Wasiliana na mtoa huduma kwa maelezo."</string>
-    <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Weka nambari ya PIN unayopendelea"</string>
-    <string name="kg_enter_confirm_pin_hint" msgid="4261064020391799132">"Thibitisha nambari ya PIN unayopendelea"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM sasa imefungwa. Weka namba ya PUK ili uendelee. Wasiliana na mtoa huduma za mtandao kwa maelezo."</string>
+    <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM ya \"<xliff:g id="CARRIER">%1$s</xliff:g>\" sasa imezimwa. Weka namba ya PUK ili uendelee. Wasiliana na mtoa huduma kwa maelezo."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Weka namba ya PIN unayopendelea"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="4261064020391799132">"Thibitisha namba ya PIN unayopendelea"</string>
     <string name="kg_sim_unlock_progress_dialog_message" msgid="1123048780346295748">"Inafungua SIM…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Andika PIN ya tarakimu 4 hadi 8."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"Nambari ya PUK inafaa kuwa na tarakimu 8 au zaidi."</string>
diff --git a/packages/SystemUI/res-keyguard/values/styles.xml b/packages/SystemUI/res-keyguard/values/styles.xml
index 6e6709f..2cca951 100644
--- a/packages/SystemUI/res-keyguard/values/styles.xml
+++ b/packages/SystemUI/res-keyguard/values/styles.xml
@@ -69,14 +69,13 @@
         <item name="android:singleLine">true</item>
         <item name="android:gravity">center_horizontal|center_vertical</item>
         <item name="android:background">@null</item>
-        <item name="android:textSize">32sp</item>
+        <item name="android:textSize">32dp</item>
         <item name="android:textColor">?android:attr/textColorPrimary</item>
         <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
         <item name="android:paddingBottom">-16dp</item>
     </style>
     <style name="Widget.TextView.Password" parent="@android:style/Widget.TextView">
         <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
-        <item name="android:background">@drawable/bouncer_password_text_view_focused_background</item>
         <item name="android:gravity">center</item>
         <item name="android:textColor">?android:attr/textColorPrimary</item>
     </style>
diff --git a/packages/SystemUI/res/drawable/arrow_pointing_down.xml b/packages/SystemUI/res/drawable/arrow_pointing_down.xml
new file mode 100644
index 0000000..be39683
--- /dev/null
+++ b/packages/SystemUI/res/drawable/arrow_pointing_down.xml
@@ -0,0 +1,26 @@
+<!--
+  ~ 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.
+  -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24.0"
+    android:viewportHeight="24.0"
+    android:tint="?attr/colorControlNormal">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M5.41,7.59L4,9l8,8 8,-8 -1.41,-1.41L12,14.17" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/qs_record_issue_icon_off.xml b/packages/SystemUI/res/drawable/qs_record_issue_icon_off.xml
new file mode 100644
index 0000000..bd60431
--- /dev/null
+++ b/packages/SystemUI/res/drawable/qs_record_issue_icon_off.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24.0dp"
+    android:height="24.0dp"
+    android:viewportWidth="24.0"
+    android:viewportHeight="24.0">
+    <path
+        android:pathData="M5.76 12.89c0 3.28 2.54 5.97 5.76 6.22v-8.26h-5.4c-.23.64-.36 1.33-.36 2.04zm9.27-5.45l1.01-1.59c.19-.29.1-.67-.19-.86-.29-.19-.68-.1-.86.19l-1.12 1.76c-.59-.19-1.22-.29-1.87-.29s-1.28.1-1.87.29L9.01 5.18c-.18-.29-.57-.38-.86-.19-.29.18-.38.57-.19.86l1.01 1.59c-1.02.57-1.86 1.43-2.43 2.45h10.92c-.57-1.02-1.41-1.88-2.43-2.45zm2.85 3.41h-5.4v8.26c3.22-.25 5.76-2.93 5.76-6.22 0-.71-.13-1.4-.36-2.04z"
+        android:fillColor="#000000"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/qs_record_issue_icon_on.xml b/packages/SystemUI/res/drawable/qs_record_issue_icon_on.xml
new file mode 100644
index 0000000..fadaf78
--- /dev/null
+++ b/packages/SystemUI/res/drawable/qs_record_issue_icon_on.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24.0dp"
+    android:height="24.0dp"
+    android:viewportWidth="24.0"
+    android:viewportHeight="24.0">
+    <path
+        android:pathData="M5.76 12.89c0 3.28 2.54 5.97 5.76 6.22v-8.26h-5.4c-.23.64-.36 1.33-.36 2.04zm9.27-5.45l1.01-1.59c.19-.29.1-.67-.19-.86-.29-.19-.68-.1-.86.19l-1.12 1.76c-.59-.19-1.22-.29-1.87-.29s-1.28.1-1.87.29L9.01 5.18c-.18-.29-.57-.38-.86-.19-.29.18-.38.57-.19.86l1.01 1.59c-1.02.57-1.86 1.43-2.43 2.45h10.92c-.57-1.02-1.41-1.88-2.43-2.45zm2.85 3.41h-5.4v8.26c3.22-.25 5.76-2.93 5.76-6.22 0-.71-.13-1.4-.36-2.04z"
+        android:fillColor="#FFFFFF"/>
+</vector>
diff --git a/packages/SystemUI/res/layout/bluetooth_device_item.xml b/packages/SystemUI/res/layout/bluetooth_device_item.xml
index 4336ccc..4535f67 100644
--- a/packages/SystemUI/res/layout/bluetooth_device_item.xml
+++ b/packages/SystemUI/res/layout/bluetooth_device_item.xml
@@ -41,7 +41,7 @@
         android:textDirection="locale"
         android:textAlignment="gravity"
         android:paddingStart="20dp"
-        android:paddingTop="10dp"
+        android:paddingTop="15dp"
         android:maxLines="1"
         android:ellipsize="end"
         app:layout_constraintTop_toTopOf="parent"
@@ -56,7 +56,7 @@
         android:id="@+id/bluetooth_device_summary"
         style="@style/BluetoothTileDialog.DeviceSummary"
         android:paddingStart="20dp"
-        android:paddingBottom="10dp"
+        android:paddingBottom="15dp"
         android:maxLines="1"
         android:ellipsize="end"
         app:layout_constraintTop_toBottomOf="@+id/bluetooth_device_name"
diff --git a/packages/SystemUI/res/layout/bluetooth_tile_dialog.xml b/packages/SystemUI/res/layout/bluetooth_tile_dialog.xml
index 50241cd..0534c6e 100644
--- a/packages/SystemUI/res/layout/bluetooth_tile_dialog.xml
+++ b/packages/SystemUI/res/layout/bluetooth_tile_dialog.xml
@@ -51,13 +51,14 @@
         android:textAppearance="@style/TextAppearance.Dialog.Body.Message"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintBottom_toTopOf="@+id/scroll_view"
         app:layout_constraintTop_toBottomOf="@id/bluetooth_tile_dialog_title" />
 
     <androidx.core.widget.NestedScrollView
         android:id="@+id/scroll_view"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
+        android:layout_marginTop="21dp"
+        android:fillViewport="true"
         app:layout_constrainedHeight="true"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintEnd_toEndOf="parent"
@@ -84,13 +85,13 @@
                 android:textSize="16sp"
                 app:layout_constraintEnd_toStartOf="@+id/bluetooth_toggle"
                 app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintBottom_toTopOf="@+id/device_list"
                 app:layout_constraintTop_toTopOf="parent" />
 
             <Switch
                 android:id="@+id/bluetooth_toggle"
                 android:layout_width="wrap_content"
                 android:layout_height="48dp"
+                android:paddingTop="10dp"
                 android:gravity="start|center_vertical"
                 android:paddingEnd="40dp"
                 android:contentDescription="@string/turn_on_bluetooth"
@@ -100,14 +101,13 @@
                 android:track="@drawable/settingslib_track_selector"
                 app:layout_constraintEnd_toEndOf="parent"
                 app:layout_constraintStart_toEndOf="@+id/bluetooth_toggle_title"
-                app:layout_constraintBottom_toTopOf="@+id/device_list"
                 app:layout_constraintTop_toTopOf="parent" />
 
             <androidx.recyclerview.widget.RecyclerView
                 android:id="@+id/device_list"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:layout_marginTop="10dp"
+                android:layout_marginTop="20dp"
                 app:layout_constraintStart_toStartOf="parent"
                 app:layout_constraintEnd_toEndOf="parent"
                 app:layout_constraintTop_toBottomOf="@+id/bluetooth_toggle"
@@ -146,6 +146,7 @@
                 android:background="@drawable/bluetooth_tile_dialog_bg_off"
                 android:layout_width="0dp"
                 android:layout_height="64dp"
+                android:layout_marginBottom="9dp"
                 android:contentDescription="@string/accessibility_bluetooth_device_settings_pair_new_device"
                 app:layout_constraintStart_toStartOf="parent"
                 app:layout_constraintEnd_toEndOf="parent"
@@ -177,7 +178,6 @@
                 android:maxLines="1"
                 android:text="@string/inline_done_button"
                 app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintTop_toBottomOf="@id/pair_new_device_button"
                 app:layout_constraintBottom_toBottomOf="parent" />
         </androidx.constraintlayout.widget.ConstraintLayout>
     </androidx.core.widget.NestedScrollView>
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index 66c57fc..6d7ce06 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -106,5 +106,5 @@
     </FrameLayout>
 
     <include layout="@layout/ambient_indication"
-             android:id="@+id/ambient_indication_container" />
+             android:id="@id/ambient_indication_container" />
 </com.android.systemui.statusbar.phone.KeyguardBottomAreaView>
diff --git a/packages/SystemUI/res/layout/privacy_dialog_card_button.xml b/packages/SystemUI/res/layout/privacy_dialog_card_button.xml
index e297b93..bcbe2c43 100644
--- a/packages/SystemUI/res/layout/privacy_dialog_card_button.xml
+++ b/packages/SystemUI/res/layout/privacy_dialog_card_button.xml
@@ -17,6 +17,8 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="56dp"
+    android:paddingTop="4dp"
+    android:paddingBottom="4dp"
     android:layout_marginBottom="4dp"
     android:ellipsize="end"
     android:maxLines="1"
diff --git a/packages/SystemUI/res/layout/privacy_dialog_v2.xml b/packages/SystemUI/res/layout/privacy_dialog_v2.xml
index 843dad0..76098a1 100644
--- a/packages/SystemUI/res/layout/privacy_dialog_v2.xml
+++ b/packages/SystemUI/res/layout/privacy_dialog_v2.xml
@@ -16,7 +16,7 @@
 <androidx.core.widget.NestedScrollView
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
-    android:layout_width="@dimen/large_dialog_width"
+    android:layout_width="match_parent"
     android:layout_height="wrap_content">
 
     <LinearLayout
diff --git a/packages/SystemUI/res/layout/record_issue_dialog.xml b/packages/SystemUI/res/layout/record_issue_dialog.xml
new file mode 100644
index 0000000..53ad9f1
--- /dev/null
+++ b/packages/SystemUI/res/layout/record_issue_dialog.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:orientation="vertical" >
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:textAppearance="@style/TextAppearance.Dialog.Body.Message"
+        android:text="@string/qs_record_issue_dropdown_header" />
+
+    <Button
+        android:id="@+id/issue_type_button"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/qs_record_issue_dropdown_prompt"
+        android:lines="1"
+        android:drawableRight="@drawable/arrow_pointing_down"
+        android:layout_marginTop="@dimen/qqs_layout_margin_top"
+        android:focusable="false"
+        android:clickable="true" />
+
+    <!-- Screen Record Switch -->
+    <LinearLayout
+        android:id="@+id/screenrecord_switch_container"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="@dimen/qqs_layout_margin_top"
+        android:orientation="horizontal">
+
+        <ImageView
+            android:layout_width="@dimen/screenrecord_option_icon_size"
+            android:layout_height="@dimen/screenrecord_option_icon_size"
+            android:layout_weight="0"
+            android:src="@drawable/ic_screenrecord"
+            app:tint="?androidprv:attr/materialColorOnSurface"
+            android:layout_gravity="center"
+            android:layout_marginEnd="@dimen/screenrecord_option_padding" />
+
+        <TextView
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:minHeight="@dimen/screenrecord_option_icon_size"
+            android:layout_weight="1"
+            android:layout_gravity="fill_vertical"
+            android:gravity="center"
+            android:text="@string/quick_settings_screen_record_label"
+            android:textAppearance="@style/TextAppearance.Dialog.Body.Message"
+            android:importantForAccessibility="no"/>
+
+        <Switch
+            android:id="@+id/screenrecord_switch"
+            android:layout_width="wrap_content"
+            android:minHeight="@dimen/screenrecord_option_icon_size"
+            android:layout_height="wrap_content"
+            android:gravity="center"
+            android:layout_gravity="fill_vertical"
+            android:layout_weight="0"
+            android:contentDescription="@string/quick_settings_screen_record_label" />
+    </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/sidefps_view.xml b/packages/SystemUI/res/layout/sidefps_view.xml
index 4d95220..fc4bf8a 100644
--- a/packages/SystemUI/res/layout/sidefps_view.xml
+++ b/packages/SystemUI/res/layout/sidefps_view.xml
@@ -14,7 +14,7 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-<com.android.systemui.biometrics.SideFpsLottieViewWrapper
+<com.android.systemui.biometrics.SideFpsIndicatorView
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:id="@+id/sidefps_animation"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 09f3766..fba6d21 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Skermopname"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Begin"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Stop"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Eenhandmodus"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Kontras"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standaard"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laai tans • Vol oor <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swiep links om die gemeenskaplike tutoriaal te begin"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Maak die legstukredigeerder oop"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Verwyder ’n legstuk"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Voeg legstuk by"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Knoppie <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Back"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Oppyl"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Afpyl"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Linkspyl"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Regspyl"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Middel"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Spasie"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Kennisgewings"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Kortpadsleutels"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Wissel sleutelborduitleg"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"of"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Maak soeknavraag skoon"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Kortpaaie"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Soek kortpaaie"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Geen kortpaaie gevind nie"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Invoer"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Maak apps oop"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Huidige app"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Wys tans soekresultate"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Wys tans stelselkortpaaie"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Wys tans invoerkortpaaie"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Wys tans kortpaaie wat apps oopmaak"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Wys tans kortpaaie vir die huidige app"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Bekyk kennisgewings"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Neem skermskoot"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Wys kortpaaie"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Stel versteknotasapp in Instellings"</string>
     <string name="install_app" msgid="5066668100199613936">"Installeer app"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Sinkroniseer wedersyds na eksterne skerm?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Enige Dual Screen-aktiwiteit wat tans loop sal gestop word"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Sinkroniseer skerm wedersyds"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Maak toe"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Skerm is gekoppel"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 9c07491..12276f5 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"የማያ ቀረጻ"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ጀምር"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"አቁም"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"የአንድ እጅ ሁነታ"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"ንጽጽር"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"መደበኛ"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ኃይል በመሙላት ላይ • በ<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ውስጥ ይሞላል"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"የጋራ አጋዥ ሥልጠናውን ለመጀመር ወደ ግራ ያንሸራትቱ።"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"የምግብር አርታዒውን ይክፈቱ"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"ምግብርን አስወግድ"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"ምግብር አክል"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -1197,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"በቅንብሮች ውስጥ ነባሪ የማስታወሻዎች መተግበሪያን ያቀናብሩ"</string>
     <string name="install_app" msgid="5066668100199613936">"መተግበሪያን ጫን"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"ወደ ውጫዊ ማሳያ ይንጸባረቅ?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"በአሁኑ ጊዜ እያሄደ ያለው ማንኛውም የDual Screen እንቅስቃሴ ይቆማል"</string>
     <string name="mirror_display" msgid="2515262008898122928">"ማሳያን አንጸባርቅ"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"አሰናብት"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"ማሳያ ተገናኝቷል"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 1c065bb..ac76ed0 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"تسجيل الشاشة"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"بدء"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"إيقاف"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"وضع \"التصفح بيد واحدة\""</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"التباين"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"عادي"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • جارٍ الشحن • ستمتلئ البطارية خلال <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"مرِّر سريعًا لليمين لبدء الدليل التوجيهي العام."</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"فتح محرِّر التطبيقات المصغّرة"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"إزالة تطبيق مصغّر"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"إضافة تطبيق مصغّر"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"الزر <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Back"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"سهم متّجه للأعلى"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"سهم متّجه للأسفل"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"سهم متّجه لليسار"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"سهم متّجه لليمين"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"وسط"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"مسافة"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"الإشعارات"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"اختصارات لوحة المفاتيح"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"تبديل تنسيق لوحة المفاتيح"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"أو"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"محو طلب البحث"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"الاختصارات"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"البحث في الاختصارات"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"لم يُعثَر على اختصارات."</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"إدخال"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"فتح التطبيقات"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"التطبيق الحالي"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"جارٍ عرض نتائج البحث"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"جارٍ عرض اختصارات النظام"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"جارٍ عرض اختصارات الإدخال"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"جارٍ عرض اختصارات فتح التطبيقات"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"جارٍ عرض اختصارات التطبيق الحالي"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"عرض الإشعارات"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"أخذ لقطة شاشة"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"عرض الاختصارات"</string>
@@ -1208,6 +1207,8 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"يمكنك ضبط تطبيق تدوين الملاحظات التلقائي في \"الإعدادات\"."</string>
     <string name="install_app" msgid="5066668100199613936">"تثبيت التطبيق"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"هل تريد بث محتوى جهازك على الشاشة الخارجية؟"</string>
+    <!-- no translation found for connected_display_dialog_dual_display_stop_warning (2917631104216376315) -->
+    <skip />
     <string name="mirror_display" msgid="2515262008898122928">"بث المحتوى على الشاشة"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"إغلاق"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"تم توصيل الشاشة"</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 0c5f104..21da387 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"স্ক্ৰীন ৰেকৰ্ড কৰা"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"আৰম্ভ কৰক"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"বন্ধ কৰক"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"এখন হাতেৰে ব্যৱহাৰ কৰা ম’ড"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"কনট্ৰাষ্ট"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"মানক"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • চাৰ্জ হৈ আছে • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ত সম্পূৰ্ণ হ’ব"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"সম্প্ৰদায় সম্পৰ্কীয় নিৰ্দেশনা আৰম্ভ কৰিবলৈ বাওঁফালে ছোৱাইপ কৰক"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"ৱিজেট সম্পাদকটো খোলক"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"এটা ৱিজেট আঁতৰাওক"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"ৱিজেট যোগ দিয়ক"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"<xliff:g id="NAME">%1$s</xliff:g> বুটাম"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"হ\'ম"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"উভতি যাওক"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"ওপৰলৈ নিৰ্দেশ কৰা কাঁড় চিহ্ন"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"তললৈ নিৰ্দেশ কৰা কাঁড় চিহ্ন"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"বাওঁফাললৈ নিৰ্দেশ কৰা কাঁড় চিহ্ন"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"সোঁফাললৈ নিৰ্দেশ কৰা কাঁড় চিহ্ন"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"স্ক্ৰীনৰ মাজত"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"স্পেচ"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"জাননীসমূহ"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"কীব\'ৰ্ড শ্বৰ্টকাটসমূহ"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"কীব\'ৰ্ডৰ সজ্জা সলনি কৰক"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"অথবা"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"সন্ধান কৰা প্ৰশ্ন মচক"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"শ্বৰ্টকাট"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"সন্ধানৰ শ্বৰ্টকাট"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"কোনো শ্বৰ্টকাট বিচাৰি পোৱা নাই"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"ইনপুট"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"এপ্ খোলক"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"বৰ্তমানৰ এপ্"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"সন্ধানৰ ফলাফল দেখুৱাই থকা হৈছে"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"ছিষ্টেমৰ শ্বৰ্টকাট দেখুৱাই থকা হৈছে"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"ইনপুট শ্বৰ্টকাট দেখুৱাই থকা হৈছে"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"এনে শ্বৰ্টকাট দেখুৱাই থকা হৈছে যিয়ে এপ্‌সমূহ খোলে"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"বৰ্তমানৰ এপ্‌টোৰ বাবে শ্বৰ্টকাট দেখুৱাই থকা হৈছে"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"জাননী চাওক"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"স্ক্ৰীনশ্বট লওক"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"শ্বৰ্টকাট দেখুৱাওক"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"ছেটিঙত টোকাৰ ডিফ’ল্ট এপ্ ছেট কৰক"</string>
     <string name="install_app" msgid="5066668100199613936">"এপ্‌টো ইনষ্টল কৰক"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"বাহ্যিক ডিছপ্লে’লৈ মিৰ’ৰ কৰিবনে?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"বৰ্তমান চলি থকা যিকোনো দ্বৈত স্ক্ৰীনৰ কাৰ্যকলাপ বন্ধ কৰা হ’ব"</string>
     <string name="mirror_display" msgid="2515262008898122928">"ডিছপ্লে’ মিৰ’ৰ কৰক"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"অগ্ৰাহ্য কৰক"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"ডিছপ্লে’ সংযোগ কৰা হৈছে"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index b2ee455..ec4d712 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Ekran yazması"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Başlayın"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Dayandırın"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Birəlli rejim"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Kontrast"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standart"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Şarj edilir • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> sonra dolacaq"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"İcma təlimatını başlatmaq üçün sola sürüşdürün"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Vidcet redaktorunu açın"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Vidceti silin"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Vidcet əlavə edin"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Düymə <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Əsas səhifə"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Geri"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Yuxarı ox"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Aşağı ox"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Sol ox"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Sağ ox"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Mərkəz"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Boşluq"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Bildirişlər"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Klaviatura qısa yolları"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Klaviatura düzümünü dəyişin"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"və ya"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Axtarış sorğusunu silin"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Qısayollar"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Qısayollar axtarın"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Qısayol tapılmadı"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Daxiletmə"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Açıq tətbiqlər"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Cari tətbiq"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Axtarış nəticələri göstərilir"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Sistem qısayolları göstərilir"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Daxiletmə qısayolları göstərilir"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Tətbiqləri açan qısayollar göstərilir"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Cari tətbiq üçün qısayollar göstərilir"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Bildirişlərə baxın"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Skrinşot çəkin"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Qısayolları göstərin"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Ayarlarda defolt qeydlər tətbiqi ayarlayın"</string>
     <string name="install_app" msgid="5066668100199613936">"Tətbiqi quraşdırın"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Xarici displeyə əks etdirilsin?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Davam edən istənilən dual screen fəaliyyəti dayandırılacaq"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Displeyi əks etdirin"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"İmtina edin"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Displey qoşulub"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index ce734dc..1320d0a 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Snimanje ekrana"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Počnite"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Zaustavite"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Režim jednom rukom"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Kontrast"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standardno"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Puni se • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do kraja punjenja"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Prevucite ulevo da biste započeli zajednički vodič"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Otvori uređivač vidžeta"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Ukloni vidžet"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Dodaj vidžet"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Zameni korisnika"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"padajući meni"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Sve aplikacije i podaci u ovoj sesiji će biti izbrisani."</string>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Dugme <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Taster Početna"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Taster Nazad"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Strelica nagore"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Strelica nadole"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Strelica nalevo"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Strelica nadesno"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Taster sa centralnom strelicom"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Razmak"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Obaveštenja"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Tasterske prečice"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Promeni raspored tastature"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ili"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Obriši upit za pretragu"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Prečice"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Pretražite prečice"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nisu pronađene prečice"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Unos"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Otvaranje aplik"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Aktuelna aplik"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Prikazuju se rezultati pretrage"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Prikazuju se sistemske prečice"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Prikazuju se prečice za umetanje"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Prikazuju se prečice za otvaranje aplikacija"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Prikazuju se prečice za aktuelnu aplikaciju"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Prikaži obaveštenja"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Napravi snimak ekrana"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Prikaži prečice"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Podesite podrazumevanu aplikaciju za beleške u Podešavanjima"</string>
     <string name="install_app" msgid="5066668100199613936">"Instaliraj aplikaciju"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Želite li da preslikate na spoljnji ekran?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Biće zaustavljena svaka aktivnost dvojnog ekrana koja je u toku"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Preslikaj ekran"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Odbaci"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Ekran je povezan"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 74e46fc..570acc8 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Запіс экрана"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Пачаць"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Спыніць"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Рэжым кіравання адной рукой"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Кантрастнасць"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Стандартная"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ідзе зарадка • Поўны зарад праз <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Правядзіце пальцам па экране ўлева, каб азнаёміцца з дапаможнікам"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Адкрыць рэдактар віджэтаў"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Выдаліць віджэт"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Дадаць віджэт"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Кнопка <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Назад"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Стрэлка ўверх"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Стрэлка ўніз"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Стрэлка ўлева"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Стрэлка ўправа"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Цэнтр"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Прабел"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Апавяшчэнні"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Спалучэнні клавіш"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Пераключыць раскладку клавіятуры"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"або"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Ачысціць пошукавы запыт"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Ярлыкі"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Пошук ярлыкоў"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Ярлыкі не знойдзены"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Увод"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Адкрытыя праграмы"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Бягучая праграма"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Паказаны вынікі пошуку"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Паказаны сістэмныя спалучэнні клавіш"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Паказаны спалучэнні клавіш, звязаныя з уводам"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Паказаны спалучэнні клавіш для адкрыцця праграм"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Паказаны спалучэнні клавіш для бягучай праграмы"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Праглядзець апавяшчэнні"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Зрабіць здымак экрана"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Паказаць спалучэнні клавіш"</string>
@@ -1207,7 +1206,8 @@
     <string name="assistant_attention_content_description" msgid="4166330881435263596">"Выяўлена прысутнасць карыстальніка"</string>
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Задайце ў Наладах стандартную праграму для нататак"</string>
     <string name="install_app" msgid="5066668100199613936">"Усталяваць праграму"</string>
-    <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Адлюстраваць на знешнім дысплеі?"</string>
+    <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Адлюстраваць на знешнім дысплэі?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Функцыя адначасовага выкарыстання двух экранаў будзе спынена, калі яна актыўная"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Адлюстраваць дысплэй"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Закрыць"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Дысплэй падключаны"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 7a00ded..e52b793 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Запис на екрана"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Старт"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Стоп"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Режим за работа с една ръка"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Контраст"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Стандартен"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарежда се • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до пълно зареждане"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Прекарайте пръст наляво, за да стартирате общия урок"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Отваряне на редактора на приспособлението"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Премахване на приспособление"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Добавяне на приспособлението"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Бутон „<xliff:g id="NAME">%1$s</xliff:g>“"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Начало"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Назад"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Стрелка за нагоре"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Стрелка за надолу"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Стрелка за наляво"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Стрелка за надясно"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Център"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Интервал"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Известия"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Клавишни комбинации"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Превкл. на клавиат. подредба"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"или"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Изчистване на заявката за търсене"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Клавишни комбинации"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Търсете комбинации"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Няма клавишни комбинации"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Въвеждане"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Отворени прил."</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Текущо прилож."</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Показани са резултатите от търсенето"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Показани са системните преки пътища"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Показани са преките пътища за въвеждане"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Показани са преките пътища, които отварят приложения"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Показани са преките пътища за текущото приложение"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Преглед на известията"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Създаване на екранна снимка"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Показване на клавишните комбинации"</string>
@@ -1208,7 +1207,8 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Задайте стандартно приложение за бележки от настройките"</string>
     <string name="install_app" msgid="5066668100199613936">"Инсталиране на приложението"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Да се дублира ли на външния екран?"</string>
-    <string name="mirror_display" msgid="2515262008898122928">"Огледално копиране на дисплея"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Всяка текуща активност с функцията Dual Screen ще бъде спряна"</string>
+    <string name="mirror_display" msgid="2515262008898122928">"Дублиране на дисплея"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Отхвърляне"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Свързан е екран"</string>
     <string name="privacy_dialog_title" msgid="7839968133469098311">"Микрофон и камера"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 9954fbd..5e65830 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"স্ক্রিন রেকর্ড"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"শুরু করুন"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"বন্ধ করুন"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"এক হাতে ব্যবহার করার মোড"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"কনট্রাস্ট"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"স্ট্যান্ডার্ড"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • চার্জ হচ্ছে • পুরো চার্জ হতে আরও <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> সময় লাগবে"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"কমিউনিটি টিউটোরিয়াল চালু করতে বাঁদিকে সোয়াইপ করুন"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"উইজেট এডিটর খুলুন"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"উইজেট সরিয়ে দিন"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"উইজেট যোগ করুন"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"<xliff:g id="NAME">%1$s</xliff:g> বোতাম"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"হোম"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"ফিরুন"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"ঊর্ধমুখী তীরচিহ্ন"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"নিম্নমুখী তীরচিহ্ন"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"বাঁদিকের তীরচিহ্ন"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"ডানদিকের তীরচিহ্ন"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"কেন্দ্র"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Space"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"বিজ্ঞপ্তি"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"কীবোর্ড শর্টকাট"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"কীবোর্ড লে-আউট পাল্টান"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"অথবা"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"সার্চ কোয়েরি মুছুন"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"শর্টকাট"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"শর্টকাট সার্চ করুন"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"কোনও শর্টকার্ট পাওয়া যায়নি"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"ইনপুট"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"খুলে রাখা অ্যাপ"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"বর্তমান অ্যাপ"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"সার্চ ফলাফল দেখানো হচ্ছে"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"সিস্টেম শর্টকাট দেখানো হচ্ছে"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"ইনপুট শর্টকাট দেখানো হচ্ছে"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"যে শর্টকাট ব্যবহার করলে অ্যাপ খুলবে, সেগুলি দেখানো হচ্ছে"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"বর্তমান অ্যাপের জন্য শর্টকাট দেখানো হচ্ছে"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"বিজ্ঞপ্তি দেখুন"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"স্ক্রিনশট নিন"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"শর্টকাট দেখুন"</string>
@@ -1207,7 +1206,9 @@
     <string name="assistant_attention_content_description" msgid="4166330881435263596">"ব্যবহারকারীর উপস্থিতি শনাক্ত করা হয়েছে"</string>
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"\'সেটিংস\' থেকে ডিফল্ট নোট নেওয়ার অ্যাপ সেট করুন"</string>
     <string name="install_app" msgid="5066668100199613936">"অ্যাপ ইনস্টল করুন"</string>
-    <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"এক্সটার্নাল ডিসপ্লে আয়না?"</string>
+    <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"এক্সটার্নাল ডিসপ্লেতে মিরর করবেন?"</string>
+    <!-- no translation found for connected_display_dialog_dual_display_stop_warning (2917631104216376315) -->
+    <skip />
     <string name="mirror_display" msgid="2515262008898122928">"ডিসপ্লে দেখান"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"বাতিল করুন"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"ডিসপ্লে কানেক্ট করা আছে"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 041e3b6..f320d40 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Snimanje ekrana"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Započnite"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Zaustavite"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Način rada jednom rukom"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Kontrast"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standardno"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Punjenje • Potpuna napunjenost za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Prevucite ulijevo da pokrenete zajednički vodič"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Otvaranje uređivača vidžeta"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Uklanjanje vidžeta"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Dodajte vidžet"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Dugme <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Tipka za početak"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Nazad"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Strelica nagore"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Strelica nadolje"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Strelica ulijevo"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Strelica udesno"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Sredina"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Tipka za razmak"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Obavještenja"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Prečice tastature"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Zamijeni raspored tastature"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ili"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Brisanje upita za pretraživanje"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Prečice"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Pretraživanje prečica"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nisu pronađene prečice"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Unos"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Otvorene aplik."</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Trenutna aplik."</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Prikazivanje rezultata pretraživanja"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Prikazivanje prečica za sistem"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Prikazivanje prečica za unos"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Prikazivanje prečica koje otvaraju aplikacije"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Prikazivanje prečica za trenutnu aplikaciju"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Prikaz obavještenja"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Pravljenje snimka ekrana"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Prikaz prečica"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Postavite zadanu aplikaciju za bilješke u Postavkama"</string>
     <string name="install_app" msgid="5066668100199613936">"Instaliraj aplikaciju"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Preslikati na vanjski ekran?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Bilo koja trenutno pokrenuta aktivnost na dvostrukom ekranu se zaustaviti"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Preslikaj ekran"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Odbaci"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Ekran je povezan"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index eb652a1..a8e908f 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Gravació de pantalla"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Inicia"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Atura"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Mode d\'una mà"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Contrast"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Estàndard"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • S\'està carregant • Es completarà d\'aquí a <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Llisca cap a l\'esquerra per iniciar el tutorial de la comunitat"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Obre l\'editor de widgets"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Suprimeix un widget"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Afegeix un widget"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Canvia d\'usuari"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menú desplegable"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Totes les aplicacions i les dades d\'aquesta sessió se suprimiran."</string>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Botó <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Inici"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Enrere"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Fletxa amunt"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Fletxa avall"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Fletxa esquerra"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Fletxa dreta"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Centre"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Espai"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notificacions"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Tecles de drecera"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Canvia disposició de teclat"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"o"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Esborra la consulta de cerca"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Dreceres"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Cerca dreceres"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"No s\'ha trobat cap drecera"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Entrada"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Obre aplicacions"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Aplicació actual"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"S\'estan mostrant els resultats de la cerca"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"S\'estan mostrant les dreceres del sistema"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"S\'estan mostrant les dreceres d\'entrada"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"S\'estan mostrant les dreceres que obren aplicacions"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"S\'estan mostrant les dreceres per a l\'aplicació actual"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Mostra les notificacions"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Fes una captura de pantalla"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Mostra les dreceres"</string>
@@ -1207,8 +1206,9 @@
     <string name="assistant_attention_content_description" msgid="4166330881435263596">"S\'ha detectat la presència d\'usuaris"</string>
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Defineix l\'aplicació de notes predeterminada a Configuració"</string>
     <string name="install_app" msgid="5066668100199613936">"Instal·la l\'aplicació"</string>
-    <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Vols replicar-ho a la pantalla externa?"</string>
-    <string name="mirror_display" msgid="2515262008898122928">"Duplica la pantalla"</string>
+    <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Replicar a la pantalla externa?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Qualsevol activitat de pantalla dual que s\'estigui executant en aquests moments s\'aturarà"</string>
+    <string name="mirror_display" msgid="2515262008898122928">"Replica la pantalla"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Ignora"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Pantalla connectada"</string>
     <string name="privacy_dialog_title" msgid="7839968133469098311">"Micròfon i càmera"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 05a20c1..79aa029 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -52,7 +52,7 @@
     <string name="usb_debugging_always" msgid="4003121804294739548">"Vždy povolit z tohoto počítače"</string>
     <string name="usb_debugging_allow" msgid="1722643858015321328">"Povolit"</string>
     <string name="usb_debugging_secondary_user_title" msgid="7843050591380107998">"Ladění přes USB není povoleno"</string>
-    <string name="usb_debugging_secondary_user_message" msgid="1888835696965417845">"Uživatel aktuálně přihlášený k tomuto zařízení nemůže zapnout ladění přes USB. Chcete-li tuto funkci používat, přepněte na administrativního uživatele."</string>
+    <string name="usb_debugging_secondary_user_message" msgid="1888835696965417845">"Uživatel aktuálně přihlášený k tomuto zařízení nemůže zapnout ladění přes USB. Pokud chcete tuto funkci používat, přepněte na administrativního uživatele."</string>
     <string name="hdmi_cec_set_menu_language_title" msgid="1259765420091503742">"Změnit systémový jazyk na <xliff:g id="LANGUAGE">%1$s</xliff:g>?"</string>
     <string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Jiné zařízení požádalo o změnu systémového jazyka"</string>
     <string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Změnit jazyk"</string>
@@ -63,7 +63,7 @@
     <string name="wifi_debugging_always" msgid="2968383799517975155">"V této síti vždy povolit"</string>
     <string name="wifi_debugging_allow" msgid="4573224609684957886">"Povolit"</string>
     <string name="wifi_debugging_secondary_user_title" msgid="2493201475880517725">"Bezdrátové ladění není povoleno"</string>
-    <string name="wifi_debugging_secondary_user_message" msgid="9085779370142222881">"Uživatel aktuálně přihlášený k tomuto zařízení nemůže zapnout bezdrátové ladění. Chcete-li tuto funkci používat, přepněte na administrativního uživatele."</string>
+    <string name="wifi_debugging_secondary_user_message" msgid="9085779370142222881">"Uživatel aktuálně přihlášený k tomuto zařízení nemůže zapnout bezdrátové ladění. Pokud chcete tuto funkci používat, přepněte na administrativního uživatele."</string>
     <string name="usb_contaminant_title" msgid="894052515034594113">"Port USB je deaktivován"</string>
     <string name="usb_contaminant_message" msgid="7730476585174719805">"Kvůli ochraně vašeho zařízení před tekutinami a nečistotami je port USB zakázán a nerozpozná žádné příslušenství.\n\nAž bude opět bezpečné port USB použít, budeme vás informovat."</string>
     <string name="usb_port_enabled" msgid="531823867664717018">"Port USB může zjišťovat nabíječky a příslušenství"</string>
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Rekordér obrazovky"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Spustit"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Ukončit"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Režim jedné ruky"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Kontrast"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standardní"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíjení • Plně nabito za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Přejetím doleva spustíte komunitní výukový program"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Otevřít editor widgetů"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Odstranit widget"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Přidat widget"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Přepnout uživatele"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"rozbalovací nabídka"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Veškeré aplikace a data v této relaci budou vymazána."</string>
@@ -1197,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Výchozí aplikaci pro poznámky nastavíte v Nastavení"</string>
     <string name="install_app" msgid="5066668100199613936">"Nainstalovat aplikaci"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Zrcadlit na externí displej?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Běžící aktivita Dual Screen bude ukončena"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Zrcadlit displej"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Zavřít"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Displej připojen"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 1cfb005..b418ce8 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Skærmoptagelse"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Start"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Stop"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Enhåndstilstand"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Kontrast"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Oplader • Fuldt opladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Stryg mod venstre for at starte den fælles vejledning"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Åbn redigeringsværktøjet til widgets"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Fjern en widget"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Tilføj widget"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"<xliff:g id="NAME">%1$s</xliff:g>-knap"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Tilbage"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Pil op"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Pil ned"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Venstrepil"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Højrepil"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Midtertast"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Mellemrumstast"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notifikationer"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Tastaturgenveje"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Skift tastaturlayout"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"eller"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Ryd søgeforespørgsel"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Genveje"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Søg efter genveje"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Ingen genveje blev fundet"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Input"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Åbn apps"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Aktuel app"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Viser søgeresultater"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Viser systemgenveje"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Viser tastaturgenveje"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Viser genveje til at åbne apps"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Viser genveje til den aktuelle app"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Se notifikationer"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Tag et screenshot"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Vis genveje"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Angiv standardapp til noter i Indstillinger"</string>
     <string name="install_app" msgid="5066668100199613936">"Installer app"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Vil du spejle til ekstern skærm?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Al aktivitet, der i øjeblikket anvender funktioner til brug af to skærme, stoppes"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Spejl skærm"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Luk"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Skærmen er tilsluttet"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 5ce500d..a6bc4d4 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Bildschirmaufzeichnung"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Starten"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Beenden"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Einhandmodus"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Kontrast"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wird geladen • Voll in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Wische nach links, um das gemeinsame Tutorial zu starten"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Widget-Editor öffnen"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Widget entfernen"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Widget hinzufügen"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Nutzer wechseln"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"Pull-down-Menü"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle Apps und Daten in dieser Sitzung werden gelöscht."</string>
@@ -1197,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Standard-Notizen-App in den Einstellungen einrichten"</string>
     <string name="install_app" msgid="5066668100199613936">"App installieren"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Auf externen Bildschirm spiegeln?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Alle momentan ausgeführten Dual-Screen-Aktivitäten werden angehalten"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Bildschirm spiegeln"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Schließen"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Bildschirm verbunden"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index fe8a07f..dd6422b 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Εγγραφή οθόνης"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Έναρξη"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Διακοπή"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Λειτουργία ενός χεριού"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Αντίθεση"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Τυπική"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Φόρτιση • Πλήρης φόρτιση σε <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Σύρετε προς τα αριστερά για να ξεκινήσετε τον κοινόχρηστο οδηγό"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Άνοιγμα προγράμ. επεξεργασίας γραφικών στοιχείων"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Αφαίρεση ενός widget"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Προσθήκη γραφικού στοιχείου"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -1197,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Ορίστε την προεπιλεγμένη εφαρμογή σημειώσεων στις Ρυθμίσεις"</string>
     <string name="install_app" msgid="5066668100199613936">"Εγκατάσταση εφαρμογής"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Κατοπτρισμός σε εξωτερική οθόνη;"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Τυχόν τρέχουσα δραστηριότητα Dual Screen θα διακοπεί"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Κατοπτρισμός οθόνης"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Παράβλεψη"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Η οθόνη είναι συνδεδεμένη"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 30b03b2..46cdc0f 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -330,6 +330,9 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Screen record"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Start"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Stop"</string>
+    <string name="qs_record_issue_label" msgid="8166290137285529059">"Record issue"</string>
+    <string name="qs_record_issue_start" msgid="2979831312582567056">"Start"</string>
+    <string name="qs_record_issue_stop" msgid="3531747965741982657">"Stop"</string>
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"One-handed mode"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Contrast"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string>
@@ -402,8 +405,9 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swipe left to start the communal tutorial"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Open the widget editor"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Remove a widget"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Add Widget"</string>
+    <string name="button_to_remove_widget" msgid="3948204829181214098">"Remove"</string>
+    <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Add widget"</string>
+    <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Done"</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>
@@ -640,14 +644,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Button <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Back"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Up arrow"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Down arrow"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Left arrow"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Right arrow"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Centre"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Space"</string>
@@ -675,10 +675,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notifications"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Keyboard shortcuts"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Switch keyboard layout"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"or"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Clear search query"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Shortcuts"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Search shortcuts"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"No shortcuts found"</string>
@@ -686,16 +684,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Input"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Open apps"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Current app"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Showing search results"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Showing system shortcuts"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Showing input shortcuts"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Showing shortcuts that open apps"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Showing shortcuts for the current app"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"View notifications"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Take screenshot"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Show shortcuts"</string>
@@ -1208,6 +1201,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Set default notes app in Settings"</string>
     <string name="install_app" msgid="5066668100199613936">"Install app"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Mirror to external display?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Any dual screen activity currently running will be stopped"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Mirror display"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Dismiss"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Display connected"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index d349d6d..9acd568 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -330,6 +330,9 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Screen record"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Start"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Stop"</string>
+    <string name="qs_record_issue_label" msgid="8166290137285529059">"Record Issue"</string>
+    <string name="qs_record_issue_start" msgid="2979831312582567056">"Start"</string>
+    <string name="qs_record_issue_stop" msgid="3531747965741982657">"Stop"</string>
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"One-handed mode"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Contrast"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string>
@@ -402,8 +405,9 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swipe left to start the communal tutorial"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Open the widget editor"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Remove a widget"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Add Widget"</string>
+    <string name="button_to_remove_widget" msgid="3948204829181214098">"Remove"</string>
+    <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Add widget"</string>
+    <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Done"</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>
@@ -1197,6 +1201,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Set default notes app in Settings"</string>
     <string name="install_app" msgid="5066668100199613936">"Install app"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Mirror to external display?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Any dual screen activity currently running will be stopped"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Mirror display"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Dismiss"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Display connected"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 30b03b2..46cdc0f 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -330,6 +330,9 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Screen record"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Start"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Stop"</string>
+    <string name="qs_record_issue_label" msgid="8166290137285529059">"Record issue"</string>
+    <string name="qs_record_issue_start" msgid="2979831312582567056">"Start"</string>
+    <string name="qs_record_issue_stop" msgid="3531747965741982657">"Stop"</string>
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"One-handed mode"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Contrast"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string>
@@ -402,8 +405,9 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swipe left to start the communal tutorial"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Open the widget editor"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Remove a widget"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Add Widget"</string>
+    <string name="button_to_remove_widget" msgid="3948204829181214098">"Remove"</string>
+    <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Add widget"</string>
+    <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Done"</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>
@@ -640,14 +644,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Button <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Back"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Up arrow"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Down arrow"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Left arrow"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Right arrow"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Centre"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Space"</string>
@@ -675,10 +675,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notifications"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Keyboard shortcuts"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Switch keyboard layout"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"or"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Clear search query"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Shortcuts"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Search shortcuts"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"No shortcuts found"</string>
@@ -686,16 +684,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Input"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Open apps"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Current app"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Showing search results"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Showing system shortcuts"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Showing input shortcuts"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Showing shortcuts that open apps"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Showing shortcuts for the current app"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"View notifications"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Take screenshot"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Show shortcuts"</string>
@@ -1208,6 +1201,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Set default notes app in Settings"</string>
     <string name="install_app" msgid="5066668100199613936">"Install app"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Mirror to external display?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Any dual screen activity currently running will be stopped"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Mirror display"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Dismiss"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Display connected"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 30b03b2..46cdc0f 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -330,6 +330,9 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Screen record"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Start"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Stop"</string>
+    <string name="qs_record_issue_label" msgid="8166290137285529059">"Record issue"</string>
+    <string name="qs_record_issue_start" msgid="2979831312582567056">"Start"</string>
+    <string name="qs_record_issue_stop" msgid="3531747965741982657">"Stop"</string>
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"One-handed mode"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Contrast"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string>
@@ -402,8 +405,9 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swipe left to start the communal tutorial"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Open the widget editor"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Remove a widget"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Add Widget"</string>
+    <string name="button_to_remove_widget" msgid="3948204829181214098">"Remove"</string>
+    <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Add widget"</string>
+    <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Done"</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>
@@ -640,14 +644,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Button <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Back"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Up arrow"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Down arrow"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Left arrow"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Right arrow"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Centre"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Space"</string>
@@ -675,10 +675,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notifications"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Keyboard shortcuts"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Switch keyboard layout"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"or"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Clear search query"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Shortcuts"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Search shortcuts"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"No shortcuts found"</string>
@@ -686,16 +684,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Input"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Open apps"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Current app"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Showing search results"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Showing system shortcuts"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Showing input shortcuts"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Showing shortcuts that open apps"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Showing shortcuts for the current app"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"View notifications"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Take screenshot"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Show shortcuts"</string>
@@ -1208,6 +1201,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Set default notes app in Settings"</string>
     <string name="install_app" msgid="5066668100199613936">"Install app"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Mirror to external display?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Any dual screen activity currently running will be stopped"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Mirror display"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Dismiss"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Display connected"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 9b46442..9cd3014 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -330,6 +330,9 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‏‏‎‎‎‎‏‏‏‏‎‎‎‏‎‏‏‎‏‏‎‎‏‏‎‏‏‏‎‏‏‏‎‏‎‏‎‏‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎Screen record‎‏‎‎‏‎"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‏‏‎‏‏‎‏‎‏‎‎‎‏‏‎‎‎‏‏‎‎‎‎‏‎‏‎‏‎‎‎‏‏‏‎‎‏‏‏‎‏‏‏‎‎‎‏‎‏‏‎‎‏‎‎‏‎Start‎‏‎‎‏‎"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‏‎‎‎‎‎‎‏‎‎‎‏‎‏‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‎‎‏‎‏‎‎‎‎‎‎‎‎‏‏‏‎‏‎‏‏‏‎Stop‎‏‎‎‏‎"</string>
+    <string name="qs_record_issue_label" msgid="8166290137285529059">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‎‏‎‎‎‏‏‏‏‏‎‏‏‎‎‏‏‏‎‎‏‏‏‎‏‏‎‏‏‎‏‎‏‏‏‎‎‎‎‎‏‏‎‏‏‏‏‎‎‎‏‏‎Record Issue‎‏‎‎‏‎"</string>
+    <string name="qs_record_issue_start" msgid="2979831312582567056">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‏‎‏‎‏‏‎‏‎‎‏‏‏‏‏‎‎‏‏‎‎‏‎‏‎‎‏‏‏‏‏‎‏‎‎‎‏‎‎‎‏‏‏‏‎‎‏‎‎‏‎‎‏‎‎‎‎‎Start‎‏‎‎‏‎"</string>
+    <string name="qs_record_issue_stop" msgid="3531747965741982657">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‎‎‎‎‏‏‎‏‎‎‏‎‏‎‎‎‎‏‎‎‎‎‎‎‎‏‎‏‏‎‎‏‎‎‎‎‏‎‎‏‏‎‎‎‏‏‏‏‎‎‎‎‎‏‎Stop‎‏‎‎‏‎"</string>
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‏‎‎‎‏‎‎‏‎‏‎‎‎‏‎‎‎‏‏‏‎‎‎‏‏‎‏‏‎‏‏‎‏‎‎‏‎‏‏‎‎‎‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎One-handed mode‎‏‎‎‏‎"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‏‎‏‏‎‏‏‎‎‏‏‎‎‏‎‎‎‏‎‎‏‏‏‏‎‏‎‏‏‎‎‎‏‏‎‏‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‎‎‏‏‎Contrast‎‏‎‎‏‎"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‏‎‎‏‏‏‎‎‏‏‎‎‏‏‎‎‎‏‏‎‎‎‎‎‏‏‎‎‎‎‏‏‏‎‏‏‎‏‎‏‏‎‏‏‏‎‏‎‏‏‎‎‎‏‎‎‎‎Standard‎‏‎‎‏‎"</string>
@@ -402,8 +405,9 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‏‎‏‎‎‏‎‏‎‏‎‎‏‏‏‏‏‎‎‏‎‏‎‎‏‏‏‎‏‏‎‏‏‎‎‏‎‏‏‎‏‎‎‏‎‎‏‎‏‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%2$s</xliff:g>‎‏‎‎‏‏‏‎ • Charging • Full in ‎‏‎‎‏‏‎<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‏‏‏‏‎‏‏‏‏‎‏‎‎‎‎‎‎‎‏‏‏‏‎‎‎‎‎‎‎‏‏‎‏‏‏‎‎‏‎‎‏‎‏‎‏‏‏‏‏‎‏‎‏‏‎Swipe left to start the communal tutorial‎‏‎‎‏‎"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‎‏‏‎‏‏‏‎‎‎‎‎‎‎‏‎‎‏‎‏‎‏‎‏‎‏‎‎‏‏‎‎‏‎‏‎‎‎‎‏‎‏‎‎‎‏‎‎‏‎‎‎‎‎‎‎Open the widget editor‎‏‎‎‏‎"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‏‏‏‏‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‎‎‎‏‎‎‏‎‎‎‏‏‎‎‏‏‎‎‏‎‎‏‏‏‎‏‎‎‎‏‎‎‏‏‎‏‎Remove a widget‎‏‎‎‏‎"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‏‏‏‎‏‎‎‎‏‎‎‏‏‏‏‏‏‏‎‏‎‎‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‎‎‎‏‎‎‏‎‎‎‎‏‎‏‏‏‏‎Add Widget‎‏‎‎‏‎"</string>
+    <string name="button_to_remove_widget" msgid="3948204829181214098">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‏‏‎‎‏‎‏‎‏‏‎‏‎‏‏‏‎‏‎‏‏‏‏‏‏‎‏‎‎‏‏‏‏‏‎‏‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‎‎Remove‎‏‎‎‏‎"</string>
+    <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‎‎‏‏‎‎‏‏‎‎‏‏‏‏‏‎‎‎‎‎‏‎‏‏‎‏‏‏‎‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‎‎‏‎‎‎‏‎Add widget‎‏‎‎‏‎"</string>
+    <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‏‎‏‎‎‏‏‎‏‏‎‎‎‎‏‏‏‏‎‏‎‎‏‏‎‏‏‎‏‏‏‎‏‎‎‎‎‏‏‏‎‎‎‏‏‎‎‏‎‎‎‎‏‏‎Done‎‏‎‎‏‎"</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>
@@ -1197,6 +1201,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‎‎‎‏‏‏‏‎‎‎‏‏‏‏‏‎‎‎‏‏‎‏‎‏‎‏‏‏‏‎‏‏‏‏‎‏‏‏‏‎‎‏‏‏‎‏‎‏‎‎‎‎‎‏‎Set default notes app in Settings‎‏‎‎‏‎"</string>
     <string name="install_app" msgid="5066668100199613936">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‎‏‎‎‎‎‎‏‏‎‏‎‏‏‏‏‎‎‏‎‏‎‏‏‏‏‎‎‏‏‎‎‏‏‎‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‎‎‎‎‎Install app‎‏‎‎‏‎"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‎‎‏‎‏‎‏‏‏‏‎‏‎‎‎‎‎‎‏‎‎‎‏‏‎‎‏‎‎‎‏‏‏‏‎‎‎‏‏‎‎Mirror to external display?‎‏‎‎‏‎"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‎‏‎‎‎‎‎‎‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‎‎‏‎‏‎‏‎‎‎‏‏‏‏‏‏‏‎‏‏‎Any dual screen activity currently running will be stopped‎‏‎‎‏‎"</string>
     <string name="mirror_display" msgid="2515262008898122928">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‎‏‏‏‎‏‎‎‎‎‎‎‎‎‎‎‏‎‏‏‏‏‎‎‎‎‏‏‏‏‏‎‏‎‏‏‎‏‎‎‎‎‏‏‏‎‏‎‎‏‎‏‏‎‎‎‎‎Mirror display‎‏‎‎‏‎"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‎‎‏‏‏‏‎‎‎‎‎‎‎‎‎‏‏‎‏‎‏‏‎‎‎‎‎‏‏‏‏‎‎‏‏‎‎‎‏‎‏‎‎‏‎‎‏‏‏‏‎‏‎‏‎‏‎‎Dismiss‎‏‎‎‏‎"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‏‎‎‏‏‎‏‏‎‏‏‏‏‏‎‏‎‎‎‏‎‎‎‏‎‏‏‎‏‎‎‎‎‎‎‏‏‎‏‏‏‏‏‎‎‎‎‎‏‏‏‎‏‎Display connected‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 0bc807e..4be14e9 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Grabación de pantalla"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Iniciar"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Detener"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modo una mano"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Contraste"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Estándar"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando • Se completará en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Desliza el dedo a la izquierda para iniciar el instructivo comunal"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Abrir el editor de widget"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Quita el widget"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Agregar widget"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Cambiar usuario"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menú expandible"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Se eliminarán las aplicaciones y los datos de esta sesión."</string>
@@ -1196,7 +1206,8 @@
     <string name="assistant_attention_content_description" msgid="4166330881435263596">"Se detectó la presencia del usuario"</string>
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Configura la app de notas predeterminada en Configuración"</string>
     <string name="install_app" msgid="5066668100199613936">"Instalar app"</string>
-    <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"¿Quieres duplicar a la pantalla externa?"</string>
+    <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"¿Quieres duplicar en la pantalla externa?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Se detendrá cualquier actividad en la pantalla doble que se esté ejecutando en ese momento."</string>
     <string name="mirror_display" msgid="2515262008898122928">"Duplicar pantalla"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Descartar"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Pantalla conectada"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index f642386..5d88d64 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Grabar pantalla"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Iniciar"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Detener"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modo Una mano"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Contraste"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Estándar"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando • Carga completa en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Desliza hacia la izquierda para iniciar el tutorial de la comunidad"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Abrir editor de widgets"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Eliminar un widget"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Añadir widget"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Botón <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Inicio"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Atrás"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Flecha hacia arriba"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Flecha hacia abajo"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Flecha hacia la izquierda"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Flecha hacia la derecha"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Centro"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tabulador"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Espacio"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notificaciones"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Ver combinaciones de teclas"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Cambiar diseño del teclado"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"o"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Borrar la consulta de búsqueda"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Combinaciones de teclas"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Buscar combinaciones de teclas"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Ninguna encontrada"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Entrada"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Apps abiertas"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"App en uso"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Mostrando resultados de la búsqueda"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Mostrando combinaciones de teclas del sistema"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Mostrando combinaciones de teclas de entrada"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Mostrando combinaciones de teclas que abren aplicaciones"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Mostrando combinaciones de teclas de la aplicación actual"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Ver notificaciones"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Hacer captura de pantalla"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Mostrar accesos directos"</string>
@@ -1207,8 +1206,9 @@
     <string name="assistant_attention_content_description" msgid="4166330881435263596">"Se ha detectado la presencia de usuarios"</string>
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Configura la aplicación de notas predeterminada en Ajustes"</string>
     <string name="install_app" msgid="5066668100199613936">"Instalar aplicación"</string>
-    <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"¿Replicar en pantalla externa?"</string>
-    <string name="mirror_display" msgid="2515262008898122928">"Replicar pantalla"</string>
+    <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"¿Proyectar a pantalla externa?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Cualquier actividad de pantalla dual que se esté ejecutando en estos momentos se detendrá"</string>
+    <string name="mirror_display" msgid="2515262008898122928">"Proyectar pantalla"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Cerrar"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Pantalla conectada"</string>
     <string name="privacy_dialog_title" msgid="7839968133469098311">"Micrófono y cámara"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 8e9616f..258bd4d 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Ekraanisalvestus"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Alustage"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Peatage"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Ühekäerežiim"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Kontrastsus"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Tavaline"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laadimine • Täis <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> pärast"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Ühise õpetuse käivitamiseks pühkige vasakule"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Vidina redaktori avamine"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Eemalda vidin"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Lisa vidin"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Nupp <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Avakuva"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Tagasi"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Ülesnool"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Allanool"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Vasaknool"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Paremnool"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Keskele"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Tühik"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Märguanded"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Klaviatuuri otseteed"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Klaviatuuripaigutuse vahetus"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"või"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Otsingupäringu tühjendamine"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Otseteed"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Otseteede otsing"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Otseteid ei leitud"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Sisend"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Rakenduste avamine"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Praegune rakendus"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Kuvatakse otsingutulemused"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Kuvatakse süsteemi otseteed"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Kuvatakse sisendi otseteed"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Kuvatakse rakenduste avamise otseteed"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Kuvatakse praeguse rakenduse otseteed"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Märguannete vaatamine"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Ekraanipildi jäädvustamine"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Otseteede kuvamine"</string>
@@ -1208,7 +1207,8 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Määrake seadetes märkmete vaikerakendus."</string>
     <string name="install_app" msgid="5066668100199613936">"Installi rakendus"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Kas peegeldada välisekraanile?"</string>
-    <string name="mirror_display" msgid="2515262008898122928">"Ekraani peegeldamine"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Kõik praegu käimas olevad kahe ekraaniga tegevused peatatakse"</string>
+    <string name="mirror_display" msgid="2515262008898122928">"Peegelda ekraani"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Loobu"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Kuvar on ühendatud"</string>
     <string name="privacy_dialog_title" msgid="7839968133469098311">"Mikrofon ja kaamera"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index fe04218..54290f7 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Pantaila-grabaketa"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Hasi"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Gelditu"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Esku bakarreko modua"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Kontrastea"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Arrunta"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Kargatzen • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> guztiz kargatu arte"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Tutorial komuna hasteko, pasatu hatza ezkerrera"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Ireki widget-editorea"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Kendu widget bat"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Gehitu widgeta"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"<xliff:g id="NAME">%1$s</xliff:g> botoia"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Hasiera"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Atzera"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Gora egiteko gezi-tekla"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Behera egiteko gezi-tekla"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Ezkerrera egiteko gezi-tekla"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Eskuinera egiteko gezi-tekla"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Erdiratu"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Zuriunea"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Jakinarazpenak"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Lasterbideak"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Aldatu tekl. diseinua"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"edo"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Garbitu bilaketa-kontsulta"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Lasterbideak"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Bilatu lasterbideak"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Ez da aurkitu lasterbiderik"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Sarrera"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Irekitako aplikazioak"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Uneko aplikazioa"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Bilaketa-emaitzak daude ikusgai"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Sistemaren lasterbideak daude ikusgai"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Informazioa sartzeko lasterbideak daude ikusgai"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Aplikazioak irekitzen dituzten lasterbideak daude ikusgai"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Oraingo aplikaziorako lasterbideak daude ikusgai"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Ikusi jakinarazpenak"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Atera pantaila-argazki bat"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Erakutsi lasterbideak"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Ezarri oharren aplikazio lehenetsia ezarpenetan"</string>
     <string name="install_app" msgid="5066668100199613936">"Instalatu aplikazioa"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Kanpoko pantailan islatu nahi duzu?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Une honetan exekutatzen ari diren pantaila bikoitzeko jarduera guztiak geldituko dira"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Islatu pantaila"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Baztertu"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Konektatutako pantaila"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 2f17835..0305887 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"ضبط صفحه‌نمایش"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"شروع"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"متوقف کردن"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"حالت یک‌دستی"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"تضاد"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"استاندارد"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • درحال شارژ شدن • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> تا شارژ کامل"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"برای شروع آموزش گام‌به‌گام عمومی، تند به‌چپ بکشید"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"باز کردن ویرایشگر ابزارک"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"حذف ابزارک"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"افزودن ابزارک"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"دکمه <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"ابتدا"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"برگشت"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"پیکان رو به‌بالا"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"پیکان روبه‌پایین"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"پیکان چپ"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"پیکان راست"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"مرکز"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Space"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"اعلان‌ها"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"میان‌برهای صفحه‌کلید"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"تغییر جانمایی صفحه‌کلید"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"یا"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"پاک کردن پُرسمان جستجو"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"میان‌برها"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"جستجوی میان‌برها"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"میان‌بری پیدا نشد"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"ورودی"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"باز کردن برنامه‌ها"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"برنامه فعلی"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"درحال نمایش نتایج جستجو"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"درحال نمایش میان‌برهای سیستم"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"درحال نمایش میان‌برهای ورودی"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"درحال نمایش میان‌برهای باز کردن برنامه‌ها"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"درحال نمایش میان‌برهای برنامه کنونی"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"مشاهده اعلان‌ها"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"گرفتن نماگرفت"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"نمایش میان‌برها"</string>
@@ -1033,7 +1032,7 @@
     <string name="media_output_dialog_launch_app_text" msgid="1527413319632586259">"برای ارسال محتوای این جلسه، لطفاً برنامه را باز کنید."</string>
     <string name="media_output_dialog_unknown_launch_app_name" msgid="1084899329829371336">"برنامه ناشناس"</string>
     <string name="media_output_dialog_button_stop_casting" msgid="6581379537930199189">"توقف پخش محتوا"</string>
-    <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"دستگاه‌های دردسترس برای خروجی صدا."</string>
+    <string name="media_output_dialog_accessibility_title" msgid="4681741064190167888">"دستگاه‌های دردسترس برای خروجی صوتی."</string>
     <string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"میزان صدا"</string>
     <string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
     <string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"بلندگوها و نمایشگرها"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"برنامه پیش‌فرض یادداشت را در «تنظیمات» تنظیم کنید"</string>
     <string name="install_app" msgid="5066668100199613936">"نصب برنامه"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"در نمایشگر خارجی پخش شود؟"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"‏همه فعالیت‌های Dual Screen که درحال اجرا است متوقف خواهد شد"</string>
     <string name="mirror_display" msgid="2515262008898122928">"بازتاباندن صفحه‌نمایش"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"بستن"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"نمایشگر متصل شد"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index d1bd05b..ae92aaa 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Näytön tallennus"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Aloita"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Lopeta"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Yhden käden moodi"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Kontrasti"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Tavallinen"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Latautuu • Täynnä <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> päästä"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Aloita yhteisöesittely pyyhkäisemällä vasemmalle"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Avaa widgetien muokkaaja"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Poista widget"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Lisää widget"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Painike <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Takaisin"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Ylänuoli"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Alanuoli"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Vasen nuoli"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Oikea nuoli"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Keskelle"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Välilyönti"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Ilmoitukset"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Pikanäppäimet"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Vaihda näppäimistöasettelu"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"tai"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Tyhjennä hakulauseke"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Pikanäppäimet"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Hae pikanäppäimiä"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Pikanäppäimiä ei löytynyt"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Syöttötapa"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Avoimet"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Sovelluslista"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Näytetään hakutuloksia"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Näytetään järjestelmän pikanäppäimiä"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Näytetään pikanäppäimiä"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Näytetään sovellusten avaamiseen tarkoitettuja pikanäppäimiä"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Näytetään sovelluksen pikanäppäimiä"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Katso ilmoitukset"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Ota kuvakaappaus"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Näytä pikakuvakkeet"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Aseta oletusmuistiinpanosovellus Asetuksista"</string>
     <string name="install_app" msgid="5066668100199613936">"Asenna sovellus"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Peilataanko ulkoiselle näytölle?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Kaikki käynnissä oleva kahden näytön toiminta lopetetaan"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Peilaa näyttö"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Ohita"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Näyttö yhdistetty"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index bcf0e96..fc4c22f 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Enregistrement d\'écran"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Démarrer"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Arrêter"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Mode Une main"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Contraste"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Recharge en cours… • Se terminera dans <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Balayer l\'écran vers la gauche pour démarrer le tutoriel communautaire"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Ouvrir l\'éditeur de widget"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Retirez le widget"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Ajouter un widget"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Bouton <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Accueil"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Précédent"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Flèche vers le haut"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Flèche vers le bas"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Flèche vers la gauche"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Flèche vers la droite"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Centrer"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Espace"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notifications"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Raccourcis clavier"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Changer la disposition du clavier"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ou"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Effacez la requête de recherche"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Raccourcis"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Recherchez des raccourcis"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Aucun raccourci trouvé"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Entrée"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Ouvrir applis"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Appli actuelle"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Affichage des résultats de recherche en cours…"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Affichage des raccourcis du système en cours…"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Affichage des raccourcis d\'entrée en cours…"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Affichage des raccourcis qui ouvrent les applications en cours…"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Affichage des raccourcis de l\'application actuelle en cours…"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Afficher les notifications"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Prendre une capture d\'écran"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Afficher les raccourcis"</string>
@@ -1208,6 +1207,8 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Définir l\'application de prise de notes par défaut dans les Paramètres"</string>
     <string name="install_app" msgid="5066668100199613936">"Installer l\'application"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Dupliquer l\'écran sur un moniteur externe?"</string>
+    <!-- no translation found for connected_display_dialog_dual_display_stop_warning (2917631104216376315) -->
+    <skip />
     <string name="mirror_display" msgid="2515262008898122928">"Dupliquer l\'écran"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Fermer"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Écran connecté"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 6555f27..462ee6c 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Enregistrement de l\'écran"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Démarrer"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Arrêter"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Mode une main"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Contraste"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Recharge • Temps restant : <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Balayer vers la gauche pour démarrer le tutoriel collectif"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Ouvrir l\'éditeur de widgets"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Retirez un widget"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Ajouter le widget"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -1196,7 +1206,8 @@
     <string name="assistant_attention_content_description" msgid="4166330881435263596">"La présence de l\'utilisateur est détectée"</string>
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Définir une appli de notes par défaut dans les paramètres"</string>
     <string name="install_app" msgid="5066668100199613936">"Installer l\'appli"</string>
-    <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Mirroring sur écran externe ?"</string>
+    <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Dupliquer sur l\'écran externe ?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Toute activité en cours sur double écran sera interrompue."</string>
     <string name="mirror_display" msgid="2515262008898122928">"Dupliquer l\'écran"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Fermer"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Écran connecté"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 716fcf2..bfbb825 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Gravar pantalla"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Iniciar"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Deter"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modo dunha soa man"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Contraste"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Nivel estándar"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando • A carga completarase en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Pasa o dedo cara á esquerda para iniciar o titorial comunitario"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Abrir o editor de widgets"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Quitar un widget"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Engadir widget"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Botón <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Inicio"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Volver"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Frecha arriba"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Frecha abaixo"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Frecha esquerda"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Frecha dereita"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Centro"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Espazo"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notificacións"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Atallos de teclado"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Cambiar deseño do teclado"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ou"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Borrar a busca"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Atallos"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Buscar atallos"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Non se atoparon atallos"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Entrada"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Abrir aplicacións"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"App actual"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Mostrando resultados da busca"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Mostrando atallos do sistema"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Mostrando atallos de introdución de datos"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Mostrando atallos que abren aplicacións"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Mostrando atallos da aplicación actual"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Ver notificacións"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Facer captura de pantalla"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Mostrar atallos"</string>
@@ -1208,7 +1207,8 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Establece a aplicación de notas predeterminada en Configuración"</string>
     <string name="install_app" msgid="5066668100199613936">"Instalar aplicación"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Queres proxectar contido nunha pantalla externa?"</string>
-    <string name="mirror_display" msgid="2515262008898122928">"Replicar pantalla"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Deterase toda a actividade que se estea executando nunha pantalla dual"</string>
+    <string name="mirror_display" msgid="2515262008898122928">"Proxectar pantalla"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Pechar"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Pantalla conectada"</string>
     <string name="privacy_dialog_title" msgid="7839968133469098311">"Micrófono e cámara"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 8379865..4095f71 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"સ્ક્રીન રેકૉર્ડ"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"શરૂ કરો"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"રોકો"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"એક-હાથે વાપરો મોડ"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"કોન્ટ્રાસ્ટ"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"સ્ટૅન્ડર્ડ"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ચાર્જ થઈ રહ્યું છે • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>માં પૂરું ચાર્જ થઈ જશે"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"કૉમ્યુનલ ટ્યૂટૉરિઅલ શરૂ કરવા માટે ડાબે સ્વાઇપ કરો"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"વિજેટ એડિટર ખોલો"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"કોઈ વિજેટ કાઢી નાખો"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"વિજેટ ઉમેરો"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"બટન <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Back"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"ઉપરની ઍરો કી"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"નીચેની ઍરો કી"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"ડાબી ઍરો કી"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"જમણી ઍરો કી"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Center"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Space"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"નોટિફિકેશન"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"કીબોર્ડ શૉર્ટકટ"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"કીબોર્ડ લેઆઉટ સ્વિચ કરો"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"અથવા"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"શોધ ક્વેરી સાફ કરો"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"શૉર્ટકટ"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"શૉર્ટકટ શોધો"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"કોઈ શૉર્ટકટ મળ્યો નથી"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"ઇનપુટ"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"ઍપ ખોલો"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"હાલની ઍપ"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"શોધ પરિણામો બતાવી રહ્યાં છીએ"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"સિસ્ટમના શૉર્ટકટ બતાવી રહ્યાં છીએ"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"ઇનપુટ માટે શૉર્ટકટ બતાવી રહ્યાં છીએ"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"ઍપ ખોલનારા શૉર્ટકટ બતાવી રહ્યાં છીએ"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"હાલની ઍપ માટે શૉર્ટકટ બતાવી રહ્યાં છીએ"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"નોટિફિકેશન જુઓ"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"સ્ક્રીનશૉટ લો"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"શૉર્ટકટ બતાવો"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"સેટિંગમાં નોંધની ડિફૉલ્ટ ઍપ સેટ કરો"</string>
     <string name="install_app" msgid="5066668100199613936">"ઍપ ઇન્સ્ટૉલ કરો"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"શું બાહ્ય ડિસ્પ્લે પર મિરર કરીએ?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"હાલમાં ડ્યૂઅલ સ્ક્રીન પર ચાલી રહેલી કોઈપણ પ્રવૃત્તિ રોકવામાં આવશે"</string>
     <string name="mirror_display" msgid="2515262008898122928">"મિરર ડિસ્પ્લે"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"છોડી દો"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Display કનેક્ટેડ છે"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index ab01d2b..6db1f08 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"स्क्रीन रिकॉर्डर"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"शुरू करें"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"रोकें"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"वन-हैंडेड मोड"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"कंट्रास्ट"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"स्टैंडर्ड"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • चार्ज हो रहा है • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> में पूरा चार्ज हो जाएगा"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"कम्यूनिटी ट्यूटोरियल शुरू करने के लिए, बाईं ओर स्वाइप करें"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"विजेट एडिटर खोलें"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"विजेट को हटाएं"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"विजेट जोड़ें"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"बटन <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Back"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"अप ऐरो"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"डाउन ऐरो"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"लेफ़्ट ऐरो"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"राइट ऐरो"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"मध्य तीर"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Space"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"सूचनाएं"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"कीबोर्ड शॉर्टकट"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"कीबोर्ड लेआउट बदलें"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"या"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"सर्च क्वेरी साफ़ करें"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"शॉर्टकट"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"शॉर्टकट खोजें"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"कोई शॉर्टकट नहीं मिला"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"इनपुट"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"खुले हुए ऐप्लिकेशन"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"मौजूदा ऐप्लिकेशन"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"खोज के नतीजे दिखाए जा रहे हैं"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"सिस्टम के शॉर्टकट दिखाए जा रहे हैं"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"इनपुट के लिए शॉर्टकट दिखाए जा रहे हैं"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"ऐसे शॉर्टकट दिखाए जा रहे हैं जिनसे ऐप्लिकेशन खोले जा सकें"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"मौजूदा ऐप्लिकेशन के लिए शॉर्टकट दिखाए जा रहे हैं"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"सूचनाएं देखें"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"स्क्रीनशॉट लें"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"शॉर्टकट दिखाएं"</string>
@@ -1207,8 +1206,9 @@
     <string name="assistant_attention_content_description" msgid="4166330881435263596">"उपयोगकर्ता की मौजूदगी का पता लगाया गया"</string>
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"सेटिंग में जाकर, नोट लेने की सुविधा देने वाले ऐप्लिकेशन को डिफ़ॉल्ट के तौर पर सेट करें"</string>
     <string name="install_app" msgid="5066668100199613936">"ऐप्लिकेशन इंस्टॉल करें"</string>
-    <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"बाहरी डिसप्ले को अन्य डिवाइस पर दिखाना है?"</string>
-    <string name="mirror_display" msgid="2515262008898122928">"मिरर डिसप्ले"</string>
+    <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"क्या आपको किसी बाहरी डिवाइस पर डिसप्ले करना है?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"ड्यूअल स्क्रीन पर चल रही गतिविधि बंद हो जाएगी"</string>
+    <string name="mirror_display" msgid="2515262008898122928">"डिसप्ले करें"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"खारिज करें"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"डिसप्ले कनेक्ट किया गया"</string>
     <string name="privacy_dialog_title" msgid="7839968133469098311">"माइक्रोफ़ोन और कैमरा"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 7584e8a..d14f9a7 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Snimanje zaslona"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Početak"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Zaustavi"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Način rada jednom rukom"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Kontrast"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standardni"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • punjenje • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do napunjenosti"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Prijeđite prstom ulijevo da biste pokrenuli zajednički vodič"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Otvaranje alata za uređivanje widgeta"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Uklanjanje widgeta"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Dodaj widget"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Promjena korisnika"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"padajući izbornik"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Izbrisat će se sve aplikacije i podaci u ovoj sesiji."</string>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Tipka <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Početak"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Natrag"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Strelica prema gore"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Strelica prema dolje"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Strelica lijevo"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Strelica desno"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Sredina"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Razmaknica"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Obavijesti"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Tipkovni prečaci"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Promjena rasporeda tipkovnice"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ili"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Brisanje upita za pretraživanje"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Prečaci"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Pretražite prečace"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nema nijednog prečaca"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Unos"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Otvaranje aplikacija"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Trenutačna aplikacija"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Prikazuju se rezultati pretraživanja"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Prikazuju se prečaci sustava"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Prikazuju se prečaci za unos"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Prikazuju se prečaci koji otvaraju aplikacije"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Prikazuju se prečaci za trenutačnu aplikaciju"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Prikaži obavijesti"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Snimi zaslon"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Prikaži prečace"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Postavite zadanu aplikaciju za bilješke u postavkama"</string>
     <string name="install_app" msgid="5066668100199613936">"Instalacija"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Želite li zrcaliti na vanjski zaslon?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Sva aktivnost dvostrukog zaslona koja je u tijeku će se zaustaviti"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Zrcaljenje zaslona"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Odbaci"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Zaslon je povezan"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 85fe455..1c4e00f 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Képernyőrögzítés"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Indítás"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Leállítás"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Egykezes mód"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Kontraszt"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Normál"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Töltés • A teljes töltöttségig: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Csúsztasson gyorsan balra a közösségi útmutató elindításához"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"A modulszerkesztő megnyitása"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"A modul eltávolítása"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Modul hozzáadása"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"<xliff:g id="NAME">%1$s</xliff:g> gomb"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Kezdőképernyő"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Vissza"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Felfelé nyíl"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Lefelé nyíl"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Balra nyíl"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Jobbra nyíl"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Középre"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Szóköz"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Értesítések"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Billentyűkódok"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Billentyűzetkiosztás váltása"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"vagy"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Keresőkifejezés törlése"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Billentyűparancsok"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Billentyűparancs keresése"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nincs billentyűparancs"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Bevitel"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Futó appok"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Aktuális app"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Keresési találatok megjelenítve"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Rendszer-billentyűparancsok megjelenítve"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Beviteli billentyűparancsok megjelenítve"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Alkalmazásokat megnyitó billentyűparancsok megjelenítve"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"A jelenlegi alkalmazáshoz tartozó billentyűparancsok megjelenítve"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Értesítések megtekintése"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Képernyőkép készítése"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Parancsikonok megjelenítése"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Állítson be alapértelmezett jegyzetkészítő alkalmazást a Beállításokban"</string>
     <string name="install_app" msgid="5066668100199613936">"Alkalmazás telepítése"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Tükrözi a kijelzőt a külső képernyőre?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"A jelenleg futó kétképernyős tevékenységek le fognak állni"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Kijelző tükrözése"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Elvetés"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Kijelző csatlakoztatva"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 5be6a87..1cfed6d 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Էկրանի տեսագրում"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Սկսել"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Կանգնեցնել"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Մեկ ձեռքի ռեժիմ"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Կոնտրաստ"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Սովորական"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Լիցքավորում • Մնացել է <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Թերթեք ձախ՝ ուղեցույցը գործարկելու համար"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Բացել վիջեթների խմբագրիչը"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Հեռացնել վիջեթը"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Ավելացնել վիջեթ"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"<xliff:g id="NAME">%1$s</xliff:g> կոճակ"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Գլխավոր էջ"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Հետ"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Վերև սլաք"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Ներքև սլաք"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Ձախ սլաք"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Աջ սլաք"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Կենտրոն"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Բացատ"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Ծանուցումներ"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Ստեղնային դյուրանցումներ"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Դասավորության փոխարկում"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"կամ"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Ջնջել որոնման հարցումը"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Դյուրանցումներ"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Դյուրանցումների որոնում"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Դյուրանցումներ չեն գտնվել"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Ներածում"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Բաց հավելվածներ"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Այս հավելվածը"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Ցուցադրվում են որոնման արդյունքները"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Ցուցադրվում են համակարգի դյուրանցումները"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Ցուցադրվում են մուտքագրման դյուրանցումները"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Ցուցադրվում են հավելվածներ բացող դյուրանցումները"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Ցուցադրվում են ընթացիկ հավելվածի դյուրանցումները"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Դիտել ծանուցումները"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Սքրինշոթ անել"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Ցույց տալ դյուրանցումները"</string>
@@ -1208,6 +1207,8 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Կարգավորեք նշումների կանխադրված հավելված Կարգավորումներում"</string>
     <string name="install_app" msgid="5066668100199613936">"Տեղադրել հավելվածը"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Հայելապատճենե՞լ արտաքին էկրանին"</string>
+    <!-- no translation found for connected_display_dialog_dual_display_stop_warning (2917631104216376315) -->
+    <skip />
     <string name="mirror_display" msgid="2515262008898122928">"Հայելապատճենել էկրանը"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Փակել"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Էկրանը միացած է"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 8d372dc..65c7c1d 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Perekam layar"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Mulai"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Berhenti"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Mode satu tangan"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Kontras"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standar"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengisi daya • Penuh dalam waktu <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Geser ke kiri untuk memulai tutorial komunal"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Buka editor widget"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Hapus widget"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Tambahkan Widget"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Tombol <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Back"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Panah atas"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Panah bawah"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Panah kiri"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Panah kanan"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Center"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Space"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notifikasi"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Pintasan keyboard"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Ganti tata letak keyboard"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"atau"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Hapus kueri penelusuran"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Pintasan"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Pintasan penelusuran"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Tidak ditemukan pintasan"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Input"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Aplikasi yang terbuka"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Aplikasi saat ini"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Menampilkan hasil penelusuran"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Menampilkan pintasan sistem"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Menampilkan pintasan input"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Menampilkan pintasan yang membuka aplikasi"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Menampilkan pintasan untuk aplikasi saat ini"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Lihat notifikasi"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Ambil screenshot"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Tampilkan pintasan"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Setel aplikasi catatan default di Setelan"</string>
     <string name="install_app" msgid="5066668100199613936">"Instal aplikasi"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Cerminkan ke layar eksternal?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Aktivitas dua layar yang sedang berjalan akan dihentikan"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Cerminkan layar"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Tutup"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Layar terhubung"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 102e8b8..29b149d 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Skjáupptaka"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Hefja"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Stöðva"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Einhent stilling"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Birtuskil"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Staðlað"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Í hleðslu • Full hleðsla eftir <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Strjúktu til vinstri til að hefja samfélagsleiðsögnina"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Opna græjuritilinn"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Fjarlægja græju"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Bæta græju við"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Skipta um notanda"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"Fellivalmynd"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Öllum forritum og gögnum í þessari lotu verður eytt."</string>
@@ -1197,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Stilltu sjálfgefið glósuforrit í stillingunum"</string>
     <string name="install_app" msgid="5066668100199613936">"Setja upp forrit"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Spegla yfir á ytri skjá?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Virkni sem kann að vera í gangi á tveimur skjám verður stöðvuð"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Spegla skjá"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Hunsa"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Skjár tengdur"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index aad1e56..733b0b6 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Registrazione dello schermo"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Inizia"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Interrompi"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modalità a una mano"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Contrasto"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • In carica • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> alla ricarica completa"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Scorri a sinistra per iniziare il tutorial della community"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Apri l\'editor del widget"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Rimuovi un widget"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Aggiungi widget"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Cambio utente"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu a discesa"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Tutte le app e i dati di questa sessione verranno eliminati."</string>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Pulsante <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home page"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Indietro"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Freccia su"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Freccia giù"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Freccia sinistra"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Freccia destra"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Al centro"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Spazio"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notifiche"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Scorciatoie da tastiera"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Cambia layout della tastiera"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"oppure"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Cancella la query di ricerca"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Scorciatoie"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Cerca scorciatoie"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Scorciatoie non trovate"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Inserimento"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"App aperte"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"App corrente"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Visualizzazione dei risultati di ricerca"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Visualizzazione delle scorciatoie di sistema"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Visualizzazione delle scorciatoie degli ingressi"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Visualizzazione delle scorciatoie che aprono le app"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Visualizzazione delle scorciatoie per l\'app corrente"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Visualizza notifiche"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Acquisisci screenshot"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Mostra scorciatoie"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Imposta l\'app per le note predefinita nelle Impostazioni"</string>
     <string name="install_app" msgid="5066668100199613936">"Installa app"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Vuoi eseguire il mirroring al display esterno?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Qualsiasi attività in modalità Dual Screen in esecuzione viene interrotta"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Esegui il mirroring del display"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Chiudi"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Display collegato"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index bbfbe32..7072a32 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"הקלטת המסך"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"התחלה"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"עצירה"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"מצב שימוש ביד אחת"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"ניגודיות"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"רגילה"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • בטעינה • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> עד לסיום"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"אפשר להחליק שמאלה כדי להפעיל את המדריך המשותף"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"פתיחה של הכלי לעריכת ווידג\'טים"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"הסרה של ווידג\'ט"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"הוספת ווידג\'ט"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -1197,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"צריך להגדיר את אפליקציית ברירת המחדל לפתקים ב\'הגדרות\'"</string>
     <string name="install_app" msgid="5066668100199613936">"התקנת האפליקציה"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"לשקף למסך חיצוני?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"כל פעילות של מסך מפוצל שרצה כרגע תופסק"</string>
     <string name="mirror_display" msgid="2515262008898122928">"תצוגת מראה"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"סגירה"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"המסך מחובר"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index c8a0a54..ca68f66 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"スクリーン レコード"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"開始"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"停止"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"片手モード"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"コントラスト"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"標準"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 充電中 • フル充電まで <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"左にスワイプすると、コミュニティ チュートリアルが開始します"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"ウィジェット エディタを開く"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"ウィジェットを削除します"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"ウィジェットを追加"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"<xliff:g id="NAME">%1$s</xliff:g> ボタン"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"戻る"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"上矢印"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"下矢印"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"左矢印"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"右矢印"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"中央"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Space"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"通知"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"キーボード ショートカット"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"キーボード レイアウトの切り替え"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"または"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"検索クエリをクリア"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ショートカット"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"ショートカットの検索"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"ショートカットがありません"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"入力"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"開いているアプリ"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"現在のアプリ"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"検索結果を表示しています"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"システムのショートカットを表示しています"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"入力用のショートカットを表示しています"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"アプリを開くショートカットを表示しています"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"現在のアプリのショートカットを表示しています"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"お知らせを表示する"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"スクリーンショットを撮る"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"ショートカットを表示する"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"[設定] でデフォルトのメモアプリを設定してください"</string>
     <string name="install_app" msgid="5066668100199613936">"アプリをインストール"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"外部ディスプレイにミラーリングしますか?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"現在実行中のデュアル スクリーンのアクティビティは停止されます"</string>
     <string name="mirror_display" msgid="2515262008898122928">"ディスプレイをミラーリングする"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"閉じる"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"ディスプレイに接続しました"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index c6c4a57..cc6f282 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"ეკრანის ჩანაწერი"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"დაწყება"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"შეწყვეტა"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"ცალი ხელის რეჟიმი"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"კონტრასტი"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"სტანდარტული"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • იტენება • სრულ დატენვამდე <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"გადაფურცლეთ მარცხნივ, რათა დაიწყოთ საერთო სახელმძღვანელო"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"გახსენით ვიჯეტის რედაქტორი"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"ამოშალეთ ვიჯეტი"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"ვიჯეტის დამატება"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -1197,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"დააყენეთ ნაგულისხმევი შენიშვნების აპი პარამეტრებში"</string>
     <string name="install_app" msgid="5066668100199613936">"აპის ინსტალაცია"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"აირეკლოს გარე ეკრანზე?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"ორმაგ ეკრანზე ნებისმიერი მიმდინარე აქტივობა შეჩერდება"</string>
     <string name="mirror_display" msgid="2515262008898122928">"ეკრანის არეკვლა"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"დახურვა"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"ეკრანი დაკავშირებულია"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 2831cf9..2a9be81 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Экранды жазу"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Бастау"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Тоқтату"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Бір қолмен басқару режимі"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Контраст"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Стандартты режим"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарядталып жатыр. • Толуына <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> қалды."</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Ортақ оқулықты ашу үшін солға қарай сырғытыңыз."</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Виджет редакторын ашу"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Виджетті өшіру"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Виджет қосу"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"<xliff:g id="NAME">%1$s</xliff:g> түймесі"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Артқа"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Жоғары бағыт пернесі"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Төмен бағыт пернесі"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Сол бағыт пернесі"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Оң бағыт пернесі"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Орталық"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Бос орын"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Хабарландырулар"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Перне тіркесімдері"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Пернетақта форматын ауыстыру"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"немесе"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Іздеу сұрауын өшіру"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Перне тіркесімдері"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Перне тіркесімдерін іздеу"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Перне тіркесімдері табылмады."</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Енгізу"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Ашылған қолданбалар"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Ағымдағы қолданба"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Іздеу нәтижелерін көрсетеді."</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Жүйе жылдам пәрмендерін көрсетеді."</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Енгізу жылдам пәрмендерін көрсетеді."</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Қолданбаларды ашатын жылдам пәрмендерді көрсетеді."</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Қазіргі қолданбаға арналған жылдам пәрмендер көрсетіледі."</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Хабарландыруларды көру"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Скриншот жасау"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Жылдам пәрмендерді көрсету"</string>
@@ -1208,8 +1207,9 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Параметрлерден әдепкі жазба қолданбасын орнатыңыз."</string>
     <string name="install_app" msgid="5066668100199613936">"Қолданбаны орнату"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Сыртқы экран арқылы да көрсету керек пе?"</string>
-    <string name="mirror_display" msgid="2515262008898122928">"Айна дисплей"</string>
-    <string name="dismiss_dialog" msgid="2195508495854675882">"Қабылдамау"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Екі экранда қазір орындалып жатқан кез келген әрекет тоқтатылады."</string>
+    <string name="mirror_display" msgid="2515262008898122928">"Көрсету"</string>
+    <string name="dismiss_dialog" msgid="2195508495854675882">"Жабу"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Дисплей қосылды"</string>
     <string name="privacy_dialog_title" msgid="7839968133469098311">"Микрофон және камера"</string>
     <string name="privacy_dialog_summary" msgid="2458769652125995409">"Соңғы рет қолданбаның датчикті пайдалануы"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index aff6ef7..feb3af0 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"ការថត​វីដេអូ​អេក្រង់"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ចាប់ផ្ដើម"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"ឈប់"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"មុខងារប្រើដៃម្ខាង"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"កម្រិត​រំលេចពណ៌"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"ស្តង់ដារ"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • កំពុងសាកថ្ម • ពេញក្នុងរយៈពេល <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"អូសទៅឆ្វេង ដើម្បីចាប់ផ្ដើមមេរៀនសហគមន៍"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"បើកកម្មវិធីកែធាតុ​ក្រាហ្វិក"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"ដកធាតុក្រាហ្វិកចេញ"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"បញ្ចូលធាតុក្រាហ្វិក"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"ប៊ូតុង <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Back"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"ព្រួញ​ឡើង​លើ"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"ព្រួញ​ចុះ​ក្រោម"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"ព្រួញ​ទៅឆ្វេង"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"ព្រួញទៅ​ស្ដាំ"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Center"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Space"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"ការជូនដំណឹង"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"ផ្លូវកាត់ក្ដារចុច"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"ប្ដូរប្លង់ក្ដារចុច"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ឬ"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"សម្អាត​សំណួរ​ស្វែងរក"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ផ្លូវកាត់"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"ស្វែងរកផ្លូវកាត់"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"រកផ្លូវកាត់មិនឃើញទេ"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"បញ្ចូល"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"កម្មវិធីដែលបើក"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"កម្មវិធីបច្ចុប្បន្ន"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"កំពុងបង្ហាញលទ្ធផល​ស្វែងរក"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"កំពុងបង្ហាញផ្លូវកាត់ប្រព័ន្ធ"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"កំពុងបង្ហាញផ្លូវកាត់បញ្ចូល"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"កំពុងបង្ហាញផ្លូវកាត់ដែលបើកកម្មវិធី"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"កំពុងបង្ហាញផ្លូវកាត់សម្រាប់កម្មវិធីបច្ចុប្បន្ន"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"មើលការជូនដំណឹង"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"ថតរូប​អេក្រង់"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"បង្ហាញផ្លូវកាត់"</string>
@@ -1207,7 +1206,8 @@
     <string name="assistant_attention_content_description" msgid="4166330881435263596">"វត្តមានអ្នកប្រើប្រាស់ត្រូវបានចាប់ដឹង"</string>
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"កំណត់កម្មវិធីកំណត់ចំណាំលំនាំដើមនៅក្នុងការកំណត់"</string>
     <string name="install_app" msgid="5066668100199613936">"ដំឡើង​កម្មវិធី"</string>
-    <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"បញ្ចាំងទៅ​ឧបករណ៍បញ្ចាំង​ខាងក្រៅឬ?"</string>
+    <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"បញ្ចាំងទៅ​ផ្ទាំងអេក្រង់​ខាងក្រៅឬ?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"បច្ចុប្បន្ន រាល់សកម្មភាពអេក្រង់ទ្វេដែលកំពុងដំណើរការនឹងត្រូវបានបញ្ឈប់"</string>
     <string name="mirror_display" msgid="2515262008898122928">"បញ្ចាំងទៅផ្ទាំងអេក្រង់"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"ច្រានចោល"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"ផ្ទាំងអេក្រង់ត្រូវបានភ្ជាប់"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 5be72d8..fa35189 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡ್"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ಪ್ರಾರಂಭಿಸಿ"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"ನಿಲ್ಲಿಸಿ"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"ಒಂದು ಕೈ ಮೋಡ್"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"ಕಾಂಟ್ರಾಸ್ಟ್‌‌"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"ಪ್ರಮಾಣಿತ"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ದಲ್ಲಿ ಪೂರ್ಣಗೊಳ್ಳುತ್ತದೆ"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"ಸಮುದಾಯದ ಟ್ಯುಟೋರಿಯಲ್ ಅನ್ನು ಪ್ರಾರಂಭಿಸಲು ಎಡಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"ವಿಜೆಟ್ ಎಡಿಟರ್ ಅನ್ನು ತೆರೆಯಿರಿ"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"ವಿಜೆಟ್ ತೆಗೆದುಹಾಕಿ"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"ವಿಜೆಟ್ ಸೇರಿಸಿ"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"<xliff:g id="NAME">%1$s</xliff:g> ಬಟನ್"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"ಹಿಂದೆ"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"ಅಪ್ ಆ್ಯರೋ"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"ಡೌನ್ ಆ್ಯರೋ"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"ಲೆಫ್ಟ್ ಆ್ಯರೋ"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"ರೈಟ್ ಆ್ಯರೋ"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"ಮಧ್ಯ"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"ಸ್ಪೇಸ್"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"ನೋಟಿಫಿಕೇಶನ್‌ಗಳು"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"ಕೀಬೋರ್ಡ್ ಶಾರ್ಟ್‌ಕಟ್‌ಗಳು"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"ಕೀಬೋರ್ಡ್‌ ಲೇಔಟ್‌ ಬದಲಾಯಿಸಿ"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ಅಥವಾ"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"ಹುಡುಕಾಟದ ಪ್ರಶ್ನೆಯನ್ನು ತೆರವುಗೊಳಿಸಿ"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ಶಾರ್ಟ್‌ಕಟ್‌ಗಳು"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"ಶಾರ್ಟ್‌ಕಟ್‌ಗಳನ್ನು ಹುಡುಕಿ"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"ಯಾವುದೇ ಶಾರ್ಟ್‌ಕಟ್‌ಗಳಿಲ್ಲ"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"ಇನ್‌ಪುಟ್"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"ಆ್ಯಪ್‌ಗಳನ್ನು ತೆರೆಯಿರಿ"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"ಪ್ರಸ್ತುತ ಆ್ಯಪ್"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"ಹುಡುಕಾಟ ಫಲಿತಾಂಶಗಳನ್ನು ತೋರಿಸಲಾಗುತ್ತಿದೆ"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"ಸಿಸ್ಟಂ ಶಾರ್ಟ್‌ಕಟ್‌ಗಳನ್ನು ತೋರಿಸಲಾಗುತ್ತಿದೆ"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"ಇನ್‌ಪುಟ್ ಶಾರ್ಟ್‌ಕಟ್‌ಗಳನ್ನು ತೋರಿಸಲಾಗುತ್ತಿದೆ"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"ಆ್ಯಪ್‌ಗಳನ್ನು ತೆರೆಯುವ ಶಾರ್ಟ್‌ಕಟ್‌ಗಳನ್ನು ತೋರಿಸಲಾಗುತ್ತಿದೆ"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"ಪ್ರಸ್ತುತ ಆ್ಯಪ್‌ಗಾಗಿ ಶಾರ್ಟ್‌ಕಟ್‌ಗಳನ್ನು ತೋರಿಸಲಾಗುತ್ತಿದೆ"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"ನೋಟಿಫಿಕೇಶನ್‌ಗಳನ್ನು ವೀಕ್ಷಿಸಿ"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ತೆಗೆದುಕೊಳ್ಳಿ"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"ಶಾರ್ಟ್‌ಕಟ್‌ಗಳನ್ನು ತೋರಿಸಿ"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ ಡೀಫಾಲ್ಟ್ ಟಿಪ್ಪಣಿಗಳ ಆ್ಯಪ್ ಅನ್ನು ಸೆಟ್ ಮಾಡಿ"</string>
     <string name="install_app" msgid="5066668100199613936">"ಆ್ಯಪ್ ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಿ"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"ಬಾಹ್ಯ ಡಿಸ್‌ಪ್ಲೇಗೆ ಪ್ರತಿಬಿಂಬಿಸಬೇಕೆ?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"ಪ್ರಸ್ತುತ ಚಾಲನೆಯಲ್ಲಿರುವ ಯಾವುದೇ ಡ್ಯುಯಲ್ ಸ್ಕ್ರೀನ್ ಚಟುವಟಿಕೆಯನ್ನು ನಿಲ್ಲಿಸಲಾಗುತ್ತದೆ"</string>
     <string name="mirror_display" msgid="2515262008898122928">"ಮಿರರ್ ಡಿಸ್‌ಪ್ಲೇ"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"ವಜಾಗೊಳಿಸಿ"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"ಡಿಸ್‌ಪ್ಲೇ ಕನೆಕ್ಟ್ ಆಗಿದೆ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 71c0a35..3ccbed3 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"화면 녹화"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"시작"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"중지"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"한 손 사용 모드"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"대비"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"표준"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 충전 중 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> 후 충전 완료"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"공동 튜토리얼을 시작하려면 왼쪽으로 스와이프하세요"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"위젯 편집기 열기"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"위젯 삭제"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"위젯 추가"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"<xliff:g id="NAME">%1$s</xliff:g> 버튼"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"뒤로"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"위쪽 화살표"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"아래쪽 화살표"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"왼쪽 화살표"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"오른쪽 화살표"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"중앙"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Space"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"알림"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"단축키"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"키보드 레이아웃 전환"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"또는"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"검색어 삭제"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"단축키"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"단축키 검색"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"단축키 없음"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"입력"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"열린 앱"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"현재 앱"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"검색 결과 표시"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"시스템 바로가기 표시"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"입력 바로가기 표시"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"앱 열기 바로가기 표시"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"현재 앱 바로가기 표시"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"알림 보기"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"스크린샷 촬영"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"단축키 표시"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"설정에서 기본 메모 앱 설정"</string>
     <string name="install_app" msgid="5066668100199613936">"앱 설치"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"외부 디스플레이로 미러링하시겠습니까?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"실행 중인 모든 듀얼 화면이 중지됩니다."</string>
     <string name="mirror_display" msgid="2515262008898122928">"디스플레이 미러링"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"닫기"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"디스플레이 연결됨"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 6276160..76d3809 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Экранды жаздыруу"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Баштадык"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Токтотуу"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Бир кол режими"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Контраст"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Кадимки"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Кубатталууда • Толгонго чейин <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> калды"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Жалпы үйрөткүчтү иштетүү үчүн солго сүрүңүз"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Виджет түзөткүчтү ачуу"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Виджетти өчүрүү"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Виджет кошуу"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"<xliff:g id="NAME">%1$s</xliff:g> баскычы"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Башкы бет"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Артка"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Өйдө жебе"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Ылдый жебе"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Солго жебе"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Оңго жебе"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Ортолотуу"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Боштук"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Билдирмелер"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Ыкчам баскычтар"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Баскычтоп калыбын которуштуруу"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"же"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Изделген суроону тазалоо"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Ыкчам баскычтар"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Ыкчам баскычтарды издөө"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Ыкчам баскычтар жок"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Киргизүү"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Ачык колдон-лор"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Учурдагы кол-мо"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Табылган нерселер көрсөтүлүүдө"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Тутумдун ыкчам баскычтары көрсөтүлүүдө"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Киргизүү үчүн ыкчам баскычтар көрсөтүлүүдө"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Колдонмолорду ачкан ыкчам баскычтар көрсөтүлүүдө"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Учурдагы колдонмонун ыкчам баскычтары көрсөтүлүүдө"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Билдирмелерди көрүү"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Скриншот тартуу"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Ыкчам баскычтарды көрсөтүү"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Параметрлерден демейки кыска жазуулар колдонмосун тууралаңыз"</string>
     <string name="install_app" msgid="5066668100199613936">"Колдонмону орнотуу"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Тышкы экранга чыгарасызбы?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Учурда иштеп жаткан бардык кош экран аракеттери токтотулат"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Тышкы экран"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Жабуу"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Экран туташтырылды"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 5da52a5..cf5ef3a 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"ບັນທຶກໜ້າຈໍ"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ເລີ່ມ"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"ຢຸດ"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"ໂໝດມືດຽວ"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"ຄອນທຣາສ"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"ມາດຕະຖານ"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ກຳລັງສາກໄຟ • ຈະເຕັມໃນອີກ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"ປັດຊ້າຍເພື່ອເລີ່ມບົດແນະນຳສ່ວນກາງ"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"ເປີດຕົວແກ້ໄຂວິດເຈັດ"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"ລຶບວິດເຈັດອອກ"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"ເພີ່ມວິດເຈັດ"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"ປຸ່ມ <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"ກັບຄືນ"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"ລູກສອນຂຶ້ນ"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"ລູກສອນລົງ"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"ລູກສອນຊ້າຍ"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"ລູກສອນຂວາ"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"ເຄິ່ງກາງ"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Space"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"ການແຈ້ງເຕືອນ"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"ປຸ່ມລັດແປ້ນພິມ"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"ສະຫຼັບແປ້ນພິມ"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ຫຼື"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"ລຶບລ້າງຄຳຊອກຫາ"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ທາງລັດ"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"ທາງລັດການຊອກຫາ"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"ບໍ່ພົບທາງລັດ"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"ການປ້ອນຂໍ້ມູນ"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"ແອັບທີ່ເປີດຢູ່"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"ແອັບປັດຈຸບັນ"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"ສະແດງຜົນການຊອກຫາ"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"ສະແດງທາງລັດລະບົບ"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"ສະແດງທາງລັດອິນພຸດ"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"ສະແດງທາງລັດທີ່ເປີດແອັບ"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"ສະແດງທາງລັດສຳລັບແອັບປັດຈຸບັນ"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"ເບິ່ງການແຈ້ງເຕືອນ"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"ຖ່າຍຮູບໜ້າຈໍ"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"ສະແດງທາງລັດ"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"ຕັ້ງຄ່າແອັບຈົດບັນທຶກເລີ່ມຕົ້ນໃນການຕັ້ງຄ່າ"</string>
     <string name="install_app" msgid="5066668100199613936">"ຕິດຕັ້ງແອັບ"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"ສາຍໃສ່ຈໍສະແດງຜົນພາຍນອກບໍ?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"ການເຄື່ອນໄຫວໃດກໍຕາມທີ່ກຳລັງດຳເນີນການຢູ່ Dual Screen ຈະຢຸດລົງ"</string>
     <string name="mirror_display" msgid="2515262008898122928">"ຈໍສະແດງຜົນແບບສະທ້ອນ"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"ປິດໄວ້"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"ເຊື່ອມຕໍ່ຈໍແລ້ວ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 34c06bd..ddad0be 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Ekrano įrašas"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Pradėti"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Stabdyti"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Vienos rankos režimas"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Kontrastas"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Įprastas"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Įkraunama • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> iki visiško įkrovimo"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Perbraukite kairėn, paleistumėte bendruomenės mokomąją medžiagą"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Atidaryti valdiklio redagavimo programą"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Pašalinti valdiklį"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Pridėti valdiklį"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Perjungti naudotoją"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"išplečiamasis meniu"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Bus ištrintos visos šios sesijos programos ir duomenys."</string>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Mygtukas <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Pagrindinis"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Atgal"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Rodyklė aukštyn"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Rodyklė žemyn"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Rodyklė kairėn"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Rodyklė dešinėn"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Centras"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Tarpas"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Pranešimai"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Spartieji klavišai"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Perjungti klaviat. išdėstymą"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"arba"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Išvalyti paieškos užklausą"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Spartieji klavišai"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Ieškoti sparčiųjų klavišų"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Sparčiųjų klavišų nerasta"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Įvestis"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Atidar. progr."</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Esama programa"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Rodomi paieškos rezultatai"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Rodomi sistemos spartieji klavišai"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Rodomi įvesties spartieji klavišai"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Rodomi programas atidarantys spartieji klavišai"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Rodomi dabartinės programos spartieji klavišai"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Peržiūrėti pranešimus"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Padaryti ekrano kopiją"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Rodyti sparčiuosius klavišus"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Nustatykite numatytąją užrašų programą Nustatymuose"</string>
     <string name="install_app" msgid="5066668100199613936">"Įdiegti programą"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Bendrinti ekrano vaizdą išoriniame ekrane?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Bet kokia šiuo metu vykdoma dvigubo ekrano veikla bus sustabdyta"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Bendrinti ekrano vaizdą"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Atsisakyti"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Ekranas prijungtas"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 66933bc..707c656 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Ekrāna ierakstīšana"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Sākt"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Apturēt"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Vienas rokas režīms"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Kontrasts"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standarta"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Notiek uzlāde • Laiks līdz pilnai uzlādei: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Velciet pa kreisi, lai palaistu kopienas pamācību."</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Atvērt logrīku redaktoru"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Noņemt logrīku"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Pievienot logrīku"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Poga <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Sākumvietas taustiņš"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Atpakaļ"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Augšupvērstā bultiņa"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Lejupvērstā bultiņa"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Kreisā bultiņa"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Labā bultiņa"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Centrā"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Atstarpe"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Paziņojumi"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Īsinājumtaustiņi"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Mainīt tastatūras izkārtojumu"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"vai"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Notīrīt meklēšanas vaicājumu"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Īsinājumtaustiņi"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Meklēt īsinājumtaustiņus"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nav atrasti"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Ievade"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Atvērtās"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Pašreizējā"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Tiek rādīti meklēšanas rezultāti"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Tiek rādīti sistēmas īsinājumtaustiņi"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Tiek rādīti ievades īsinājumtaustiņi"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Tiek rādīti īsinājumtaustiņi lietotņu atvēršanai"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Tiek rādīti īsinājumtaustiņi pašreizējai lietotnei"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Skatīt paziņojumus"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Izveidot ekrānuzņēmumu"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Rādīt īsinājumtaustiņus"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Iestatījumos iestatiet noklusējuma piezīmju lietotni."</string>
     <string name="install_app" msgid="5066668100199613936">"Instalēt lietotni"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Vai spoguļot ārējā displejā?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Visas pašlaik aktīvās divu ekrānu darbības tiks apturētas"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Spoguļot displeju"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Nerādīt"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Pievienots displejs"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 44f6e0c..24cd49a 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Снимање екран"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Започни"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Сопри"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Режим со една рака"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Контраст"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Стандарден"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Се полни • Полна по <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Повлечете налево за да го започнете заедничкото упатство"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Го отвора уредникот на виџети"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Отстранува виџет"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Додајте виџет"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Копче <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home-копче"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Назад"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Стрелка нагоре"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Стрелка надолу"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Стрелка налево"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Стрелка надесно"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Центар"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Space"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Известувања"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Кратенки на тастатурата"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Промени јазик на тастатура"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"или"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Бришење поим за пребарување"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Кратенки"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Пребарувајте кратенки"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Не се пронајдени кратенки"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Внесување"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Отворени аплик."</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Тековна аплик."</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Се прикажуваат резултати од пребарувањето"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Се прикажуваат системски кратенки"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Се прикажуваат кратенки за внесување"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Се прикажуваат кратенки за отворање апликации"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Се прикажуваат кратенки за тековната апликација"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Прегледајте ги известувањата"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Направете слика од екранот"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Прикажи кратенки"</string>
@@ -1207,7 +1206,8 @@
     <string name="assistant_attention_content_description" msgid="4166330881435263596">"Откриено е присуство на корисник"</string>
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Поставете стандардна апликација за белешки во „Поставки“"</string>
     <string name="install_app" msgid="5066668100199613936">"Инсталирајте ја апликацијата"</string>
-    <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Да се синхронизира на надворешниот екран?"</string>
+    <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Да се преслика на надворешниот екран?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Секоја активност што тековно се извршува на Dual Screen ќе се сопре"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Пресликај екран"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Отфрли"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Екранот е поврзан"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 4644fa5..1f153c5 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"സ്‌ക്രീൻ റെക്കോർഡ്"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ആരംഭിക്കുക"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"നിര്‍ത്തുക"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"ഒറ്റക്കൈ മോഡ്"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"കോൺട്രാസ്റ്റ്"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"സ്‌റ്റാൻഡേർഡ്"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ചാർജ് ചെയ്യുന്നു • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-ൽ പൂർത്തിയാകും"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"കമ്മ്യൂണൽ ട്യൂട്ടോറിയൽ ആരംഭിക്കാൻ ഇടത്തോട്ട് സ്വൈപ്പ് ചെയ്യുക"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"വിജറ്റ് എഡിറ്റർ തുറക്കുക"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"വിജറ്റ് നീക്കം ചെയ്യുക"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"വിജറ്റ് ചേർക്കുക"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"ബട്ടൺ <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"ഹോം"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"ബാക്ക്"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"മുകളിലേക്കുള്ള അമ്പടയാളം"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"താഴേക്കുള്ള അമ്പടയാളം"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"ഇടത് അമ്പടയാളം"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"വലത് അമ്പടയാളം"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"മധ്യം"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"TAB"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"സ്പെയ്സ്"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"അറിയിപ്പുകൾ"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"കീബോർഡ് കുറുക്കുവഴികൾ"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"കീബോർഡ് ലേഔട്ട് മാറുക"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"അല്ലെങ്കിൽ"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"തിരയൽ ചോദ്യം മായ്‌ക്കുക"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"കുറുക്കുവഴികൾ"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"കുറുക്കുവഴികൾ തിരയുക"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"കുറുക്കുവഴി കണ്ടെത്തിയില്ല"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"ഇൻപുട്ട്"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"തുറന്ന ആപ്പുകൾ"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"നിലവിലെ ആപ്പ്"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"തിരയൽ ഫലങ്ങൾ കാണിക്കുന്നു"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"സിസ്‌റ്റം കുറുക്കുവഴികൾ കാണിക്കുന്നു"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"ഇൻപുട്ട് കുറുക്കുവഴികൾ കാണിക്കുന്നു"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"ആപ്പുകൾ തുറക്കുന്ന കുറുക്കുവഴികൾ കാണിക്കുന്നു"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"നിലവിലെ ആപ്പിനുള്ള കുറുക്കുവഴികൾ കാണിക്കുന്നു"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"അറിയിപ്പുകൾ കാണുക"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"സ്ക്രീൻഷോട്ട് എടുക്കുക"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"കുറുക്കുവഴികൾ കാണിക്കുക"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"ക്രമീകരണത്തിൽ കുറിപ്പുകൾക്കുള്ള ഡിഫോൾട്ട് ആപ്പ് സജ്ജീകരിക്കുക"</string>
     <string name="install_app" msgid="5066668100199613936">"ആപ്പ് ഇൻസ്റ്റാൾ ചെയ്യൂ"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"ബാഹ്യ ഡിസ്‌പ്ലേയിലേക്ക് മിറർ ചെയ്യണോ?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"നിലവിൽ റൺ ചെയ്യുന്ന ഏതൊരു ഡ്യുവൽ സ്ക്രീൻ ആക്റ്റിവിറ്റിയും നിർത്തും"</string>
     <string name="mirror_display" msgid="2515262008898122928">"മിറർ ഡിസ്‌പ്ലേ"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"ഡിസ്‌മിസ് ചെയ്യുക"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"ഡിസ്പ്ലേ കണക്റ്റ് ചെയ്തിരിക്കുന്നു"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 217eeb1..91f7180 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Дэлгэцийн үйлдэл бичих"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Эхлүүлэх"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Зогсоох"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Нэг гарын горим"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Ялгарал"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Стандарт"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Цэнэглэж байна • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-н дараа дүүрнэ"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Нийтийн практик хичээлийг эхлүүлэхийн тулд зүүн тийш шударна уу"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Виджет засварлагчийг нээх"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Виджетийг хасах"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Виджет нэмэх"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"<xliff:g id="NAME">%1$s</xliff:g> товчлуур"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Нүүр хуудас"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Буцах"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Дээш сум"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Доош сум"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Зүүн сум"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Баруун сум"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Гол хэсэг"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Зай"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Мэдэгдэл"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Гарын товчлол"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Гарын бүдүүвч рүү сэлгэх"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"эсвэл"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Хайлтын асуулгыг арилгах"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Товчлолууд"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Товчлолууд хайх"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Ямар ч товчлол олдсонгүй"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Оролт"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Нээлттэй аппууд"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Одоогийн апп"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Хайлтын илэрцүүдийг харуулж байна"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Системийн товчлолуудыг харуулж байна"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Оролтын товчлолуудыг харуулж байна"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Аппуудыг нээдэг товчлолуудыг харуулж байна"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Одоогийн аппад товчлолууд харуулж байна"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Мэдэгдлийг харах"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Дэлгэцийн агшныг авах"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Товчлол харуулах"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Тохиргоонд тэмдэглэлийн өгөгдмөл апп тохируулна уу"</string>
     <string name="install_app" msgid="5066668100199613936">"Аппыг суулгах"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Гадны дэлгэцэд тусгал үүсгэх үү?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Одоо ажиллаж буй аливаа хос дэлгэцийн үйл ажиллагааг зогсооно"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Дэлгэцийн тусгал үүсгэх"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Хаах"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Дэлгэц холбогдсон"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index f768881..39e2c5c 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"स्क्रीन रेकॉर्ड"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"सुरू"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"थांबा"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"एकहाती मोड"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"कॉंट्रास्ट"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"साधारण"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • चार्ज होत आहे • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मध्ये पूर्ण होईल"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"सामुदायिक ट्यूटोरियल सुरू करण्यासाठी डावीकडे स्वाइप करा"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"विजेट संपादक उघडा"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"विजेट काढून टाका"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"विजेट जोडा"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"बटण <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"परत"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"अप अ‍ॅरो"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"डाउन अ‍ॅरो"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"लेफ्ट अ‍ॅरो"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"राइट अ‍ॅरो"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"मध्यवर्ती"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Space"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"सूचना"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"कीबोर्ड शॉर्टकट"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"कीबोर्ड लेआउट स्विच करा"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"किंवा"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"शोध क्वेरी साफ करा"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"शॉर्टकट"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"शॉर्टकट शोधा"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"एकही शॉर्टकट आढळला नाहीत"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"इनपुट"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"ॲप्स उघडा"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"सध्याचे अ‍ॅप"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"शोध परिणाम दाखवत आहे"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"सिस्टीम शॉर्टकट दाखवत आहे"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"इनपुट शॉर्टकट दाखवत आहे"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"ॲप्स उघडणारे शॉर्टकट दाखवत आहे"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"सद्य अ‍ॅपसाठी शॉर्टकट दाखवत आहे"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"सूचना पहा"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"स्क्रीनशॉट घ्या"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"शॉर्टकट दाखवा"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"सेटिंग्ज मध्ये डीफॉल्ट टिपा अ‍ॅप सेट करा"</string>
     <string name="install_app" msgid="5066668100199613936">"अ‍ॅप इंस्टॉल करा"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"बाह्य डिस्प्लेवर मिरर करायचे आहे का?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"सध्या सुरू असलेली कोणतीही ड्युअल स्क्रीन अ‍ॅक्टिव्हिटी थांबवली जाईल"</string>
     <string name="mirror_display" msgid="2515262008898122928">"डिस्प्ले मिरर करा"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"डिसमिस करा"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"डिस्प्ले कनेक्ट केला आहे"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index db53890..732a180 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Rakam skrin"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Mula"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Berhenti"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Mod sebelah tangan"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Kontras"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengecas • Penuh dalam masa <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Leret ke kiri untuk memulakan tutorial umum"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Buka editor widget"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Alih keluar widget"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Tambahkan Widget"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Tukar pengguna"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu tarik turun"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Semua apl dan data dalam sesi ini akan dipadam."</string>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Butang <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Skrin Utama"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Kembali"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Anak panah ke atas"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Anak panah ke bawah"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Anak panah ke kiri"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Anak panah ke kanan"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Tengah"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Space"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Pemberitahuan"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Pintasan Papan Kekunci"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Tukar reka letak papan kekunci"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"atau"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Kosongkan pertanyaan carian"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Pintasan"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Cari pintasan"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Tiada pintasan ditemukan"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Input"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Apl yang dibuka"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Apl semasa"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Memaparkan hasil carian"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Memaparkan pintasan sistem"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Memaparkan pintasan input"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Memaparkan pintasan yang membuka apl"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Memaparkan pintasan untuk apl semasa"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Lihat pemberitahuan"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Ambil tangkapan skrin"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Tunjukkan pintasan"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Tetapkan apl nota lalai dalam Tetapan"</string>
     <string name="install_app" msgid="5066668100199613936">"Pasang apl"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Paparkan pada paparan luaran?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Sebarang aktiviti dwiskrin yang sedang dijalankan akan dihentikan"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Segerakkan paparan"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Ketepikan"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Paparan disambungkan"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 6221ca1..069a833 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"စခရင် ရိုက်ကူးရန်"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"စတင်ရန်"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"ရပ်ရန်"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"လက်တစ်ဖက်သုံးမုဒ်"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"ဆန့်ကျင်ဘက်"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"ပုံမှန်"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • အားသွင်းနေသည် • အားပြည့်ရန် <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> လိုသည်"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"အများသုံးရှင်းလင်းပို့ချချက် စတင်ရန် ဘယ်သို့ပွတ်ဆွဲပါ"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"ဝိဂျက်တည်းဖြတ်စနစ် ဖွင့်ရန်"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"ဝိဂျက် ဖယ်ရှားရန်"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"ဝိဂျက် ထည့်ရန်"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"ခလုတ် <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"ပင်မ"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"နောက်သို့"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"အပေါ်ညွှန်မြား"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"အောက်ညွှန်မြား"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"ဘယ်ညွှန်မြား"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"ညာညွှန်မြား"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"ဌာန"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Space"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"အကြောင်းကြားချက်များ"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"ကီးဘုတ် ဖြတ်လမ်းများ"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"ကီးဘုတ်အပြင်အဆင် ပြောင်းခြင်း"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"သို့မဟုတ်"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"ရှာဖွေစာလုံး ရှင်းထုတ်ရန်"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ဖြတ်လမ်းလင့်ခ်များ"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"ဖြတ်လမ်းလင့်ခ်များ ရှာပါ"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"ဖြတ်လမ်းလင့်ခ် မတွေ့ပါ"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"စာရိုက်ခြင်း"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"ဖွင့်ထားသောအက်ပ်"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"လက်ရှိအက်ပ်"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"ရှာဖွေမှုရလဒ်များ ပြထားသည်"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"စနစ်ဖြတ်လမ်းလင့်ခ်များ ပြထားသည်"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"ထည့်သွင်းသည့် ဖြတ်လမ်းလင့်ခ်များ ပြထားသည်"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"အက်ပ်ဖွင့်သည့် ဖြတ်လမ်းလင့်ခ်များ ပြထားသည်"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"လက်ရှိအက်ပ်အတွက် ဖြတ်လမ်းလင့်ခ်များ ပြထားသည်"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"အကြောင်းကြားချက်များ ကြည့်ရန်"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"ဖန်သားပြင်ဓာတ်ပုံ ရိုက်ရန်"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"ဖြတ်လမ်းလင့်ခ်များ ပြပါ"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"ဆက်တင်များတွင် မူရင်းမှတ်စုများအက်ပ် သတ်မှတ်ပါ"</string>
     <string name="install_app" msgid="5066668100199613936">"အက်ပ် ထည့်သွင်းရန်"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"ပြင်ပဖန်သားပြင်သို့ စကရင်ပွားမလား။"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"လက်ရှိလုပ်ဆောင်နေသော Dual Screen လုပ်ဆောင်ချက်များ ရပ်သွားပါမည်"</string>
     <string name="mirror_display" msgid="2515262008898122928">"ဖန်သားပြင်ကို စကရင်ပွားရန်"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"ပယ်ရန်"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"ဖန်သားပြင်ကို ချိတ်ဆက်လိုက်ပါပြီ"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 9fc3625..0b5a0b2 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Skjermopptak"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Start"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Stopp"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Enhåndsmodus"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Kontrast"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lader • Fulladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Sveip til venstre for å starte fellesveiledningen"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Åpne redigeringsverktøyet for moduler"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Fjern en modul"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Legg til en modul"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"<xliff:g id="NAME">%1$s</xliff:g>-knappen"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Startskjerm"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Tilbake"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Oppoverpil"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Nedoverpil"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Venstrepil"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Høyrepil"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Midttasten"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Mellomrom"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Varsler"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Hurtigtaster"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Bytt tastaturoppsett"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"eller"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Fjern søket"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Hurtigtaster"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Søk etter hurtigtaster"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Fant ingen hurtigtaster"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Inndata"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Åpne apper"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Aktiv app"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Viser søkeresultater"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Viser systemsnarveier"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Viser inndatasnarveier"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Viser snarveier som åpner apper"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Viser snarveier for den gjeldende appen"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Se varsler"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Ta skjermdump"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Vis snarveier"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Du kan velge en standardapp for notater i Innstillinger"</string>
     <string name="install_app" msgid="5066668100199613936">"Installer appen"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Vil du speile til en ekstern skjerm?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Eventuell nåværende aktivitet på to skjermer stoppes"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Speil skjermen"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Lukk"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"En skjerm er koblet til"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 79cb703..9c6ffc5 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"स्क्रिन रेकर्ड"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"सुरु गर्नुहोस्"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"रोक्नुहोस्"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"एक हाते मोड"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"कन्ट्रास्ट"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"डिफल्ट"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • चार्ज हुँदै छ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मा फुल चार्ज हुने छ"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"कम्युनल ट्युटोरियल सुरु गर्न बायाँतिर स्वाइप गर्नुहोस्"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"विजेट एडिटर खोल्नुहोस्"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"कुनै विजेट हटाउनुहोस्"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"विजेट हाल्नुहोस्"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"<xliff:g id="NAME">%1$s</xliff:g> बटन"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"पछाडि"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"अप एरो"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"डाउन एरो"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"लेफ्ट एरो"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"राइट एरो"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"केन्द्र"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"स्पेस"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"सूचनाहरू"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"किबोर्ड सर्टकटहरू"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"किबोर्डको लेआउट बदल्नुहोस्"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"वा"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"किवर्ड हटाउनुहोस्"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"सर्टकटहरू"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"सर्टकटहरू खोज्नुहोस्"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"कुनै पनि सर्टकट भेटिएन"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"इनपुट"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"खोलिएका एपहरू"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"हालको एप"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"खोज परिणामहरू देखाइँदै छ"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"सिस्टमका सर्टकटहरू देखाइँदै छ"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"इनपुट गर्ने सर्टकटहरू देखाइँदै छ"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"एपहरू खोल्ने सर्टकटहरू देखाइँदै छ"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"हालको एपका लागि सर्टकटहरू देखाइँदै छ"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"सूचनाहरू हेर्नुहोस्"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"स्क्रिनसट खिच्नुहोस्"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"सर्टकटहरू देखाइऊन्"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"सेटिङमा गई नोट बनाउने डिफल्ट एप तोक्नुहोस्"</string>
     <string name="install_app" msgid="5066668100199613936">"एप इन्स्टल गर्नुहोस्"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"बाह्य डिस्प्लेमा मिरर गर्ने हो?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"डुअल स्क्रिनसम्बन्धी हाल चलिरहेको कुनै पनि गतिविधि रोकिने छ"</string>
     <string name="mirror_display" msgid="2515262008898122928">"डिस्प्ले मिरर गर्नुहोस्"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"खारेज गर्नुहोस्"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"डिस्प्ले कनेक्ट गरिएको छ"</string>
diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml
index a22fd18..bcc3c83 100644
--- a/packages/SystemUI/res/values-night/colors.xml
+++ b/packages/SystemUI/res/values-night/colors.xml
@@ -93,9 +93,6 @@
     <color name="qs_user_switcher_selected_avatar_icon_color">#202124</color>
     <!-- Color of background circle of user avatars in quick settings user switcher -->
     <color name="qs_user_switcher_avatar_background">#3C4043</color>
-    <!-- Color of border for keyguard password input when focused -->
-    <color name="bouncer_password_focus_color">@*android:color/system_secondary_dark</color>
-
 
     <!-- Accessibility floating menu -->
     <color name="accessibility_floating_menu_background">#B3000000</color> <!-- 70% -->
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 60ddb89..4dae290 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Schermopname"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Starten"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Stoppen"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Bediening met 1 hand"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Contrast"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standaard"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Opladen • Vol over <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swipe naar links om de communitytutorial te starten"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"De widget-editor openen"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Verwijder een widget"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Widget toevoegen"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Gebruiker wijzigen"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pull-downmenu"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Alle apps en gegevens in deze sessie worden verwijderd."</string>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Knop <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Terug"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Pijl-omhoog"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Pijl-omlaag"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Pijl-links"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Pijl-rechts"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Midden"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Spatiebalk"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Meldingen"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Sneltoetsen"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Toetsenbordindeling wisselen"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"of"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Zoekopdracht wissen"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Sneltoetsen"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Sneltoetsen zoeken"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Geen sneltoetsen gevonden"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Invoer"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Apps openen"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Huidige app"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Zoekresultaten tonen"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Systeemsnelkoppelingen tonen"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Invoersnelkoppelingen tonen"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Snelkoppelingen tonen die apps openen"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Snelkoppelingen voor de huidige app tonen"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Meldingen bekijken"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Screenshot maken"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Snelkoppelingen tonen"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Standaard notitie-app instellen in Instellingen"</string>
     <string name="install_app" msgid="5066668100199613936">"App installeren"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Spiegelen naar extern scherm?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Alle dual screen-activiteiten die actief zijn, worden gestopt"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Scherm spiegelen"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Sluiten"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Scherm verbonden"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index e02a5a7..bc599ba 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"ସ୍କ୍ରିନ ରେକର୍ଡ"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ଆରମ୍ଭ କରନ୍ତୁ"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"ବନ୍ଦ କରନ୍ତୁ"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"ଏକ-ହାତ ମୋଡ"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"କଣ୍ଟ୍ରାଷ୍ଟ"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"ଷ୍ଟାଣ୍ଡାର୍ଡ"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ଚାର୍ଜ ହେଉଛି • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ରେ ସମ୍ପୂର୍ଣ୍ଣ ହେବ"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"କମ୍ୟୁନାଲ ଟ୍ୟୁଟୋରିଆଲ ଆରମ୍ଭ କରିବା ପାଇଁ ବାମକୁ ସ୍ୱାଇପ କରନ୍ତୁ"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"ୱିଜେଟ ଏଡିଟର ଖୋଲନ୍ତୁ"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"ଏକ ୱିଜେଟକୁ କାଢ଼ି ଦିଅନ୍ତୁ"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"ୱିଜେଟ ଯୋଗ କରନ୍ତୁ"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"ବଟନ୍‍ <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"ହୋମ"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"ଫେରନ୍ତୁ"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"ଅପ ତୀର କୀ"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"ଡାଉନ ଆରୋ"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"ବାମ ତୀର କୀ"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"ଡାହାଣ ତୀର କୀ"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"କେନ୍ଦ୍ର"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"ସ୍ପେସ୍‍"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"ବିଜ୍ଞପ୍ତି"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"କୀବୋର୍ଡ ସର୍ଟକଟ"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"କୀ\'ବୋର୍ଡ୍‍ର ଲେଆଉଟ୍‍କୁ ବଦଳାନ୍ତୁ"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"କିମ୍ବା"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"ସର୍ଚ୍ଚ କ୍ୱେରୀକୁ ଖାଲି କରନ୍ତୁ"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ସର୍ଟକଟଗୁଡ଼ିକ"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"ସର୍ଟକଟ ସର୍ଚ୍ଚ କରନ୍ତୁ"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"କୌଣସି ସର୍ଟକଟ ମିଳିଲା ନାହିଁ"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"ଇନପୁଟ କରନ୍ତୁ"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"ଆପ୍ସ ଖୋଲନ୍ତୁ"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"ବର୍ତ୍ତମାନର ଆପ"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"ସର୍ଚ୍ଚ ଫଳାଫଳ ଦେଖାଯାଉଛି"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"ସିଷ୍ଟମ ସର୍ଟକଟ ଦେଖାଯାଉଛି"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"ଇନପୁଟ ସର୍ଟକଟ ଦେଖାଯାଉଛି"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"ଆପ୍ସକୁ ଖୋଲୁଥିବା ସର୍ଟକଟ ଦେଖାଯାଉଛି"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"ବର୍ତ୍ତମାନର ଆପ ପାଇଁ ସର୍ଟକଟ ଦେଖାଯାଉଛି"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ଭ୍ୟୁ କରନ୍ତୁ"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"ସ୍କ୍ରିନସଟ ନିଅନ୍ତୁ"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"ସର୍ଟକଟଗୁଡ଼ିକ ଦେଖାନ୍ତୁ"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"ସେଟିଂସରେ ଡିଫଲ୍ଟ ନୋଟ୍ସ ଆପ ସେଟ କରନ୍ତୁ"</string>
     <string name="install_app" msgid="5066668100199613936">"ଆପ ଇନଷ୍ଟଲ କରନ୍ତୁ"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"ଏକ୍ସଟର୍ନଲ ଡିସପ୍ଲେକୁ ମିରର କରିବେ?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"ବର୍ତ୍ତମାନ ଚାଲୁଥିବା ଯେ କୌଣସି ଡୁଆଲ ସ୍କ୍ରିନ କାର୍ଯ୍ୟକଳାପ ବନ୍ଦ ହୋଇଯିବ"</string>
     <string name="mirror_display" msgid="2515262008898122928">"ଡିସପ୍ଲେ ମିରର କରନ୍ତୁ"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"ଖାରଜ କରନ୍ତୁ"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"ଡିସପ୍ଲେ କନେକ୍ଟ କରାଯାଇଛି"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 4ab6e8be..a0718ab 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡ"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ਸ਼ੁਰੂ ਕਰੋ"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"ਰੋਕੋ"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"ਇੱਕ ਹੱਥ ਮੋਡ"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"ਕੰਟ੍ਰਾਸਟ"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"ਮਿਆਰੀ"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ਵਿੱਚ ਪੂਰਾ ਚਾਰਜ ਹੋਵੇਗਾ"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"ਭਾਈਚਾਰਕ ਟਿਊਟੋਰੀਅਲ ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਖੱਬੇ ਪਾਸੇ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"ਵਿਜੇਟ ਸੰਪਾਦਕ ਖੋਲ੍ਹੋ"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"ਵਿਜੇਟ ਨੂੰ ਹਟਾਓ"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"ਵਿਜੇਟ ਸ਼ਾਮਲ ਕਰੋ"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"ਬਟਨ <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Back"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"ਉੱਪਰ ਤੀਰ"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"ਹੇਠਾਂ ਤੀਰ"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"ਖੱਬਾ ਤੀਰ"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"ਸੱਜਾ ਤੀਰ"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Center"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Space"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"ਸੂਚਨਾਵਾਂ"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"ਕੀ-ਬੋਰਡ ਸ਼ਾਰਟਕੱਟ"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"ਕੀ-ਬੋਰਡ ਖਾਕਾ ਬਦਲੋ"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ਜਾਂ"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"ਖੋਜ ਪੁੱਛਗਿੱਛ ਕਲੀਅਰ ਕਰੋ"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ਸ਼ਾਰਟਕੱਟ"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"ਸ਼ਾਰਟਕੱਟਾਂ ਨੂੰ ਖੋਜੋ"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"ਕੋਈ ਸ਼ਾਰਟਕੱਟ ਨਹੀਂ ਮਿਲਿਆ"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"ਇਨਪੁੱਟ"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"ਐਪਾਂ ਖੋਲ੍ਹੋ"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"ਮੌਜੂਦਾ ਐਪ"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"ਖੋਜ ਨਤੀਜੇ ਦਿਖਾਏ ਜਾ ਰਹੇ ਹਨ"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"ਸਿਸਟਮ ਸ਼ਾਰਟਕੱਟ ਦਿਖਾਏ ਜਾ ਰਹੇ ਹਨ"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"ਇਨਪੁੱਟ ਸ਼ਾਰਟਕੱਟ ਦਿਖਾਏ ਜਾ ਰਹੇ ਹਨ"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"ਐਪਾਂ ਨੂੰ ਖੋਲ੍ਹਣ ਵਾਲੇ ਸ਼ਾਰਟਕੱਟ ਦਿਖਾਏ ਜਾ ਰਹੇ ਹਨ"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"ਮੌਜੂਦਾ ਐਪ ਦੇ ਸ਼ਾਰਟਕੱਟ ਦਿਖਾਏ ਜਾ ਰਹੇ ਹਨ"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"ਸੂਚਨਾਵਾਂ ਦੇਖੋ"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਲਓ"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"ਸ਼ਾਰਟਕੱਟ ਦਿਖਾਓ"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਜਾ ਕੇ ਪੂਰਵ-ਨਿਰਧਾਰਿਤ ਨੋਟ ਐਪ ਨੂੰ ਸੈੱਟ ਕਰੋ"</string>
     <string name="install_app" msgid="5066668100199613936">"ਐਪ ਸਥਾਪਤ ਕਰੋ"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"ਕੀ ਬਾਹਰੀ ਡਿਸਪਲੇ \'ਤੇ ਪ੍ਰਤਿਬਿੰਬਿਤ ਕਰਨਾ ਹੈ?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"ਇਸ ਵੇਲੇ ਚੱਲ ਰਹੀ ਕਿਸੇ ਵੀ Dual Screen ਸਰਗਰਮੀ ਬੰਦ ਕਰ ਦਿੱਤਾ ਜਾਵੇਗਾ"</string>
     <string name="mirror_display" msgid="2515262008898122928">"ਡਿਸਪਲੇ ਨੂੰ ਪ੍ਰਤਿਬਿੰਬਿਤ ਕਰੋ"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"ਖਾਰਜ ਕਰੋ"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"ਡਿਸਪਲੇ ਨੂੰ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 3647bd4..4585c1b 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Nagrywanie ekranu"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Rozpocznij"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Zatrzymaj"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Tryb jednej ręki"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Kontrast"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standardowy"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ładowanie • Pełne naładowanie za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Aby uruchomić wspólny samouczek, przeciągnij palcem w lewo"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Otwórz edytor widżetów"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Usuń widżet"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Dodaj widżet"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Przełącz użytkownika"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Wszystkie aplikacje i dane w tej sesji zostaną usunięte."</string>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Przycisk <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Wstecz"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Strzałka w górę"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Strzałka w dół"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Strzałka w lewo"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Strzałka w prawo"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Do środka"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Spacja"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Powiadomienia"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Skróty klawiszowe"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Przełącz układ klawiatury"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"lub"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Wyczyść wyszukiwanie hasło"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Skróty"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Wyszukiwanie skrótów"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nie znaleziono skrótów"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Wprowadzanie"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Otwieranie aplikacji"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Bieżąca aplikacja"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Pokazuję wyniki wyszukiwania"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Pokazuję skróty systemowe"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Pokazuję skróty dotyczące danych wejściowych"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Pokazuję skróty otwierające aplikacje"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Pokazuję skróty dotyczące bieżącej aplikacji"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Wyświetlanie powiadomień"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Robienie zrzutu ekranu"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Pokazywanie skrótów"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Ustaw domyślną aplikację do obsługi notatek w Ustawieniach"</string>
     <string name="install_app" msgid="5066668100199613936">"Zainstaluj aplikację"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Powielić na wyświetlaczu zewnętrznym?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Każda aktualnie uruchomiona aktywność na dwóch ekranach zostanie zatrzymana"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Powielaj obraz"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Zamknij"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Wyświetlacz podłączony"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 329f40a..81ddb63 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -133,7 +133,7 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefone"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Assistência de voz"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Carteira"</string>
-    <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Leitor de código QR"</string>
+    <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Leitor de QR code"</string>
     <string name="accessibility_unlock_button" msgid="3613812140816244310">"Desbloqueado"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloqueado"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Verificando rosto"</string>
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Gravação de tela"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Iniciar"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Parar"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modo para uma mão"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Contraste"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Padrão"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregando • Conclusão em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Deslize para a esquerda para iniciar o tutorial compartilhado"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Abrir o editor de widgets"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Remover um widget"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Adicionar widget"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -568,7 +578,7 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloquear para usar"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Ocorreu um problema ao carregar os cards. Tente novamente mais tarde"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Configurações de tela de bloqueio"</string>
-    <string name="qr_code_scanner_title" msgid="1938155688725760702">"Leitor de código QR"</string>
+    <string name="qr_code_scanner_title" msgid="1938155688725760702">"Leitor de QR code"</string>
     <string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Atualizando"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Perfil de trabalho"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Modo avião"</string>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Botão <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Voltar"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Seta para cima"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Seta para baixo"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Seta para a esquerda"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Seta para a direita"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Centralizar"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Space"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notificações"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Atalhos do teclado"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Alterar layout do teclado"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ou"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Limpar a consulta de pesquisa"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Atalhos"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Atalhos de pesquisa"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nenhum atalho encontrado"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Entrada"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Apps abertos"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"App atual"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Mostrando resultados da pesquisa"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Mostrando atalhos do sistema"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Mostrando atalhos de entrada"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Mostrando atalhos que abrem apps"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Mostrando atalhos do app atual"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Mostrar as notificações"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Fazer uma captura de tela"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Mostrar atalhos"</string>
@@ -1043,7 +1042,7 @@
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Como funciona a transmissão"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Transmitir"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"As pessoas próximas a você com dispositivos Bluetooth compatíveis podem ouvir a mídia que você está transmitindo"</string>
-    <string name="media_output_broadcasting_message" msgid="4150299923404886073">"As pessoas próximas com dispositivos Bluetooth compatíveis podem ler seu código QR ou usar o nome da transmissão e a senha para ouvir a transmissão."</string>
+    <string name="media_output_broadcasting_message" msgid="4150299923404886073">"As pessoas próximas com dispositivos Bluetooth compatíveis podem ler seu QR code ou usar o nome da transmissão e a senha para ouvir a transmissão."</string>
     <string name="media_output_broadcast_name" msgid="8786127091542624618">"Nome da transmissão"</string>
     <string name="media_output_broadcast_code" msgid="870795639644728542">"Senha"</string>
     <string name="media_output_broadcast_dialog_save" msgid="7910865591430010198">"Salvar"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Defina o app de notas padrão nas Configurações"</string>
     <string name="install_app" msgid="5066668100199613936">"Instalar o app"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Espelhar para a tela externa?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Qualquer atividade em tela dupla que esteja sendo executada no momento será interrompida"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Espelhar tela"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Dispensar"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Tela conectada"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 1b22929..b519a7d 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -330,6 +330,9 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Gravação ecrã"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Iniciar"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Parar"</string>
+    <string name="qs_record_issue_label" msgid="8166290137285529059">"Registar problema"</string>
+    <string name="qs_record_issue_start" msgid="2979831312582567056">"Iniciar"</string>
+    <string name="qs_record_issue_stop" msgid="3531747965741982657">"Parar"</string>
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modo para uma mão"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Contraste"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Padrão"</string>
@@ -402,8 +405,9 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • A carregar • Carga completa em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Deslize rapidamente para a esquerda para iniciar o tutorial coletivo"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Abrir editor de widgets"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Remover widget"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Adicionar widget"</string>
+    <string name="button_to_remove_widget" msgid="3948204829181214098">"Remover"</string>
+    <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Adicionar widget"</string>
+    <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Concluir"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Mudar utilizador"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu pendente"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Todas as apps e dados desta sessão serão eliminados."</string>
@@ -1197,6 +1201,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Predefina a app de notas nas Definições"</string>
     <string name="install_app" msgid="5066668100199613936">"Instalar app"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Espelhar para o ecrã externo?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Qualquer atividade de Dual Screen atualmente em curso vai ser interrompida"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Espelhar ecrã"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Ignorar"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Ecrã ligado"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 329f40a..81ddb63 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -133,7 +133,7 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefone"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Assistência de voz"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Carteira"</string>
-    <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Leitor de código QR"</string>
+    <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Leitor de QR code"</string>
     <string name="accessibility_unlock_button" msgid="3613812140816244310">"Desbloqueado"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloqueado"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Verificando rosto"</string>
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Gravação de tela"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Iniciar"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Parar"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modo para uma mão"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Contraste"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Padrão"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Carregando • Conclusão em <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Deslize para a esquerda para iniciar o tutorial compartilhado"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Abrir o editor de widgets"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Remover um widget"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Adicionar widget"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -568,7 +578,7 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloquear para usar"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Ocorreu um problema ao carregar os cards. Tente novamente mais tarde"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Configurações de tela de bloqueio"</string>
-    <string name="qr_code_scanner_title" msgid="1938155688725760702">"Leitor de código QR"</string>
+    <string name="qr_code_scanner_title" msgid="1938155688725760702">"Leitor de QR code"</string>
     <string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Atualizando"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Perfil de trabalho"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Modo avião"</string>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Botão <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Voltar"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Seta para cima"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Seta para baixo"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Seta para a esquerda"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Seta para a direita"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Centralizar"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Space"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notificações"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Atalhos do teclado"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Alterar layout do teclado"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ou"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Limpar a consulta de pesquisa"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Atalhos"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Atalhos de pesquisa"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nenhum atalho encontrado"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Entrada"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Apps abertos"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"App atual"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Mostrando resultados da pesquisa"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Mostrando atalhos do sistema"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Mostrando atalhos de entrada"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Mostrando atalhos que abrem apps"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Mostrando atalhos do app atual"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Mostrar as notificações"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Fazer uma captura de tela"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Mostrar atalhos"</string>
@@ -1043,7 +1042,7 @@
     <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Como funciona a transmissão"</string>
     <string name="media_output_broadcast" msgid="3555580945878071543">"Transmitir"</string>
     <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"As pessoas próximas a você com dispositivos Bluetooth compatíveis podem ouvir a mídia que você está transmitindo"</string>
-    <string name="media_output_broadcasting_message" msgid="4150299923404886073">"As pessoas próximas com dispositivos Bluetooth compatíveis podem ler seu código QR ou usar o nome da transmissão e a senha para ouvir a transmissão."</string>
+    <string name="media_output_broadcasting_message" msgid="4150299923404886073">"As pessoas próximas com dispositivos Bluetooth compatíveis podem ler seu QR code ou usar o nome da transmissão e a senha para ouvir a transmissão."</string>
     <string name="media_output_broadcast_name" msgid="8786127091542624618">"Nome da transmissão"</string>
     <string name="media_output_broadcast_code" msgid="870795639644728542">"Senha"</string>
     <string name="media_output_broadcast_dialog_save" msgid="7910865591430010198">"Salvar"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Defina o app de notas padrão nas Configurações"</string>
     <string name="install_app" msgid="5066668100199613936">"Instalar o app"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Espelhar para a tela externa?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Qualquer atividade em tela dupla que esteja sendo executada no momento será interrompida"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Espelhar tela"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Dispensar"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Tela conectada"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 73da4e7..bc3fbe9 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Înregistrarea ecranului"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Începe"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Oprește"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modul cu o mână"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Contrast"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Se încarcă • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> până la încărcarea completă"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Glisează spre stânga pentru a începe tutorialul pentru comunitate"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Deschide editorul de widgeturi"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Elimină un widget"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Adaugă widgetul"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -1197,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Setează aplicația prestabilită de note din Setări"</string>
     <string name="install_app" msgid="5066668100199613936">"Instalează aplicația"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Oglindești pe ecranul extern?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Orice activitate care rulează pe două ecrane va fi oprită"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Afișare în oglindă"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Închide"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Ecran conectat"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index ee3945d..2e8a257 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Запись видео с экрана"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Начать"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Остановить"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Режим управления одной рукой"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Контрастность"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Стандартная"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарядка • Осталось <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Чтобы ознакомиться с руководством, проведите по экрану влево"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Открыть редактор виджетов"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Удалить виджет"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Добавить виджет"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Кнопка <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Главный экран"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Назад"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Стрелка вверх"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Стрелка вниз"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Стрелка влево"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Стрелка вправо"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Центральная стрелка"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Пробел"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Уведомления"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Быстрые клавиши"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Переключение раскладки"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"или"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Удалить поисковый запрос"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Сочетания клавиш"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Поиск сочетаний клавиш"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Нет сочетаний клавиш."</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Ввод"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Запущенные приложения"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Это приложение"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Показаны результаты поиска"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Показаны системные сочетания клавиш"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Показаны сочетания клавиш, связанные с вводом"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Показаны сочетания клавиш для открытия приложений"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Показаны сочетания клавиш для текущего приложения"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Посмотреть уведомления"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Сделать скриншот"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Показать сочетания клавиш"</string>
@@ -1208,7 +1207,8 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Задайте стандартное приложение для заметок в настройках."</string>
     <string name="install_app" msgid="5066668100199613936">"Установить приложение"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Дублировать на внешний дисплей?"</string>
-    <string name="mirror_display" msgid="2515262008898122928">"Дублировать дисплей"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Функция одновременного использования двух экранов будет остановлена, если она активна."</string>
+    <string name="mirror_display" msgid="2515262008898122928">"Дублировать"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Закрыть"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Экран подключен"</string>
     <string name="privacy_dialog_title" msgid="7839968133469098311">"Микрофон и камера"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index e03c7c0..2405bbf 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"තිර පටිගත කිරීම"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ආරම්භ කරන්න"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"නතර කරන්න"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"තනි අත් ප්‍රකාරය"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"අසමානතාව"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"සම්මත"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ආරෝපණය වෙමින් • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>කින් සම්පූර්ණ වේ"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"පොදු නිබන්ධනය ආරම්භ කිරීමට වමට ස්වයිප් කරන්න"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"විජට් සංස්කාරකය විවෘත කරන්න"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"විජට්ටුවක් ඉවත් කරන්න"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"විජට්ටුව එක් කරන්න"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"<xliff:g id="NAME">%1$s</xliff:g> බොත්තම"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home යතුර"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"ආපසු"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"ඉහළ ඊතලය"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"පහළ ඊතලය"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"වම් ඊතලය"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"දකුණු ඊතලය"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"මැද"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"ඉඩ යතුර"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"දැනුම්දීම්"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"යතුරු පුවරු කෙටිමං"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"යතුරුපුවරු පිරිසැලසුම මාරු කරන්න"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"හෝ"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"සෙවීම් විමසුම හිස් කරන්න"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"කෙටිමං"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"කෙටිමං සොයන්න"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"කෙටිමං හමු නොවුණි"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"ආදානය"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"විවෘත යෙදුම්"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"වත්මන් යෙදුම"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"සෙවීම් ප්‍රතිඵල පෙන්වමින්"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"පද්ධති කෙටිමං පෙන්වමින්"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"ආදාන කෙටිමං පෙන්වමින්"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"යෙදුම් විවෘත කරන කෙටිමං පෙන්වමින්"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"වත්මන් යෙදුම සඳහා කෙටිමං පෙන්වමින්"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"දැනුම්දීම් බලන්න"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"තිර රුව ගන්න"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"කෙටිමං පෙන්වන්න"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"සැකසීම් තුළ පෙරනිමි සටහන් යෙදුම සකසන්න"</string>
     <string name="install_app" msgid="5066668100199613936">"යෙදුම ස්ථාපනය කරන්න"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"බාහිර සංදර්ශකයට දර්පණය කරන්න ද?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"දැනට ක්‍රියාත්මක වන ඕනෑම ද්විත්ව තිර ක්‍රියාකාරකමක් නවත්වනු ඇත"</string>
     <string name="mirror_display" msgid="2515262008898122928">"සංදර්ශකය දර්පණය කරන්න"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"අස් කරන්න"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"සංදර්ශකය සම්බන්ධ කර ඇත"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index ca49d66..f53b5bf 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Rekordér obrazovky"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Začať"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Ukončiť"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Režim jednej ruky"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Kontrast"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Štandardný"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíja sa • Do úplného nabitia zostáva <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Potiahnutím doľava spustite komunitný návod"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Otvoriť editor miniaplikácií"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Odstrániť miniaplikáciu"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Pridať miniaplikáciu"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Tlačidlo <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Domov"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Späť"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Šípka nahor"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Šípka nadol"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Šípka doľava"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Šípka doprava"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Do stredu"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Medzerník"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Upozornenia"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Klávesové skratky"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Prepnúť rozloženie klávesnice"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"alebo"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Vymazať vyhľadávací dopyt"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Skratky"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Hľadajte skratky"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nenašli sa žiadne skratky"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Vstup"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Otvorenie apl."</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Aktuálna aplik."</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Zobrazujú sa výsledky vyhľadávania"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Zobrazujú sa skratky systému"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Zobrazujú sa skratky vstupu"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Zobrazujú sa skratky na otvorenie aplikácií"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Zobrazujú sa skratky aktuálnej aplikácie"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Zobrazenie upozornení"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Vytvorenie snímky obrazovky"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Zobrazenie skratiek"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Nastavte predvolenú aplikáciu na poznámky v Nastaveniach"</string>
     <string name="install_app" msgid="5066668100199613936">"Inštalovať aplikáciu"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Chcete zrkadliť na externú obrazovku?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Akákoľvek momentálne prebiehajúca aktivita vo funkcii Dual Screen bude zastavená"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Zrkadliť obrazovku"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Zavrieť"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Obrazovka je pripojená"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index b03d7ff..ef56c4b 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Snemanje zaslona"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Začni"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Ustavi"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Enoročni način"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Kontrast"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standardni"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Polnjenje • Napolnjeno čez <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Povlecite levo, da zaženete vadnico za skupnost"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Odpiranje urejevalnika pripomočkov"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Odstranitev pripomočka"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Dodaj pripomoček"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Preklop med uporabniki"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"spustni meni"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Vse aplikacije in podatki v tej seji bodo izbrisani."</string>
@@ -1196,7 +1206,8 @@
     <string name="assistant_attention_content_description" msgid="4166330881435263596">"Zaznana je prisotnost uporabnika"</string>
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Nastavite privzeto aplikacijo za zapiske v nastavitvah."</string>
     <string name="install_app" msgid="5066668100199613936">"Namesti aplikacijo"</string>
-    <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Želite zrcaliti v zunanji zaslon?"</string>
+    <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Želite zrcaliti na zunanji zaslon?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Vse dejavnosti na dveh zaslonih, ki se trenutno izvajajo, bodo ustavljene."</string>
     <string name="mirror_display" msgid="2515262008898122928">"Zrcali zaslon"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Opusti"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Zaslon je povezan"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index c779b65..b8824c7 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Regjistrimi i ekranit"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Nis"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Ndalo"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modaliteti i përdorimit me një dorë"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Kontrasti"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Po karikohet • Plot për <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Rrëshqit shpejt majtas për të filluar udhëzuesin e përbashkët"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Hap modifikuesin e miniaplikacionit"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Hiq një miniaplikacion"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Shto miniaplikacionin"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Butoni <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Kreu"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Prapa"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Shigjeta lart"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Shigjeta poshtë"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Shigjeta majtas"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Shigjeta djathtas"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Qendror"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Hapësirë"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Njoftimet"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Shkurtoret e tastierës"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Ndërro strukturën e tastierës"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"ose"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Pastro pyetjen e kërkimit"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Shkurtoret"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Kërko shkurtoret"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nuk u gjet shkurtore"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Hyrja"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Apl. e hapura"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Apl. aktual"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Po shfaqen rezultatet e kërkimit"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Po shfaqen shkurtoret e sistemit"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Po shfaqen shkurtoret e hyrjes"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Po shfaqen shkurtoret që hapin aplikacionet"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Po shfaqen shkurtoret për aplikacionin aktual"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Shiko njoftimet"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Nxirr një pamje ekrani"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Shfaq shkurtoret"</string>
@@ -1208,6 +1207,8 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Cakto aplikacionin e parazgjedhur të shënimeve te \"Cilësimet\""</string>
     <string name="install_app" msgid="5066668100199613936">"Instalo aplikacionin"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Të pasqyrohet në ekranin e jashtëm?"</string>
+    <!-- no translation found for connected_display_dialog_dual_display_stop_warning (2917631104216376315) -->
+    <skip />
     <string name="mirror_display" msgid="2515262008898122928">"Pasqyro ekranin"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Hiq"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Ekrani është lidhur"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 48673b9..1eb4519 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Снимање екрана"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Почните"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Зауставите"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Режим једном руком"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Контраст"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Стандардно"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Пуни се • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до краја пуњења"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Превуците улево да бисте започели заједнички водич"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Отвори уређивач виџета"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Уклони виџет"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Додај виџет"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Дугме <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Тастер Почетна"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Тастер Назад"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Стрелица нагоре"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Стрелица надоле"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Стрелица налево"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Стрелица надесно"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Тастер са централном стрелицом"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Размак"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Обавештења"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Тастерске пречице"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Промени распоред тастатуре"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"или"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Обриши упит за претрагу"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Пречице"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Претражите пречице"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Нису пронађене пречице"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Унос"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Отварање аплик"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Актуелна аплик"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Приказују се резултати претраге"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Приказују се системске пречице"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Приказују се пречице за уметање"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Приказују се пречице за отварање апликација"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Приказују се пречице за актуелну апликацију"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Прикажи обавештења"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Направи снимак екрана"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Прикажи пречице"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Подесите подразумевану апликацију за белешке у Подешавањима"</string>
     <string name="install_app" msgid="5066668100199613936">"Инсталирај апликацију"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Желите ли да пресликате на спољњи екран?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Биће заустављена свака активност двојног екрана која је у току"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Пресликај екран"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Одбаци"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Екран је повезан"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 0b2cab0..c998e6d 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Skärminspelning"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Starta"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Stoppa"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Enhandsläge"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Kontrast"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laddas • Fulladdat om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Svep åt vänster för att börja med gruppguiden"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Öppna widgetredigeraren"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Ta bort en widget"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Lägg till widget"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Knappen <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Start"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Tillbaka"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Uppåtpil"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Nedåtpil"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Vänsterpil"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Högerpil"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Centrera"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Blanksteg"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Aviseringar"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Kortkommandon"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Byt tangentbordslayout"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"eller"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Rensa sökfråga"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Kortkommandon"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Sök efter kortkommando"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Inga resultat"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Inmatning"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Öppna appar"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Aktuell app"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Visar sökresultat"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Visar genvägar för systemet"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Visar genvägar för indata"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Visar genvägar som öppnar appar"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Visar genvägar för den aktuella appen"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Se aviseringar"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Ta skärmbild"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Se genvägar"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Ställ in en standardapp för anteckningar i inställningarna"</string>
     <string name="install_app" msgid="5066668100199613936">"Installera appen"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Vill du spegla till extern skärm?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Pågående Dual Screen-aktivitet stoppas"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Spegla skärm"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Ignorera"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Skärm har anslutits"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 3cd5345..fc742d8 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Rekodi ya skrini"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Anza kurekodi"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Acha kurekodi"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Hali ya kutumia kwa mkono mmoja"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Utofautishaji"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Kawaida"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Inachaji • Itajaa baada ya <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Telezesha kidole kushoto ili uanze mafunzo ya pamoja"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Fungua kihariri cha wijeti"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Ondoa wijeti"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Weka Wijeti"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -1197,6 +1207,8 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Teua programu chaguomsingi ya madokezo katika Mipangilio"</string>
     <string name="install_app" msgid="5066668100199613936">"Sakinisha programu"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Ungependa kuonyesha kwenye skrini ya nje?"</string>
+    <!-- no translation found for connected_display_dialog_dual_display_stop_warning (2917631104216376315) -->
+    <skip />
     <string name="mirror_display" msgid="2515262008898122928">"Akisi skrini"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Ondoa"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Skrini imeunganishwa"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 7989a35..afba7a92 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"ஸ்கிரீன் ரெக்கார்டு"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"தொடங்கு"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"நிறுத்து"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"ஒற்றைக் கைப் பயன்முறை"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"ஒளி மாறுபாடு"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"இயல்புநிலை"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • சார்ஜாகிறது • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> இல் முழுவதும் சார்ஜாகும்"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"சமூகப் பயிற்சியைத் தொடங்க இடதுபுறம் ஸ்வைப் செய்யுங்கள்"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"விட்ஜெட் எடிட்டரைத் திறக்கும்"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"விட்ஜெட்டை அகற்றும்"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"விட்ஜெட்டைச் சேர்"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"<xliff:g id="NAME">%1$s</xliff:g> பட்டன்"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"ஹோம்"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"பேக்"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"மேல்நோக்கிய அம்புக்குறி"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"கீழ்நோக்கிய அம்புக்குறி"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"இடது அம்புக்குறி"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"வலது அம்புக்குறி"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"நடு"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"ஸ்பேஸ்"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"அறிவிப்புகள்"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"கீபோர்டு ஷார்ட்கட்கள்"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"கீபோர்டு லே அவுட்டை மாற்று"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"அல்லது"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"தேடல் வினவலை அழிக்கும்"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ஷார்ட்கட்கள்"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"ஷார்ட்கட்களைத் தேடுக"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"ஷார்ட்கட்கள் எதுவுமில்லை"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"உள்ளீடு"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"திறந்த ஆப்ஸ்"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"தற்போதைய ஆப்ஸ்"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"தேடல் முடிவுகளைக் காட்டுகிறது"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"சிஸ்டம் ஷார்ட்கட்களைக் காட்டுகிறது"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"உள்ளிடுவதற்கான ஷார்ட்கட்களைக் காட்டுகிறது"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"ஆப்ஸைத் திறப்பதற்கான ஷார்ட்கட்களைக் காட்டுகிறது"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"தற்போது உபயோகத்தில் இருக்கும் ஆப்ஸுக்கான ஷார்ட்கட்களைக் காட்டுகிறது"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"அறிவிப்புகளைக் காட்டுதல்"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"ஸ்கிரீன்ஷாட் எடுத்தல்"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"ஷார்ட்கட்களைக் காட்டுதல்"</string>
@@ -1208,6 +1207,8 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"குறிப்பு எடுப்பதற்கான இயல்புநிலை ஆப்ஸை அமைப்புகளில் அமையுங்கள்"</string>
     <string name="install_app" msgid="5066668100199613936">"ஆப்ஸை நிறுவுங்கள்"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"வெளிப்புறக் காட்சிக்கு மிரர் செய்யவா?"</string>
+    <!-- no translation found for connected_display_dialog_dual_display_stop_warning (2917631104216376315) -->
+    <skip />
     <string name="mirror_display" msgid="2515262008898122928">"டிஸ்பிளேயை மிரர் செய்"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"வேண்டாம்"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"டிஸ்ப்ளே இணைக்கப்பட்டது"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 6b2c032..6621dae 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"స్క్రీన్ రికార్డ్"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ప్రారంభించండి"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"ఆపు"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"వన్-హ్యాండెడ్ మోడ్"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"కాంట్రాస్ట్"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"స్టాండర్డ్"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ఛార్జ్ అవుతోంది • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>లో పూర్తిగా ఛార్జ్ అవుతుంది"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"కమ్యూనల్ ట్యుటోరియల్‌ను ప్రారంభించడానికి ఎడమ వైపునకు స్వైప్ చేయండి"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"విడ్జెట్ ఎడిటర్‌ను తెరవండి"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"విడ్జెట్‌ను తీసివేయండి"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"విడ్జెట్‌ను జోడించండి"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"బటన్ <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"వెనుకకు"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"పై వైపు బాణం"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"కింది వైపు బాణం"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"ఎడమ వైపు బాణం"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"కుడి వైపు బాణం"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"మధ్య"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"అంతరం"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"నోటిఫికేషన్‌లు"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"కీబోర్డ్ షార్ట్‌కట్‌లు"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"కీబోర్డ్ లేఅవుట్‌ను మార్చండి"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"లేదా"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"సెర్చ్ క్వెరీని క్లియర్ చేయండి"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"షార్ట్‌కట్‌లు"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"షార్ట్‌కట్స్ సెర్చ్ చేయండి"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"షార్ట్‌కట్‌లు ఏవీ లేవు"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"ఇన్‌పుట్"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"యాప్స్ తెరవండి"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"ప్రస్తుత యాప్"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"సెర్చ్ ఫలితాలను చూపుతోంది"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"సిస్టమ్ షార్ట్‌కట్‌లను చూపుతోంది"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"ఇన్‌పుట్ షార్ట్‌కట్‌లను చూపుతోంది"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"యాప్‌లను తెరిచే షార్ట్‌కట్‌లను చూపుతోంది"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"ప్రస్తుత యాప్ కోసం షార్ట్‌కట్‌లను చూపుతోంది"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"నోటిఫికేషన్‌లను చూడండి"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"స్క్రీన్‌షాట్‌ను తీయండి"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"షార్ట్‌కట్‌లను చూపించండి"</string>
@@ -1207,7 +1206,8 @@
     <string name="assistant_attention_content_description" msgid="4166330881435263596">"యూజర్ ఉనికి గుర్తించబడింది"</string>
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"సెట్టింగ్‌లలో ఆటోమేటిక్‌గా ఉండేలా ఒక నోట్స్ యాప్‌ను సెట్ చేసుకోండి"</string>
     <string name="install_app" msgid="5066668100199613936">"యాప్‌ను ఇన్‌స్టాల్ చేయండి"</string>
-    <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"బాహ్య డిస్‌ప్లే‌ను మిర్రర్ చేయాలా?"</string>
+    <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"ఎక్స్‌టర్నల్ డిస్‌ప్లే‌కి మిర్రర్‌ చేయాలా?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"ప్రస్తుతం రన్ అవుతున్న Dual Screen యాక్టివిటీ ఏదైనా ఉంటే, అది ఆపివేయబడుతుంది"</string>
     <string name="mirror_display" msgid="2515262008898122928">"మిర్రర్ డిస్‌ప్లే"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"విస్మరించండి"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"డిస్‌ప్లే కనెక్ట్ చేయబడింది"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 3c5396f..8c24e4b 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"บันทึกหน้าจอ"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"เริ่ม"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"หยุด"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"โหมดมือเดียว"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"คอนทราสต์"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"มาตรฐาน"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • กำลังชาร์จ • จะเต็มในอีก <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"ปัดไปทางซ้ายเพื่อเริ่มบทแนะนำส่วนกลาง"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"เปิดเครื่องมือแก้ไขวิดเจ็ต"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"นำวิดเจ็ตออก"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"เพิ่มวิดเจ็ต"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"ปุ่ม <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"กลับ"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"ลูกศรขึ้น"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"ลูกศรลง"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"ลูกศรซ้าย"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"ลูกศรขวา"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"กึ่งกลาง"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"วรรค"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"การแจ้งเตือน"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"แป้นพิมพ์ลัด"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"สลับรูปแบบแป้นพิมพ์"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"หรือ"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"ล้างคำค้นหา"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"แป้นพิมพ์ลัด"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"ค้นหาแป้นพิมพ์ลัด"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"ไม่พบแป้นพิมพ์ลัด"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"อินพุต"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"แอปที่เปิดอยู่"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"แอปปัจจุบัน"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"แสดงผลการค้นหา"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"แสดงแป้นพิมพ์ลัดสำหรับระบบ"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"แสดงแป้นพิมพ์ลัดสำหรับอินพุต"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"แสดงแป้นพิมพ์ลัดที่เปิดแอป"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"แสดงแป้นพิมพ์ลัดสำหรับแอปปัจจุบัน"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"ดูการแจ้งเตือน"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"ถ่ายภาพหน้าจอ"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"แสดงแป้นพิมพ์ลัด"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"กำหนดแอปการจดบันทึกเริ่มต้นในการตั้งค่า"</string>
     <string name="install_app" msgid="5066668100199613936">"ติดตั้งแอป"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"มิเรอร์ไปยังจอแสดงผลภายนอกไหม"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"กิจกรรมที่ทำอยู่บน Dual Screen จะหยุดลง"</string>
     <string name="mirror_display" msgid="2515262008898122928">"มิเรอร์จอแสดงผล"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"ปิด"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"เชื่อมต่อจอแสดงผลแล้ว"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 21111a4..f0b9d1f 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Pag-record ng screen"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Magsimula"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Ihinto"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"One-hand mode"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Contrast"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standard"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nagcha-charge • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> na lang para mapuno"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Mag-swipe pakaliwa para simulan ang communal na tutorial"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Buksan ang editor ng widget"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Mag-alis ng widget"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Idagdag ang Widget"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Magpalit ng user"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"pulldown menu"</string>
     <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Ide-delete ang lahat ng app at data sa session na ito."</string>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Button na <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Back"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Pataas na arrow"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Pababang arrow"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Pakaliwang arrow"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Pakanang arrow"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Center"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Space"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Mga Notification"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Mga Keyboard Shortcut"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Magpalit ng layout ng keyboard"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"o"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"I-clear ang query sa paghahanap"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Mga Shortcut"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Maghanap ng mga shortcut"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Walang nakitang shortcut"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Input"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Buksan ang app"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Kasalukuyang app"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Ipinapakita ang mga resulta ng paghahanap"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Ipinapakita ang mga shortcut ng system"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Ipinapakita ang mga shortcut ng input"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Ipinapakita ang mga shortcut na nagbubukas ng mga app"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Ipinapakita ang mga shortcut para sa kasalukuyang app"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Tumingin ng mga notification"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Kumuha ng screenshot"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Ipakita ang mga shortcut"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Magtakda ng default na app sa pagtatala sa Mga Setting"</string>
     <string name="install_app" msgid="5066668100199613936">"I-install ang app"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"I-mirror sa external na display?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Ihihinto ang anumang aktibidad sa dual screen na kasalukuyang tumatakbo."</string>
     <string name="mirror_display" msgid="2515262008898122928">"I-mirror ang display"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"I-dismiss"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Naikonekta ang display"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 08b0251..f9d90d4 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Ekran kaydı"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Başlat"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Durdur"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Tek el modu"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Kontrast"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standart"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Şarj oluyor • Dolmasına <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> kaldı"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Ortak eğitimi başlatmak için sola kaydırın"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Widget düzenleyiciyi açın"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Widget kaldır"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Widget Ekle"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"<xliff:g id="NAME">%1$s</xliff:g> düğmesi"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Geri"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Yukarı ok"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Aşağı ok"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Sol ok"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Sağ ok"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Orta"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Boşluk"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Bildirimler"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Klavye Kısayolları"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Klavye düzenini değiştir"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"veya"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Arama sorgusunu temizle"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Kısayollar"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Kısayol araması yapın"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Kısayol bulunamadı"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Giriş"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Uygulamaları açma"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Mevcut uygulama"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Arama sonuçları gösteriliyor"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Sistem kısayolları gösteriliyor"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Giriş kısayolları gösteriliyor"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Uygulamaları açan kısayollar gösteriliyor"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Mevcut uygulamanın kısayolları gösteriliyor"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Bildirimleri görüntüle"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Ekran görüntüsü al"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Kısayolları göster"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Ayarlar\'ı kullanarak varsayılan notlar ayarlayın"</string>
     <string name="install_app" msgid="5066668100199613936">"Uygulamayı yükle"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Harici ekrana yansıtılsın mı?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Şu anda devam eden tüm Dual Screen etkinlikleri durdurulacak"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Ekranı yansıt"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Kapat"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Ekran bağlandı"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 9048b63..c5211e8 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Запис екрана"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Почати"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Зупинити"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Режим керування однією рукою"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Контраст"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Стандартний"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Заряджання • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до повного заряду"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Проведіть пальцем уліво, щоб відкрити спільний навчальний посібник"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Відкрити редактор віджетів"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Вилучити віджет"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Додати віджет"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Кнопка <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Назад"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Стрілка вгору"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Стрілка вниз"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Стрілка вліво"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Стрілка вправо"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Центр"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Пробіл"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Сповіщення"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Комбінації клавіш"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Змінити розкладку клавіатури"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"або"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Очистити пошуковий запит"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Швидкі команди"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Пошук швидких команд"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Швидк. команд не знайдено"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Метод введення"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Відкр. додатки"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Поточн. додаток"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Показано результати пошуку"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Показано комбінації клавіш для системних дій"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Показано комбінації клавіш для введення даних"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Показано комбінації клавіш, які відкривають додатки"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Показано комбінації клавіш для поточного додатка"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Переглянути сповіщення"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Зробити знімок екрана"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Показати комбінації клавіш"</string>
@@ -1208,6 +1207,8 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Призначте стандартний додаток для нотаток у налаштуваннях"</string>
     <string name="install_app" msgid="5066668100199613936">"Установити додаток"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Дублювати на зовнішньому екрані?"</string>
+    <!-- no translation found for connected_display_dialog_dual_display_stop_warning (2917631104216376315) -->
+    <skip />
     <string name="mirror_display" msgid="2515262008898122928">"Дублювати екран"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Закрити"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Дисплей під’єднано"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index d9bb0ae..01995c8 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"اسکرین ریکارڈ"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"شروع کریں"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"روکیں"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"ایک ہاتھ کی وضع"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"کنٹراسٹ"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"معیاری"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • چارج ہو رہا ہے • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> میں مکمل"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"کمیونل ٹیوٹوریل شروع کرنے کے لیے بائیں سوائپ کریں"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"ویجیٹ ایڈیٹر کو کھولیں"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"ویجیٹ ہٹائیں"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"ویجٹ شامل کریں"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"بٹن <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"پیچھے"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"اوپر تیر کا نشان"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"نیچے تیر کا نشان"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"بایاں تیر"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"دایاں تیر"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"سینٹر"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Space"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"اطلاعات"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"کی بورڈ شارٹ کٹس"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"کی بورڈ لے آؤٹ سوئچ کریں"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"یا"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"تلاش کا استفسار صاف کریں"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"شارٹ کٹس"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"شارٹ کٹس تلاش کریں"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"کوئی شارٹ کٹ نہیں ملا"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"ان پٹ"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"ایپس کھولیں"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"موجودہ ایپ"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"تلاش کے نتائج دکھائے جا رہے ہیں"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"سسٹم کے شارٹ کٹس دکھائے جا رہے ہیں"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"ان پٹ شارٹ کٹس دکھائے جا رہے ہیں"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"ایپس کو کھولنے والے شارٹ کٹس دکھائے جا رہے ہیں"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"موجودہ ایپ کے شارٹ کٹس دکھائے جا رہے ہیں"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"اطلاعات دیکھیں"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"اسکرین شاٹ لیں"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"شارٹ کٹس دکھائيں"</string>
@@ -1208,7 +1207,8 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"ترتیبات میں ڈیفالٹ نوٹس ایپ سیٹ کریں"</string>
     <string name="install_app" msgid="5066668100199613936">"ایپ انسٹال کریں"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"بیرونی ڈسپلے پر مرر کریں؟"</string>
-    <string name="mirror_display" msgid="2515262008898122928">"ڈسپلے کو دو طرفہ مطابقت پذیر بنائیں"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"‏فی الحال چلنے والی Dual Screen کی کوئی بھی سرگرمی روک دی جائے گی"</string>
+    <string name="mirror_display" msgid="2515262008898122928">"ڈسپلے کو مرر کریں"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"برخاست کریں"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"ڈسپلے منسلک ہے"</string>
     <string name="privacy_dialog_title" msgid="7839968133469098311">"مائیکروفون اور کیمرا"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 5696c61..bf48146 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Ekran yozuvi"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Boshlash"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Toʻxtatish"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Ixcham rejim"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Kontrast"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Standart"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Quvvat olmoqda • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> qoldi"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Qoʻllanma bilan tanishish uchun chapga suring"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Vidjet muharririni ochish"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Vidjetni olib tashlash"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Vidjet"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"<xliff:g id="NAME">%1$s</xliff:g> tugmasi"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Bosh ekran"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Orqaga"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Tepaga strelka"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Pastga strelka"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Chapga strelka"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Oʻngga strelka"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Markaziy ko‘rsatkichli chiziq"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Probel"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Bildirishnomalar"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Tezkor tugmalar"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Klaviatura terilmasini almashtirish"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"yoki"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Qidiruv soʻrovini tozalash"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Tezkor tugmalar"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Tezkor tugmalar qidiruvi"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Tezkor tugmalar topilmadi"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Kiritish"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Ochiq ilovalar"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Joriy ilova"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Qidiruv natijalarini koʻrsatadi"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Tizim tezkor tugmalari koʻrsatiladi"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Kirish bilan bogʻliq tezkor tugmalarni koʻrsatiladi"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Ilovalarni ochuvchi tezkor tugmalar koʻrsatiladi"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Joriy ilova uchun tezkor tugmalar koʻrsatiladi"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Bildirishnomalarni ochish"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Skrinshot olish"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Yorliqlarni ochish"</string>
@@ -1208,7 +1207,8 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Standart qaydlar ilovasini Sozlamalar orqali tanlang"</string>
     <string name="install_app" msgid="5066668100199613936">"Ilovani oʻrnatish"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Tashqi displeyda aks ettirilsinmi?"</string>
-    <string name="mirror_display" msgid="2515262008898122928">"Displeyni akslantirish"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Joriy ishga tushgan ikki ekranli faollik toʻxtatiladi"</string>
+    <string name="mirror_display" msgid="2515262008898122928">"Displeyni aks ettirish"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Yopish"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Displey ulandi"</string>
     <string name="privacy_dialog_title" msgid="7839968133469098311">"Mikrofon va kamera"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index c281d90..a70c8ad 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Ghi màn hình"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Bắt đầu"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Dừng"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Chế độ một tay"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Độ tương phản"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Chuẩn"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Đang sạc • Sẽ đầy sau <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Vuốt sang trái để bắt đầu xem hướng dẫn chung"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Mở trình chỉnh sửa tiện ích"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Xoá tiện ích"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Thêm tiện ích"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Nút <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Quay lại"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Mũi tên lên"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Mũi tên xuống"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Mũi tên trái"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Mũi tên phải"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Giữa"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Dấu cách"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Thông báo"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Phím tắt"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Chuyển đổi bố cục bàn phím"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"hoặc"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Xoá cụm từ tìm kiếm"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Lối tắt"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Lối tắt tìm kiếm"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Không tìm thấy lối tắt"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Đầu vào"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Ứng dụng đang mở"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Ứng dụng hiện tại"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Hiện các kết quả tìm kiếm"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Hiện các phím tắt cho hệ thống"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Hiện các phím tắt cho phương thức nhập"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Hiện các phím tắt mở ứng dụng"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Hiện các phím tắt cho ứng dụng hiện tại"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Xem thông báo"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Chụp ảnh màn hình"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Hiện phím tắt"</string>
@@ -714,10 +713,10 @@
     <string name="system_multitasking_rhs" msgid="2454557648974553729">"Vào chế độ chia đôi màn hình, ứng dụng hiện tại ở màn hình bên phải"</string>
     <string name="system_multitasking_lhs" msgid="3516599774920979402">"Vào chế độ chia đôi màn hình, ứng dụng hiện tại ở màn hình bên trái"</string>
     <string name="system_multitasking_full_screen" msgid="336048080383640562">"Chuyển từ chế độ chia đôi màn hình sang chế độ toàn màn hình"</string>
-    <string name="system_multitasking_replace" msgid="7410071959803642125">"Trong chế độ chia đôi màn hình: thay ứng dụng này bằng ứng dụng khác"</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>
     <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Đầu vào"</string>
     <string name="input_switch_input_language_next" msgid="3782155659868227855">"Chuyển sang ngôn ngữ tiếp theo"</string>
-    <string name="input_switch_input_language_previous" msgid="6043341362202336623">"Chuyển sang ngôn ngữ trước"</string>
+    <string name="input_switch_input_language_previous" msgid="6043341362202336623">"Chuyển về ngôn ngữ trước"</string>
     <string name="input_access_emoji" msgid="8105642858900406351">"Truy cập biểu tượng cảm xúc"</string>
     <string name="input_access_voice_typing" msgid="7291201476395326141">"Truy cập tính năng nhập liệu bằng giọng nói"</string>
     <string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Ứng dụng"</string>
@@ -1207,7 +1206,9 @@
     <string name="assistant_attention_content_description" msgid="4166330881435263596">"Phát hiện thấy người dùng đang hiện diện"</string>
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Đặt ứng dụng ghi chú mặc định trong phần Cài đặt"</string>
     <string name="install_app" msgid="5066668100199613936">"Cài đặt ứng dụng"</string>
-    <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Đồng bộ hoá hai chiều sang màn hình ngoài?"</string>
+    <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Phản chiếu sang màn hình ngoài?"</string>
+    <!-- no translation found for connected_display_dialog_dual_display_stop_warning (2917631104216376315) -->
+    <skip />
     <string name="mirror_display" msgid="2515262008898122928">"Phản chiếu màn hình"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Đóng"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Đã kết nối màn hình"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 7cde292..abc2e31 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"屏幕录制"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"开始"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"停止"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"单手模式"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"对比度"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"标准"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在充电 • 将于 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>后充满"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"向左滑动即可启动公共教程"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"打开微件编辑器"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"移除微件"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"添加微件"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"<xliff:g id="NAME">%1$s</xliff:g>按钮"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"返回"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"向上键"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"向下键"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"向左键"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"向右键"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"中心"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"空格"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"通知"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"键盘快捷键"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"切换键盘布局"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"或"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"清除搜索查询"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"快捷键"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"搜索快捷键"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"未找到任何快捷键"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"输入"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"已开应用"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"当前应用"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"目前显示的是搜索结果"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"目前显示的是系统快捷键"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"目前显示的是输入法的快捷键"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"目前显示的是用于打开应用的快捷键"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"目前显示的是当前应用的快捷键"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"查看通知"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"截取屏幕截图"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"显示快捷键"</string>
@@ -1208,7 +1207,8 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"在设置中设置默认记事应用"</string>
     <string name="install_app" msgid="5066668100199613936">"安装应用"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"镜像到外接显示屏?"</string>
-    <string name="mirror_display" msgid="2515262008898122928">"镜像显示"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"当前正在进行的任何双屏幕活动都将会停止"</string>
+    <string name="mirror_display" msgid="2515262008898122928">"镜像到显示屏"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"关闭"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"显示屏已连接"</string>
     <string name="privacy_dialog_title" msgid="7839968133469098311">"麦克风和摄像头"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index a997d06..ac40c48 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"螢幕錄影"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"開始"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"停"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"單手模式"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"對比"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"標準"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 充電中 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充滿電"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"向左滑動即可開始共用教學課程"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"開啟小工具編輯器"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"移除小工具"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"新增小工具"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"<xliff:g id="NAME">%1$s</xliff:g> 鍵"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"返回"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"向上箭咀"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"向下箭咀"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"向左箭咀"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"向右箭咀"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"箭咀中央"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"空格"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"通知"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"鍵盤快速鍵"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"切換鍵盤配置"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"或"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"清除搜尋查詢"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"快速鍵"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"搜尋快速鍵"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"找不到快速鍵"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"輸入"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"已開應用程式"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"目前的應用程式"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"顯示緊搜尋結果"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"顯示緊系統嘅快速鍵"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"顯示緊輸入裝置嘅快速鍵"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"顯示緊打開應用程式嘅快速鍵"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"顯示緊而家呢個應用程式用到嘅快速鍵"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"查看通知"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"擷取螢幕截圖"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"顯示快速鍵"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"在「設定」中指定預設筆記應用程式"</string>
     <string name="install_app" msgid="5066668100199613936">"安裝應用程式"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"要鏡像投射至外部顯示屏嗎?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"目前進行的雙螢幕活動都會停止"</string>
     <string name="mirror_display" msgid="2515262008898122928">"鏡像顯示"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"關閉"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"已連接顯示屏"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 9900adf..cc34a4a 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"螢幕錄影"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"開始"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"停止"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"單手模式"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"對比"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"標準"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 充電中 • 將於 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充飽"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"向左滑動即可啟動通用教學課程"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"開啟小工具編輯器"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"移除小工具"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"新增小工具"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"<xliff:g id="NAME">%1$s</xliff:g> 按鈕"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home 鍵"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"返回"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"向上箭頭"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"向下箭頭"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"向左箭頭"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"向右箭頭"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"中央鍵"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"空格鍵"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"通知"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"鍵盤快速鍵"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"切換鍵盤配置"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"或"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"清除搜尋查詢"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"快速鍵"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"搜尋快速鍵"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"找不到快速鍵"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"輸入"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"已開啟的應用程式"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"目前的應用程式"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"顯示搜尋結果"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"顯示系統快速鍵"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"顯示輸入快速鍵"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"顯示可開啟應用程式的快速鍵"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"顯示目前應用程式的快速鍵"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"查看通知"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"拍攝螢幕截圖"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"顯示快速鍵"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"在「設定」中指定預設記事應用程式"</string>
     <string name="install_app" msgid="5066668100199613936">"安裝應用程式"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"要以鏡像方式投放至外部螢幕嗎?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"目前進行的雙螢幕活動都會停止"</string>
     <string name="mirror_display" msgid="2515262008898122928">"鏡像顯示"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"關閉"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"螢幕已連結"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 42ddb35..83fc628 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -330,6 +330,12 @@
     <string name="quick_settings_screen_record_label" msgid="8650355346742003694">"Irekhodi lesikrini"</string>
     <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Qala"</string>
     <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Misa"</string>
+    <!-- no translation found for qs_record_issue_label (8166290137285529059) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_start (2979831312582567056) -->
+    <skip />
+    <!-- no translation found for qs_record_issue_stop (3531747965741982657) -->
+    <skip />
     <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Imodi yesandla esisodwa"</string>
     <string name="quick_settings_contrast_label" msgid="988087460210159123">"Ukugqama"</string>
     <string name="quick_settings_contrast_standard" msgid="2538227821968061832">"Okujwayelekile"</string>
@@ -402,8 +408,12 @@
     <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Iyashaja • Izogcwala ngo-<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string>
     <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swayiphela kwesokunxele ukuze uqale okokufundisa komphakathi"</string>
     <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Vula isihleli sewijethi"</string>
-    <string name="button_to_remove_widget" msgid="1511255853677835341">"Susa iwijethi"</string>
-    <string name="hub_mode_add_widget_button_text" msgid="3956587989338301487">"Engeza Iwijethi"</string>
+    <!-- no translation found for button_to_remove_widget (3948204829181214098) -->
+    <skip />
+    <!-- no translation found for hub_mode_add_widget_button_text (4831464661209971729) -->
+    <skip />
+    <!-- no translation found for hub_mode_editing_exit_button_text (3704686734192264771) -->
+    <skip />
     <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>
@@ -640,14 +650,10 @@
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Inkinobho <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Ekhaya"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Emuva"</string>
-    <!-- no translation found for keyboard_key_dpad_up (7199805608386368673) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_down (3354221123220737397) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_left (144176368026538621) -->
-    <skip />
-    <!-- no translation found for keyboard_key_dpad_right (8485763312139820037) -->
-    <skip />
+    <string name="keyboard_key_dpad_up" msgid="7199805608386368673">"Umcibisholo waphezulu"</string>
+    <string name="keyboard_key_dpad_down" msgid="3354221123220737397">"Umcibisholo waphansi"</string>
+    <string name="keyboard_key_dpad_left" msgid="144176368026538621">"Umcibisholo wangokwesokunxele"</string>
+    <string name="keyboard_key_dpad_right" msgid="8485763312139820037">"Umcibisholo wangokwesokudla"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Maphakathi"</string>
     <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Isikhala"</string>
@@ -675,10 +681,8 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Izaziso"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Izinqamulelo Zekhibhodi"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Shintsha isakhiwo sekhibhodi"</string>
-    <!-- no translation found for keyboard_shortcut_join (3578314570034512676) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_clear_text (6631051796030377857) -->
-    <skip />
+    <string name="keyboard_shortcut_join" msgid="3578314570034512676">"noma"</string>
+    <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Sula umbuzo wosesho"</string>
     <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Izinqamuleli"</string>
     <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Sesha izinqamuleli"</string>
     <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Azikho izinqamuleli ezitholakele"</string>
@@ -686,16 +690,11 @@
     <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Okokufaka"</string>
     <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Vula ama-app"</string>
     <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"I-app yamanje"</string>
-    <!-- no translation found for keyboard_shortcut_a11y_show_search_results (2865241062981833705) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_system (7744143131119370483) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_input (4589316004510335529) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_open_apps (6175417687221004059) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_a11y_filter_current_app (7944592357493737911) -->
-    <skip />
+    <string name="keyboard_shortcut_a11y_show_search_results" msgid="2865241062981833705">"Ibonisa imiphumela yosesho"</string>
+    <string name="keyboard_shortcut_a11y_filter_system" msgid="7744143131119370483">"Ibonisa izinqamuleli zesistimu"</string>
+    <string name="keyboard_shortcut_a11y_filter_input" msgid="4589316004510335529">"Ibonisa izinqamuleli zokufakwayo"</string>
+    <string name="keyboard_shortcut_a11y_filter_open_apps" msgid="6175417687221004059">"Ibonisa izinqamuleli ezivula ama-app"</string>
+    <string name="keyboard_shortcut_a11y_filter_current_app" msgid="7944592357493737911">"Ibonisa izinqamuleli ze-app yamanje"</string>
     <string name="group_system_access_notification_shade" msgid="1619028907006553677">"Buka izaziso"</string>
     <string name="group_system_full_screenshot" msgid="5742204844232667785">"Thatha isithombe-skrini"</string>
     <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Bonisa izinqamuleli"</string>
@@ -1208,6 +1207,7 @@
     <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Setha i-app yamanothi azenzakalelayo Kumsethingi"</string>
     <string name="install_app" msgid="5066668100199613936">"Faka i-app"</string>
     <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Fanisa nesibonisi sangaphandle?"</string>
+    <string name="connected_display_dialog_dual_display_stop_warning" msgid="2917631104216376315">"Noma yimuphi umsebenzi wezikrini ezimbili ezisebenzayo uzomiswa"</string>
     <string name="mirror_display" msgid="2515262008898122928">"Isibonisi sokufanisa"</string>
     <string name="dismiss_dialog" msgid="2195508495854675882">"Chitha"</string>
     <string name="connected_display_icon_desc" msgid="6373560639989971997">"Isibonisi sixhunyiwe"</string>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 462fc95..5f6a39a 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -56,8 +56,6 @@
     <color name="kg_user_switcher_restricted_avatar_icon_color">@color/GM2_grey_600</color>
     <!-- Color of background circle of user avatars in keyguard user switcher -->
     <color name="user_avatar_color_bg">?android:attr/colorBackgroundFloating</color>
-    <!-- Color of border for keyguard password input when focused -->
-    <color name="bouncer_password_focus_color">@*android:color/system_secondary_light</color>
 
     <!-- Icon color for user avatars in user switcher quick settings -->
     <color name="qs_user_switcher_avatar_icon_color">#3C4043</color>
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 1838795..cf63cc7 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -223,6 +223,8 @@
     <item type="id" name="lock_icon_bg" />
     <item type="id" name="burn_in_layer" />
     <item type="id" name="communal_tutorial_indicator" />
+    <item type="id" name="nssl_placeholder_barrier_bottom" />
+    <item type="id" name="ambient_indication_container" />
 
     <!-- Privacy dialog -->
     <item type="id" name="privacy_dialog_close_app_button" />
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 7ca0b6e..e10925d 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -824,6 +824,27 @@
     <!-- QuickSettings: Text to prompt the user to stop an ongoing recording [CHAR LIMIT=20] -->
     <string name="quick_settings_screen_record_stop">Stop</string>
 
+    <!-- QuickSettings: Record Issue tile [CHAR LIMIT=NONE] -->
+    <string name="qs_record_issue_label">Record Issue</string>
+    <!-- QuickSettings: Text to prompt the user to begin a new recording [CHAR LIMIT=20] -->
+    <string name="qs_record_issue_start">Start</string>
+    <!-- QuickSettings: Text to prompt the user to stop an ongoing recording [CHAR LIMIT=20] -->
+    <string name="qs_record_issue_stop">Stop</string>
+
+    <!-- QuickSettings: Issue Type Drop down options in Record Issue Start Dialog [CHAR LIMIT=50] -->
+    <string name="qs_record_issue_dropdown_header">What part of your device experience was affected?</string>
+    <!-- QuickSettings: Issue Type Drop down prompt in Record Issue Start Dialog [CHAR LIMIT=30] -->
+    <string name="qs_record_issue_dropdown_prompt">Select issue type</string>
+    <!-- QuickSettings: Screen record switch label in Record Issue Start Dialog [CHAR LIMIT=20] -->
+    <string name="qs_record_issue_dropdown_screenrecord">Screen record</string>
+
+    <!-- QuickSettings: Issue Type Drop down choices list in Record Issue Start Dialog [CHAR LIMIT=30] -->
+    <string-array name="qs_record_issue_types">
+        <item>Performance</item>
+        <item>User Interface</item>
+        <item>Battery</item>
+    </string-array>
+
     <!-- QuickSettings: Label for the toggle that controls whether One-handed mode is enabled. [CHAR LIMIT=NONE] -->
     <string name="quick_settings_onehanded_label">One-handed mode</string>
 
@@ -1059,9 +1080,11 @@
     <!-- Description for the button that opens the widget editor on click. [CHAR LIMIT=50] -->
     <string name="button_to_open_widget_editor">Open the widget editor</string>
     <!-- Description for the button that removes a widget on click. [CHAR LIMIT=50] -->
-    <string name="button_to_remove_widget">Remove a widget</string>
+    <string name="button_to_remove_widget">Remove</string>
     <!-- Text for the button that launches the hub mode widget picker. [CHAR LIMIT=50] -->
-    <string name="hub_mode_add_widget_button_text">Add Widget</string>
+    <string name="hub_mode_add_widget_button_text">Add widget</string>
+    <!-- Text for the button that exits the hub mode editing mode. [CHAR LIMIT=50] -->
+    <string name="hub_mode_editing_exit_button_text">Done</string>
 
     <!-- Related to user switcher --><skip/>
 
diff --git a/packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/shared/model/BiometricModalities.kt b/packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/shared/model/BiometricModalities.kt
index 80f70a0..3064829 100644
--- a/packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/shared/model/BiometricModalities.kt
+++ b/packages/SystemUI/shared/biometrics/src/com/android/systemui/biometrics/shared/model/BiometricModalities.kt
@@ -37,6 +37,10 @@
     val hasSfps: Boolean
         get() = hasFingerprint && fingerprintProperties!!.isAnySidefpsType
 
+    /** If UDFPS authentication is available. */
+    val hasUdfps: Boolean
+        get() = hasFingerprint && fingerprintProperties!!.isAnyUdfpsType
+
     /** If fingerprint authentication is available (and [faceProperties] is non-null). */
     val hasFace: Boolean
         get() = faceProperties != null
diff --git a/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt b/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt
index f1a4007..e27a328 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt
@@ -119,9 +119,8 @@
 data class ReleasedFlag constructor(
     override val name: String,
     override val namespace: String,
-    override val teamfood: Boolean = false,
     override val overridden: Boolean = false
-) : BooleanFlag(name, namespace, true, teamfood, overridden)
+) : BooleanFlag(name, namespace, true, teamfood = false, overridden)
 
 /**
  * A Flag that reads its default values from a resource overlay instead of code.
@@ -132,8 +131,9 @@
     override val name: String,
     override val namespace: String,
     @BoolRes override val resourceId: Int,
+) : ResourceFlag<Boolean> {
     override val teamfood: Boolean = false
-) : ResourceFlag<Boolean>
+}
 
 /**
  * A Flag that can reads its overrides from System Properties.
@@ -147,7 +147,6 @@
     override val namespace: String,
     override val default: Boolean = false,
 ) : SysPropFlag<Boolean> {
-    // TODO(b/268520433): Teamfood not supported for sysprop flags yet.
     override val teamfood: Boolean = false
 }
 
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButton.java b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButton.java
index fec96c6..317201d 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButton.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButton.java
@@ -16,8 +16,6 @@
 
 package com.android.systemui.shared.rotation;
 
-import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
-
 import android.annotation.DimenRes;
 import android.annotation.IdRes;
 import android.annotation.LayoutRes;
@@ -89,8 +87,7 @@
             @DimenRes int roundedContentPadding, @DimenRes int taskbarLeftMargin,
             @DimenRes int taskbarBottomMargin, @DimenRes int buttonDiameter,
             @DimenRes int rippleMaxWidth, @BoolRes int floatingRotationBtnPositionLeftResource) {
-        mContext = context.createWindowContext(context.getDisplay(), TYPE_NAVIGATION_BAR_PANEL,
-                null);
+        mContext = context;
         mWindowManager = mContext.getSystemService(WindowManager.class);
         mKeyButtonContainer = (ViewGroup) LayoutInflater.from(mContext).inflate(layout, null);
         mKeyButtonView = mKeyButtonContainer.findViewById(keyButtonId);
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/InteractionJankMonitorWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InteractionJankMonitorWrapper.java
index c505bd5..d6a5477 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/InteractionJankMonitorWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InteractionJankMonitorWrapper.java
@@ -16,82 +16,22 @@
 
 package com.android.systemui.shared.system;
 
-import android.annotation.IntDef;
 import android.os.Build;
 import android.text.TextUtils;
 import android.view.View;
 
+import com.android.internal.jank.Cuj;
 import com.android.internal.jank.InteractionJankMonitor;
 import com.android.internal.jank.InteractionJankMonitor.Configuration;
 
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
 public final class InteractionJankMonitorWrapper {
-    // Launcher journeys.
-    public static final int CUJ_APP_LAUNCH_FROM_RECENTS =
-            InteractionJankMonitor.CUJ_LAUNCHER_APP_LAUNCH_FROM_RECENTS;
-    public static final int CUJ_APP_LAUNCH_FROM_ICON =
-            InteractionJankMonitor.CUJ_LAUNCHER_APP_LAUNCH_FROM_ICON;
-    public static final int CUJ_APP_CLOSE_TO_HOME =
-            InteractionJankMonitor.CUJ_LAUNCHER_APP_CLOSE_TO_HOME;
-    public static final int CUJ_APP_CLOSE_TO_HOME_FALLBACK =
-            InteractionJankMonitor.CUJ_LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK;
-    public static final int CUJ_APP_CLOSE_TO_PIP =
-            InteractionJankMonitor.CUJ_LAUNCHER_APP_CLOSE_TO_PIP;
-    public static final int CUJ_QUICK_SWITCH =
-            InteractionJankMonitor.CUJ_LAUNCHER_QUICK_SWITCH;
-    public static final int CUJ_OPEN_ALL_APPS =
-            InteractionJankMonitor.CUJ_LAUNCHER_OPEN_ALL_APPS;
-    public static final int CUJ_CLOSE_ALL_APPS_SWIPE =
-            InteractionJankMonitor.CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE;
-    public static final int CUJ_CLOSE_ALL_APPS_TO_HOME =
-            InteractionJankMonitor.CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME;
-    public static final int CUJ_ALL_APPS_SCROLL =
-            InteractionJankMonitor.CUJ_LAUNCHER_ALL_APPS_SCROLL;
-    public static final int CUJ_APP_LAUNCH_FROM_WIDGET =
-            InteractionJankMonitor.CUJ_LAUNCHER_APP_LAUNCH_FROM_WIDGET;
-    public static final int CUJ_SPLIT_SCREEN_ENTER =
-            InteractionJankMonitor.CUJ_SPLIT_SCREEN_ENTER;
-    public static final int CUJ_LAUNCHER_UNLOCK_ENTRANCE_ANIMATION =
-            InteractionJankMonitor.CUJ_LAUNCHER_UNLOCK_ENTRANCE_ANIMATION;
-    public static final int CUJ_RECENTS_SCROLLING =
-            InteractionJankMonitor.CUJ_RECENTS_SCROLLING;
-    public static final int CUJ_APP_SWIPE_TO_RECENTS =
-            InteractionJankMonitor.CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS;
-    public static final int CUJ_OPEN_SEARCH_RESULT =
-            InteractionJankMonitor.CUJ_LAUNCHER_OPEN_SEARCH_RESULT;
-    public static final int CUJ_LAUNCHER_UNFOLD_ANIM =
-            InteractionJankMonitor.CUJ_LAUNCHER_UNFOLD_ANIM;
-
-    @IntDef({
-            CUJ_APP_LAUNCH_FROM_RECENTS,
-            CUJ_APP_LAUNCH_FROM_ICON,
-            CUJ_APP_CLOSE_TO_HOME,
-            CUJ_APP_CLOSE_TO_HOME_FALLBACK,
-            CUJ_APP_CLOSE_TO_PIP,
-            CUJ_QUICK_SWITCH,
-            CUJ_APP_LAUNCH_FROM_WIDGET,
-            CUJ_LAUNCHER_UNLOCK_ENTRANCE_ANIMATION,
-            CUJ_RECENTS_SCROLLING,
-            CUJ_APP_SWIPE_TO_RECENTS,
-            CUJ_OPEN_ALL_APPS,
-            CUJ_CLOSE_ALL_APPS_SWIPE,
-            CUJ_CLOSE_ALL_APPS_TO_HOME,
-            CUJ_OPEN_SEARCH_RESULT,
-            CUJ_LAUNCHER_UNFOLD_ANIM,
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface CujType {
-    }
-
     /**
      * Begin a trace session.
      *
      * @param v       an attached view.
-     * @param cujType the specific {@link InteractionJankMonitor.CujType}.
+     * @param cujType the specific {@link Cuj.CujType}.
      */
-    public static void begin(View v, @CujType int cujType) {
+    public static void begin(View v, @Cuj.CujType int cujType) {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) return;
         InteractionJankMonitor.getInstance().begin(v, cujType);
     }
@@ -100,10 +40,10 @@
      * Begin a trace session.
      *
      * @param v       an attached view.
-     * @param cujType the specific {@link InteractionJankMonitor.CujType}.
+     * @param cujType the specific {@link Cuj.CujType}.
      * @param timeout duration to cancel the instrumentation in ms
      */
-    public static void begin(View v, @CujType int cujType, long timeout) {
+    public static void begin(View v, @Cuj.CujType int cujType, long timeout) {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) return;
         Configuration.Builder builder =
                 Configuration.Builder.withView(cujType, v)
@@ -115,10 +55,10 @@
      * Begin a trace session.
      *
      * @param v       an attached view.
-     * @param cujType the specific {@link InteractionJankMonitor.CujType}.
+     * @param cujType the specific {@link Cuj.CujType}.
      * @param tag the tag to distinguish different flow of same type CUJ.
      */
-    public static void begin(View v, @CujType int cujType, String tag) {
+    public static void begin(View v, @Cuj.CujType int cujType, String tag) {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) return;
         Configuration.Builder builder =
                 Configuration.Builder.withView(cujType, v);
@@ -131,9 +71,9 @@
     /**
      * End a trace session.
      *
-     * @param cujType the specific {@link InteractionJankMonitor.CujType}.
+     * @param cujType the specific {@link Cuj.CujType}.
      */
-    public static void end(@CujType int cujType) {
+    public static void end(@Cuj.CujType int cujType) {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) return;
         InteractionJankMonitor.getInstance().end(cujType);
     }
@@ -141,7 +81,7 @@
     /**
      * Cancel the trace session.
      */
-    public static void cancel(@CujType int cujType) {
+    public static void cancel(@Cuj.CujType int cujType) {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) return;
         InteractionJankMonitor.getInstance().cancel(cujType);
     }
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 bf68869..d8c1e41 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
@@ -103,8 +103,6 @@
     public static final int SYSUI_STATE_BACK_DISABLED = 1 << 22;
     // The bubble stack is expanded AND the mange menu for bubbles is expanded on top of it.
     public static final int SYSUI_STATE_BUBBLES_MANAGE_MENU_EXPANDED = 1 << 23;
-    // The current app is in immersive mode
-    public static final int SYSUI_STATE_IMMERSIVE_MODE = 1 << 24;
     // The voice interaction session window is showing
     public static final int SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING = 1 << 25;
     // Freeform windows are showing in desktop mode
@@ -162,7 +160,6 @@
             SYSUI_STATE_DEVICE_DOZING,
             SYSUI_STATE_BACK_DISABLED,
             SYSUI_STATE_BUBBLES_MANAGE_MENU_EXPANDED,
-            SYSUI_STATE_IMMERSIVE_MODE,
             SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING,
             SYSUI_STATE_FREEFORM_ACTIVE_IN_DESKTOP_MODE,
             SYSUI_STATE_DEVICE_DREAMING,
@@ -247,9 +244,6 @@
         if ((flags & SYSUI_STATE_BUBBLES_MANAGE_MENU_EXPANDED) != 0) {
             str.add("bubbles_mange_menu_expanded");
         }
-        if ((flags & SYSUI_STATE_IMMERSIVE_MODE) != 0) {
-            str.add("immersive_mode");
-        }
         if ((flags & SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING) != 0) {
             str.add("vis_win_showing");
         }
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 aef8371..f9fe67a 100644
--- a/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsFactory.kt
+++ b/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsFactory.kt
@@ -42,7 +42,7 @@
         name: String,
         namespace: String = "systemui",
     ): ReleasedFlag {
-        val flag = ReleasedFlag(name = name, namespace = namespace, teamfood = false)
+        val flag = ReleasedFlag(name = name, namespace = namespace)
         checkForDupesAndAdd(flag)
         return flag
     }
@@ -57,7 +57,6 @@
                 name = name,
                 namespace = namespace,
                 resourceId = resourceId,
-                teamfood = false,
             )
         checkForDupesAndAdd(flag)
         return flag
diff --git a/packages/SystemUI/src-release/com/android/systemui/flags/FlagsFactory.kt b/packages/SystemUI/src-release/com/android/systemui/flags/FlagsFactory.kt
index f4b4296..aedf0ce 100644
--- a/packages/SystemUI/src-release/com/android/systemui/flags/FlagsFactory.kt
+++ b/packages/SystemUI/src-release/com/android/systemui/flags/FlagsFactory.kt
@@ -42,7 +42,7 @@
         name: String,
         namespace: String = "systemui",
     ): ReleasedFlag {
-        val flag = ReleasedFlag(name = name, namespace = namespace, teamfood = false)
+        val flag = ReleasedFlag(name = name, namespace = namespace)
         flagMap[name] = flag
         return flag
     }
@@ -57,7 +57,6 @@
                 name = name,
                 namespace = namespace,
                 resourceId = resourceId,
-                teamfood = false,
             )
         flagMap[name] = flag
         return flag
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index be2c65f..cdd7b80 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -72,7 +72,7 @@
 import com.android.systemui.statusbar.phone.NotificationIconAreaController;
 import com.android.systemui.statusbar.phone.NotificationIconContainer;
 import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
-import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.ui.SystemBarUtilsState;
 import com.android.systemui.util.ViewController;
 import com.android.systemui.util.concurrency.DelayableExecutor;
 import com.android.systemui.util.settings.SecureSettings;
@@ -105,7 +105,7 @@
     private final NotificationIconContainerAlwaysOnDisplayViewModel mAodIconsViewModel;
     private final KeyguardRootViewModel mKeyguardRootViewModel;
     private final ConfigurationState mConfigurationState;
-    private final ConfigurationController mConfigurationController;
+    private final SystemBarUtilsState mSystemBarUtilsState;
     private final DozeParameters mDozeParameters;
     private final ScreenOffAnimationController mScreenOffAnimationController;
     private final AlwaysOnDisplayNotificationIconViewStore mAodIconViewStore;
@@ -183,7 +183,7 @@
             KeyguardSliceViewController keyguardSliceViewController,
             NotificationIconAreaController notificationIconAreaController,
             LockscreenSmartspaceController smartspaceController,
-            ConfigurationController configurationController,
+            SystemBarUtilsState systemBarUtilsState,
             ScreenOffAnimationController screenOffAnimationController,
             StatusBarIconViewBindingFailureTracker iconViewBindingFailureTracker,
             KeyguardUnlockAnimationController keyguardUnlockAnimationController,
@@ -208,7 +208,7 @@
         mKeyguardSliceViewController = keyguardSliceViewController;
         mNotificationIconAreaController = notificationIconAreaController;
         mSmartspaceController = smartspaceController;
-        mConfigurationController = configurationController;
+        mSystemBarUtilsState = systemBarUtilsState;
         mScreenOffAnimationController = screenOffAnimationController;
         mIconViewBindingFailureTracker = iconViewBindingFailureTracker;
         mSecureSettings = secureSettings;
@@ -619,13 +619,14 @@
                     mAodIconsBindHandle.dispose();
                 }
                 if (nic != null) {
-                    final DisposableHandle viewHandle = NotificationIconContainerViewBinder.bind(
-                            nic,
-                            mAodIconsViewModel,
-                            mConfigurationState,
-                            mConfigurationController,
-                            mIconViewBindingFailureTracker,
-                            mAodIconViewStore);
+                    final DisposableHandle viewHandle =
+                            NotificationIconContainerViewBinder.bindWhileAttached(
+                                    nic,
+                                    mAodIconsViewModel,
+                                    mConfigurationState,
+                                    mSystemBarUtilsState,
+                                    mIconViewBindingFailureTracker,
+                                    mAodIconViewStore);
                     final DisposableHandle visHandle = KeyguardRootViewBinder.bindAodIconVisibility(
                             nic,
                             mKeyguardRootViewModel.isNotifIconContainerVisible(),
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
index 5c206e9..5d63c2a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
@@ -281,7 +281,10 @@
             setAlpha(1f);
             mAppearAnimationUtils.startAnimation2d(
                     mLockPatternView.getCellStates(),
-                    () -> enableClipping(true),
+                    () -> {
+                        enableClipping(true);
+                        mLockPatternView.invalidate();
+                    },
                     KeyguardPatternView.this);
         });
         if (!TextUtils.isEmpty(mSecurityMessageDisplay.getText())) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
index 9764de1..36fe75f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
@@ -168,6 +168,7 @@
 
         // Set selected property on so the view can send accessibility events.
         mPasswordEntry.setSelected(true);
+        mPasswordEntry.setDefaultFocusHighlightEnabled(false);
 
         mOkButton = findViewById(R.id.key_enter);
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java
index 38a8cd3..c4aa7a2 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java
@@ -104,4 +104,14 @@
      */
     default void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput) {
     }
+
+    /**
+     * Shows the security screen that should be shown.
+     *
+     * This can be considered as a "refresh" of the bouncer view. Based on certain parameters,
+     * we might switch to a different bouncer screen. e.g. SimPin to SimPuk.
+     */
+    default void showCurrentSecurityScreen() {
+
+    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index f706301..cce2018 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -27,6 +27,8 @@
 import static com.android.keyguard.KeyguardSecurityContainer.USER_TYPE_PRIMARY;
 import static com.android.keyguard.KeyguardSecurityContainer.USER_TYPE_SECONDARY_USER;
 import static com.android.keyguard.KeyguardSecurityContainer.USER_TYPE_WORK_PROFILE;
+import static com.android.keyguard.KeyguardSecurityModel.SecurityMode.SimPin;
+import static com.android.keyguard.KeyguardSecurityModel.SecurityMode.SimPuk;
 import static com.android.systemui.DejankUtils.whitelistIpcs;
 import static com.android.systemui.flags.Flags.LOCKSCREEN_ENABLE_LANDSCAPE;
 import static com.android.systemui.flags.Flags.REVAMPED_BOUNCER_MESSAGES;
@@ -36,7 +38,7 @@
 import android.content.Intent;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
-import android.hardware.biometrics.BiometricOverlayConstants;
+import android.hardware.biometrics.BiometricRequestConstants;
 import android.media.AudioManager;
 import android.metrics.LogMaker;
 import android.os.SystemClock;
@@ -72,6 +74,7 @@
 import com.android.systemui.biometrics.FaceAuthAccessibilityDelegate;
 import com.android.systemui.biometrics.SideFpsController;
 import com.android.systemui.biometrics.SideFpsUiRequestSource;
+import com.android.systemui.biometrics.shared.SideFpsControllerRefactor;
 import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor;
 import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
 import com.android.systemui.classifier.FalsingA11yDelegate;
@@ -99,6 +102,7 @@
 import dagger.Lazy;
 
 import java.io.File;
+import java.util.Arrays;
 import java.util.Optional;
 
 import javax.inject.Inject;
@@ -164,8 +168,8 @@
                     }
                     mCurrentUser = mSelectedUserInteractor.getSelectedUserId();
                     showPrimarySecurityScreen(false);
-                    if (mCurrentSecurityMode != SecurityMode.SimPin
-                            && mCurrentSecurityMode != SecurityMode.SimPuk) {
+                    if (mCurrentSecurityMode != SimPin
+                            && mCurrentSecurityMode != SimPuk) {
                         reinflateViewFlipper((l) -> {
                         });
                     }
@@ -334,6 +338,11 @@
         public void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput) {
             mViewMediatorCallback.setNeedsInput(needsInput);
         }
+
+        @Override
+        public void showCurrentSecurityScreen() {
+            showPrimarySecurityScreen(false);
+        }
     };
 
     private final SwipeListener mSwipeListener = new SwipeListener() {
@@ -478,7 +487,11 @@
         mSceneContainerFlags = sceneContainerFlags;
         mGlobalSettings = globalSettings;
         mSessionTracker = sessionTracker;
-        mSideFpsController = sideFpsController;
+        if (SideFpsControllerRefactor.isEnabled()) {
+            mSideFpsController = Optional.empty();
+        } else {
+            mSideFpsController = sideFpsController;
+        }
         mFalsingA11yDelegate = falsingA11yDelegate;
         mTelephonyManager = telephonyManager;
         mViewMediatorCallback = viewMediatorCallback;
@@ -561,12 +574,14 @@
         mView.clearFocus();
     }
 
+    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
     /**
      * Shows and hides the side finger print sensor animation.
      *
      * @param isVisible sets whether we show or hide the side fps animation
      */
     public void updateSideFpsVisibility(boolean isVisible) {
+        SideFpsControllerRefactor.assertInLegacyMode();
         if (!mSideFpsController.isPresent()) {
             return;
         }
@@ -574,7 +589,7 @@
         if (isVisible) {
             mSideFpsController.get().show(
                     SideFpsUiRequestSource.PRIMARY_BOUNCER,
-                    BiometricOverlayConstants.REASON_AUTH_KEYGUARD
+                    BiometricRequestConstants.REASON_AUTH_KEYGUARD
             );
         } else {
             mSideFpsController.get().hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
@@ -888,7 +903,8 @@
                         finish = true;
                         eventSubtype = BOUNCER_DISMISS_SIM;
                         uiEvent = BouncerUiEvent.BOUNCER_DISMISS_SIM;
-                    } else {
+                    } else if (Arrays.asList(SimPin, SimPuk).contains(securityMode)) {
+                        // There are additional screens to the sim pin/puk flow.
                         showSecurityScreen(securityMode);
                     }
                     break;
@@ -1095,8 +1111,8 @@
     }
 
     private void configureMode() {
-        boolean useSimSecurity = mCurrentSecurityMode == SecurityMode.SimPin
-                || mCurrentSecurityMode == SecurityMode.SimPuk;
+        boolean useSimSecurity = mCurrentSecurityMode == SimPin
+                || mCurrentSecurityMode == SimPuk;
         int mode = KeyguardSecurityContainer.MODE_DEFAULT;
         if (canDisplayUserSwitcher() && !useSimSecurity) {
             mode = KeyguardSecurityContainer.MODE_USER_SWITCHER;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
index 6e24208..c5e7070 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
@@ -16,6 +16,8 @@
 
 package com.android.keyguard;
 
+import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+
 import static com.android.systemui.util.PluralMessageFormaterKt.icuMessageFormat;
 
 import android.annotation.NonNull;
@@ -60,7 +62,7 @@
     // When this is true and when SIM card is PIN locked state, on PIN lock screen, message would
     // be displayed to inform user about the number of remaining PIN attempts left.
     private boolean mShowDefaultMessage;
-    private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+    private int mSubId = INVALID_SUBSCRIPTION_ID;
     private AlertDialog mRemainingAttemptsDialog;
     private ImageView mSimImageView;
 
@@ -68,6 +70,12 @@
         @Override
         public void onSimStateChanged(int subId, int slotId, int simState) {
             if (DEBUG) Log.v(TAG, "onSimStateChanged(subId=" + subId + ",state=" + simState + ")");
+            // If subId has gone to PUK required then we need to go to the PUK screen.
+            if (subId == mSubId && simState == TelephonyManager.SIM_STATE_PUK_REQUIRED) {
+                getKeyguardSecurityCallback().showCurrentSecurityScreen();
+                return;
+            }
+
             if (simState == TelephonyManager.SIM_STATE_READY) {
                 mRemainingAttempts = -1;
                 resetState();
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 37bd9b2..9c61a8a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -1277,6 +1277,17 @@
 
     private final FaceAuthenticationListener mFaceAuthenticationListener =
             new FaceAuthenticationListener() {
+                public void onAuthenticatedChanged(boolean isAuthenticated) {
+                    if (!isAuthenticated) {
+                        for (int i = 0; i < mCallbacks.size(); i++) {
+                            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+                            if (cb != null) {
+                                cb.onFacesCleared();
+                            }
+                        }
+                    }
+                }
+
                 @Override
                 public void onAuthEnrollmentStateChanged(boolean enrolled) {
                     notifyAboutEnrollmentChange(TYPE_FACE);
@@ -1961,7 +1972,7 @@
 
     protected void handleStartedGoingToSleep(int arg1) {
         Assert.isMainThread();
-        clearBiometricRecognized();
+        clearFingerprintRecognized();
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
@@ -3010,7 +3021,7 @@
     void handleUserSwitching(int userId, Runnable resultCallback) {
         mLogger.logUserSwitching(userId, "from UserTracker");
         Assert.isMainThread();
-        clearBiometricRecognized();
+        clearFingerprintRecognized();
         boolean trustUsuallyManaged = mTrustManager.isTrustUsuallyManaged(userId);
         mLogger.logTrustUsuallyManagedUpdated(userId, mUserTrustIsUsuallyManaged.get(userId),
                 trustUsuallyManaged, "userSwitching");
@@ -3560,25 +3571,30 @@
         return mServiceStates.get(subId);
     }
 
-    public void clearBiometricRecognized() {
-        clearBiometricRecognized(UserHandle.USER_NULL);
+    /**
+     * Resets the fingerprint authenticated state to false.
+     */
+    public void clearFingerprintRecognized() {
+        clearFingerprintRecognized(UserHandle.USER_NULL);
     }
 
-    public void clearBiometricRecognizedWhenKeyguardDone(int unlockedUser) {
-        clearBiometricRecognized(unlockedUser);
+    /**
+     * Resets the fingerprint authenticated state to false.
+     */
+    public void clearFingerprintRecognizedWhenKeyguardDone(int unlockedUser) {
+        clearFingerprintRecognized(unlockedUser);
     }
 
-    private void clearBiometricRecognized(int unlockedUser) {
+    private void clearFingerprintRecognized(int unlockedUser) {
         Assert.isMainThread();
         mUserFingerprintAuthenticated.clear();
         mTrustManager.clearAllBiometricRecognized(FINGERPRINT, unlockedUser);
-        mTrustManager.clearAllBiometricRecognized(FACE, unlockedUser);
-        mLogger.d("clearBiometricRecognized");
+        mLogger.d("clearFingerprintRecognized");
 
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
-                cb.onBiometricsCleared();
+                cb.onFingerprintsCleared();
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index 02dd331..9d216dce 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -291,9 +291,14 @@
     public void onLogoutEnabledChanged() { }
 
     /**
-     * Called when authenticated biometrics are cleared.
+     * Called when authenticated fingerprint biometrics are cleared.
      */
-    public void onBiometricsCleared() { }
+    public void onFingerprintsCleared() { }
+
+    /**
+     * Called when authenticated face biometrics have cleared.
+     */
+    public void onFacesCleared() { }
 
     /**
      * Called when the secondary lock screen requirement changes.
diff --git a/packages/SystemUI/src/com/android/systemui/Prefs.java b/packages/SystemUI/src/com/android/systemui/Prefs.java
index 70750a1..0be206d 100644
--- a/packages/SystemUI/src/com/android/systemui/Prefs.java
+++ b/packages/SystemUI/src/com/android/systemui/Prefs.java
@@ -73,7 +73,8 @@
             Key.ACCESSIBILITY_FLOATING_MENU_POSITION,
             Key.HAS_CLICKED_NUDGE_TO_SETUP_DREAM,
             Key.HAS_DISMISSED_NUDGE_TO_SETUP_DREAM,
-            Key.HAS_ACCESSIBILITY_FLOATING_MENU_TUCKED
+            Key.HAS_ACCESSIBILITY_FLOATING_MENU_TUCKED,
+            Key.BLUETOOTH_TILE_DIALOG_CONTENT_HEIGHT,
     })
     // TODO: annotate these with their types so {@link PrefsCommandLine} can know how to set them
     public @interface Key {
@@ -119,6 +120,7 @@
         String HAS_CLICKED_NUDGE_TO_SETUP_DREAM = "HasClickedNudgeToSetupDream";
         String HAS_DISMISSED_NUDGE_TO_SETUP_DREAM = "HasDismissedNudgeToSetupDream";
         String HAS_ACCESSIBILITY_FLOATING_MENU_TUCKED = "HasAccessibilityFloatingMenuTucked";
+        String BLUETOOTH_TILE_DIALOG_CONTENT_HEIGHT = "BluetoothTileDialogContentHeight";
     }
 
     public static boolean getBoolean(Context context, @Key String key, boolean defaultValue) {
diff --git a/packages/SystemUI/src/com/android/systemui/StatusBarInsetsCommand.kt b/packages/SystemUI/src/com/android/systemui/StatusBarInsetsCommand.kt
new file mode 100644
index 0000000..7e2a1e1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/StatusBarInsetsCommand.kt
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui
+
+import android.view.Surface
+import android.view.Surface.Rotation
+import com.android.systemui.statusbar.commandline.ParseableCommand
+import com.android.systemui.statusbar.commandline.Type
+import java.io.PrintWriter
+
+class StatusBarInsetsCommand(
+    private val callback: Callback,
+) : ParseableCommand(NAME) {
+
+    val bottomMargin: BottomMarginCommand? by subCommand(BottomMarginCommand())
+
+    override fun execute(pw: PrintWriter) {
+        callback.onExecute(command = this, pw)
+    }
+
+    interface Callback {
+        fun onExecute(command: StatusBarInsetsCommand, printWriter: PrintWriter)
+    }
+
+    companion object {
+        const val NAME = "status-bar-insets"
+    }
+}
+
+class BottomMarginCommand : ParseableCommand(NAME) {
+
+    private val rotationDegrees: Int? by
+        param(
+            longName = "rotation",
+            shortName = "r",
+            description = "For which rotation the margin should be set. One of 0, 90, 180, 270",
+            valueParser = Type.Int,
+        )
+
+    @Rotation
+    val rotationValue: Int?
+        get() = ROTATION_DEGREES_TO_VALUE_MAPPING[rotationDegrees]
+
+    val marginBottomDp: Float? by
+        param(
+            longName = "margin",
+            shortName = "m",
+            description = "Margin amount, in dp. Can be a fractional value, such as 10.5",
+            valueParser = Type.Float,
+        )
+
+    override fun execute(pw: PrintWriter) {
+        // Not needed for a subcommand
+    }
+
+    companion object {
+        const val NAME = "bottom-margin"
+        private val ROTATION_DEGREES_TO_VALUE_MAPPING =
+            mapOf(
+                0 to Surface.ROTATION_0,
+                90 to Surface.ROTATION_90,
+                180 to Surface.ROTATION_180,
+                270 to Surface.ROTATION_270,
+            )
+
+        val ROTATION_DEGREES_OPTIONS: Set<Int> = ROTATION_DEGREES_TO_VALUE_MAPPING.keys
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index bf44517..c3f6480 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -110,6 +110,10 @@
         View.setTracedRequestLayoutClassClass(
                 SystemProperties.get("persist.debug.trace_request_layout_class", null));
 
+        if (Flags.enableLayoutTracing()) {
+            View.setTraceLayoutSteps(true);
+        }
+
         if (Process.myUserHandle().equals(UserHandle.SYSTEM)) {
             IntentFilter bootCompletedFilter = new
                     IntentFilter(Intent.ACTION_LOCKED_BOOT_COMPLETED);
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityModule.kt b/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityModule.kt
index ca859de..24aa11e 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityModule.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 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.
@@ -16,61 +16,16 @@
 
 package com.android.systemui.accessibility
 
-import com.android.systemui.qs.tileimpl.QSTileImpl
-import com.android.systemui.qs.tiles.ColorCorrectionTile
-import com.android.systemui.qs.tiles.ColorInversionTile
-import com.android.systemui.qs.tiles.DreamTile
-import com.android.systemui.qs.tiles.FontScalingTile
-import com.android.systemui.qs.tiles.NightDisplayTile
-import com.android.systemui.qs.tiles.OneHandedModeTile
-import com.android.systemui.qs.tiles.ReduceBrightColorsTile
+import com.android.systemui.accessibility.data.repository.ColorCorrectionRepository
+import com.android.systemui.accessibility.data.repository.ColorCorrectionRepositoryImpl
+import com.android.systemui.accessibility.qs.QSAccessibilityModule
 import dagger.Binds
 import dagger.Module
-import dagger.multibindings.IntoMap
-import dagger.multibindings.StringKey
 
-@Module
+@Module(includes = [QSAccessibilityModule::class])
 interface AccessibilityModule {
-
-    /** Inject ColorInversionTile into tileMap in QSModule */
     @Binds
-    @IntoMap
-    @StringKey(ColorInversionTile.TILE_SPEC)
-    fun bindColorInversionTile(colorInversionTile: ColorInversionTile): QSTileImpl<*>
-
-    /** Inject NightDisplayTile into tileMap in QSModule */
-    @Binds
-    @IntoMap
-    @StringKey(NightDisplayTile.TILE_SPEC)
-    fun bindNightDisplayTile(nightDisplayTile: NightDisplayTile): QSTileImpl<*>
-
-    /** Inject ReduceBrightColorsTile into tileMap in QSModule */
-    @Binds
-    @IntoMap
-    @StringKey(ReduceBrightColorsTile.TILE_SPEC)
-    fun bindReduceBrightColorsTile(reduceBrightColorsTile: ReduceBrightColorsTile): QSTileImpl<*>
-
-    /** Inject OneHandedModeTile into tileMap in QSModule */
-    @Binds
-    @IntoMap
-    @StringKey(OneHandedModeTile.TILE_SPEC)
-    fun bindOneHandedModeTile(oneHandedModeTile: OneHandedModeTile): QSTileImpl<*>
-
-    /** Inject ColorCorrectionTile into tileMap in QSModule */
-    @Binds
-    @IntoMap
-    @StringKey(ColorCorrectionTile.TILE_SPEC)
-    fun bindColorCorrectionTile(colorCorrectionTile: ColorCorrectionTile): QSTileImpl<*>
-
-    /** Inject DreamTile into tileMap in QSModule */
-    @Binds
-    @IntoMap
-    @StringKey(DreamTile.TILE_SPEC)
-    fun bindDreamTile(dreamTile: DreamTile): QSTileImpl<*>
-
-    /** Inject FontScalingTile into tileMap in QSModule */
-    @Binds
-    @IntoMap
-    @StringKey(FontScalingTile.TILE_SPEC)
-    fun bindFontScalingTile(fontScalingTile: FontScalingTile): QSTileImpl<*>
+    abstract fun colorCorrectionRepository(
+        impl: ColorCorrectionRepositoryImpl
+    ): ColorCorrectionRepository
 }
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationConnectionImpl.java b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationConnectionImpl.java
index 4944531..ba943b0 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationConnectionImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationConnectionImpl.java
@@ -22,8 +22,8 @@
 import android.os.RemoteException;
 import android.util.Log;
 import android.view.accessibility.IMagnificationConnection;
+import android.view.accessibility.IMagnificationConnectionCallback;
 import android.view.accessibility.IRemoteMagnificationAnimationCallback;
-import android.view.accessibility.IWindowMagnificationConnectionCallback;
 
 import com.android.systemui.dagger.qualifiers.Main;
 
@@ -36,7 +36,7 @@
 
     private static final String TAG = "WindowMagnificationConnectionImpl";
 
-    private IWindowMagnificationConnectionCallback mConnectionCallback;
+    private IMagnificationConnectionCallback mConnectionCallback;
     private final Magnification mMagnification;
     private final Handler mHandler;
 
@@ -105,7 +105,7 @@
     }
 
     @Override
-    public void setConnectionCallback(IWindowMagnificationConnectionCallback callback) {
+    public void setConnectionCallback(IMagnificationConnectionCallback callback) {
         mConnectionCallback = callback;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java
index c03e403..a98990a 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java
@@ -59,8 +59,8 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
-import com.android.systemui.res.R;
 import com.android.systemui.common.ui.view.SeekBarWithIconButtonsView;
+import com.android.systemui.res.R;
 import com.android.systemui.util.settings.SecureSettings;
 
 import java.lang.annotation.Retention;
@@ -671,17 +671,17 @@
     }
 
     private Rect getDraggableWindowBounds() {
-        final int layoutMargin = mContext.getResources().getDimensionPixelSize(
-                R.dimen.magnification_switch_button_margin);
         final WindowMetrics windowMetrics = mWindowManager.getCurrentWindowMetrics();
         final Insets windowInsets = windowMetrics.getWindowInsets().getInsetsIgnoringVisibility(
                 WindowInsets.Type.systemBars() | WindowInsets.Type.displayCutout());
+        // re-measure the settings panel view so that we can get the correct view size to inset
+        int unspecificSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
+        mSettingView.measure(unspecificSpec, unspecificSpec);
+
         final Rect boundRect = new Rect(windowMetrics.getBounds());
         boundRect.offsetTo(0, 0);
-        boundRect.inset(0, 0, mParams.width, mParams.height);
+        boundRect.inset(0, 0, mSettingView.getMeasuredWidth(), mSettingView.getMeasuredHeight());
         boundRect.inset(windowInsets);
-        boundRect.inset(layoutMargin, layoutMargin);
-
         return boundRect;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/data/repository/ColorCorrectionRepository.kt b/packages/SystemUI/src/com/android/systemui/accessibility/data/repository/ColorCorrectionRepository.kt
new file mode 100644
index 0000000..6483ae4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/data/repository/ColorCorrectionRepository.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.accessibility.data.repository
+
+import android.os.UserHandle
+import android.provider.Settings.Secure
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.util.settings.SecureSettings
+import com.android.systemui.util.settings.SettingsProxyExt.observerFlow
+import javax.inject.Inject
+import kotlin.coroutines.CoroutineContext
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onStart
+import kotlinx.coroutines.withContext
+
+/** Provides data related to color correction. */
+interface ColorCorrectionRepository {
+    /** Observable for whether color correction is enabled */
+    fun isEnabled(userHandle: UserHandle): Flow<Boolean>
+
+    /** Sets color correction enabled state. */
+    suspend fun setIsEnabled(isEnabled: Boolean, userHandle: UserHandle): Boolean
+}
+
+@SysUISingleton
+class ColorCorrectionRepositoryImpl
+@Inject
+constructor(
+    @Background private val bgCoroutineContext: CoroutineContext,
+    private val secureSettings: SecureSettings,
+) : ColorCorrectionRepository {
+
+    companion object {
+        const val SETTING_NAME = Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED
+        const val DISABLED = 0
+        const val ENABLED = 1
+    }
+
+    override fun isEnabled(userHandle: UserHandle): Flow<Boolean> =
+        secureSettings
+            .observerFlow(userHandle.identifier, SETTING_NAME)
+            .onStart { emit(Unit) }
+            .map { secureSettings.getIntForUser(SETTING_NAME, userHandle.identifier) == ENABLED }
+            .distinctUntilChanged()
+            .flowOn(bgCoroutineContext)
+
+    override suspend fun setIsEnabled(isEnabled: Boolean, userHandle: UserHandle): Boolean =
+        withContext(bgCoroutineContext) {
+            secureSettings.putIntForUser(
+                SETTING_NAME,
+                if (isEnabled) ENABLED else DISABLED,
+                userHandle.identifier
+            )
+        }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/qs/QSAccessibilityModule.kt b/packages/SystemUI/src/com/android/systemui/accessibility/qs/QSAccessibilityModule.kt
new file mode 100644
index 0000000..df7fdb8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/qs/QSAccessibilityModule.kt
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.accessibility.qs
+
+import com.android.systemui.qs.QsEventLogger
+import com.android.systemui.qs.pipeline.shared.TileSpec
+import com.android.systemui.qs.tileimpl.QSTileImpl
+import com.android.systemui.qs.tiles.ColorCorrectionTile
+import com.android.systemui.qs.tiles.ColorInversionTile
+import com.android.systemui.qs.tiles.DreamTile
+import com.android.systemui.qs.tiles.FontScalingTile
+import com.android.systemui.qs.tiles.NightDisplayTile
+import com.android.systemui.qs.tiles.OneHandedModeTile
+import com.android.systemui.qs.tiles.ReduceBrightColorsTile
+import com.android.systemui.qs.tiles.base.viewmodel.QSTileViewModelFactory
+import com.android.systemui.qs.tiles.impl.colorcorrection.domain.ColorCorrectionTileMapper
+import com.android.systemui.qs.tiles.impl.colorcorrection.domain.interactor.ColorCorrectionTileDataInteractor
+import com.android.systemui.qs.tiles.impl.colorcorrection.domain.interactor.ColorCorrectionUserActionInteractor
+import com.android.systemui.qs.tiles.impl.colorcorrection.domain.model.ColorCorrectionTileModel
+import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
+import com.android.systemui.qs.tiles.viewmodel.QSTileUIConfig
+import com.android.systemui.qs.tiles.viewmodel.QSTileViewModel
+import com.android.systemui.res.R
+import dagger.Binds
+import dagger.Module
+import dagger.Provides
+import dagger.multibindings.IntoMap
+import dagger.multibindings.StringKey
+
+@Module
+interface QSAccessibilityModule {
+
+    /** Inject ColorInversionTile into tileMap in QSModule */
+    @Binds
+    @IntoMap
+    @StringKey(ColorInversionTile.TILE_SPEC)
+    fun bindColorInversionTile(colorInversionTile: ColorInversionTile): QSTileImpl<*>
+
+    /** Inject NightDisplayTile into tileMap in QSModule */
+    @Binds
+    @IntoMap
+    @StringKey(NightDisplayTile.TILE_SPEC)
+    fun bindNightDisplayTile(nightDisplayTile: NightDisplayTile): QSTileImpl<*>
+
+    /** Inject ReduceBrightColorsTile into tileMap in QSModule */
+    @Binds
+    @IntoMap
+    @StringKey(ReduceBrightColorsTile.TILE_SPEC)
+    fun bindReduceBrightColorsTile(reduceBrightColorsTile: ReduceBrightColorsTile): QSTileImpl<*>
+
+    /** Inject OneHandedModeTile into tileMap in QSModule */
+    @Binds
+    @IntoMap
+    @StringKey(OneHandedModeTile.TILE_SPEC)
+    fun bindOneHandedModeTile(oneHandedModeTile: OneHandedModeTile): QSTileImpl<*>
+
+    /** Inject ColorCorrectionTile into tileMap in QSModule */
+    @Binds
+    @IntoMap
+    @StringKey(ColorCorrectionTile.TILE_SPEC)
+    fun bindColorCorrectionTile(colorCorrectionTile: ColorCorrectionTile): QSTileImpl<*>
+
+    /** Inject DreamTile into tileMap in QSModule */
+    @Binds
+    @IntoMap
+    @StringKey(DreamTile.TILE_SPEC)
+    fun bindDreamTile(dreamTile: DreamTile): QSTileImpl<*>
+
+    /** Inject FontScalingTile into tileMap in QSModule */
+    @Binds
+    @IntoMap
+    @StringKey(FontScalingTile.TILE_SPEC)
+    fun bindFontScalingTile(fontScalingTile: FontScalingTile): QSTileImpl<*>
+
+    companion object {
+
+        const val COLOR_CORRECTION_TILE_SPEC = "color_correction"
+
+        @Provides
+        @IntoMap
+        @StringKey(COLOR_CORRECTION_TILE_SPEC)
+        fun provideColorCorrectionTileConfig(uiEventLogger: QsEventLogger): QSTileConfig =
+            QSTileConfig(
+                tileSpec = TileSpec.create(COLOR_CORRECTION_TILE_SPEC),
+                uiConfig =
+                    QSTileUIConfig.Resource(
+                        iconRes = R.drawable.ic_qs_color_correction,
+                        labelRes = R.string.quick_settings_color_correction_label,
+                    ),
+                instanceId = uiEventLogger.getNewInstanceId(),
+            )
+
+        /** Inject ColorCorrectionTile into tileViewModelMap in QSModule */
+        @Provides
+        @IntoMap
+        @StringKey(COLOR_CORRECTION_TILE_SPEC)
+        fun provideColorCorrectionTileViewModel(
+            factory: QSTileViewModelFactory.Static<ColorCorrectionTileModel>,
+            mapper: ColorCorrectionTileMapper,
+            stateInteractor: ColorCorrectionTileDataInteractor,
+            userActionInteractor: ColorCorrectionUserActionInteractor
+        ): QSTileViewModel =
+            factory.create(
+                TileSpec.create(COLOR_CORRECTION_TILE_SPEC),
+                userActionInteractor,
+                stateInteractor,
+                mapper,
+            )
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt b/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt
index dd4ca92..fda23b7f 100644
--- a/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt
@@ -24,9 +24,9 @@
 import com.android.internal.widget.LockPatternUtils
 import com.android.internal.widget.LockscreenCredential
 import com.android.keyguard.KeyguardSecurityModel
+import com.android.systemui.authentication.shared.model.AuthenticationLockoutModel
 import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.authentication.shared.model.AuthenticationResultModel
-import com.android.systemui.authentication.shared.model.AuthenticationThrottlingModel
 import com.android.systemui.broadcast.BroadcastDispatcher
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
@@ -60,14 +60,6 @@
 /** Defines interface for classes that can access authentication-related application state. */
 interface AuthenticationRepository {
     /**
-     * Whether the auto confirm feature is enabled for the currently-selected user.
-     *
-     * Note that the length of the PIN is also important to take into consideration, please see
-     * [hintedPinLength].
-     */
-    val isAutoConfirmFeatureEnabled: StateFlow<Boolean>
-
-    /**
      * Emits the result whenever a PIN/Pattern/Password security challenge is attempted by the user
      * in order to unlock the device.
      */
@@ -88,10 +80,22 @@
     val isPatternVisible: StateFlow<Boolean>
 
     /**
-     * The current authentication throttling state, set when the user has to wait before being able
-     * to try another authentication attempt. `null` indicates throttling isn't active.
+     * The current authentication lockout (aka "throttling") state, set when the user has to wait
+     * before being able to try another authentication attempt. `null` indicates throttling isn't
+     * active.
      */
-    val throttling: MutableStateFlow<AuthenticationThrottlingModel?>
+    val lockout: MutableStateFlow<AuthenticationLockoutModel?>
+
+    /** Whether throttling has occurred at least once since the last successful authentication. */
+    val hasLockoutOccurred: MutableStateFlow<Boolean>
+
+    /**
+     * Whether the auto confirm feature is enabled for the currently-selected user.
+     *
+     * Note that the length of the PIN is also important to take into consideration, please see
+     * [hintedPinLength].
+     */
+    val isAutoConfirmFeatureEnabled: StateFlow<Boolean>
 
     /**
      * The currently-configured authentication method. This determines how the authentication
@@ -135,22 +139,25 @@
     /** Reports an authentication attempt. */
     suspend fun reportAuthenticationAttempt(isSuccessful: Boolean)
 
+    /** Reports that the user has entered a temporary device lockout (throttling). */
+    suspend fun reportLockoutStarted(durationMs: Int)
+
     /** Returns the current number of failed authentication attempts. */
     suspend fun getFailedAuthenticationAttemptCount(): Int
 
     /**
-     * Returns the timestamp for when the current throttling will end, allowing the user to attempt
+     * Returns the timestamp for when the current lockout will end, allowing the user to attempt
      * authentication again.
      *
      * Note that this is in milliseconds and it matches [SystemClock.elapsedRealtime].
      */
-    suspend fun getThrottlingEndTimestamp(): Long
+    suspend fun getLockoutEndTimestamp(): Long
 
     /**
-     * Sets the throttling timeout duration (time during which the user should not be allowed to
+     * Sets the lockout timeout duration (time during which the user should not be allowed to
      * attempt authentication).
      */
-    suspend fun setThrottleDuration(durationMs: Int)
+    suspend fun setLockoutDuration(durationMs: Int)
 
     /**
      * Checks the given [LockscreenCredential] to see if it's correct, returning an
@@ -172,11 +179,6 @@
     mobileConnectionsRepository: MobileConnectionsRepository,
 ) : AuthenticationRepository {
 
-    override val isAutoConfirmFeatureEnabled: StateFlow<Boolean> =
-        refreshingFlow(
-            initialValue = false,
-            getFreshValue = lockPatternUtils::isAutoPinConfirmEnabled,
-        )
     override val authenticationChallengeResult = MutableSharedFlow<Boolean>()
 
     override val hintedPinLength: Int = 6
@@ -187,11 +189,15 @@
             getFreshValue = lockPatternUtils::isVisiblePatternEnabled,
         )
 
-    override val throttling: MutableStateFlow<AuthenticationThrottlingModel?> =
-        MutableStateFlow(null)
+    override val lockout: MutableStateFlow<AuthenticationLockoutModel?> = MutableStateFlow(null)
 
-    private val selectedUserId: Int
-        get() = userRepository.getSelectedUserInfo().id
+    override val hasLockoutOccurred: MutableStateFlow<Boolean> = MutableStateFlow(false)
+
+    override val isAutoConfirmFeatureEnabled: StateFlow<Boolean> =
+        refreshingFlow(
+            initialValue = false,
+            getFreshValue = lockPatternUtils::isAutoPinConfirmEnabled,
+        )
 
     override val authenticationMethod: Flow<AuthenticationMethodModel> =
         combine(userRepository.selectedUserInfo, mobileConnectionsRepository.isAnySimSecure) {
@@ -249,19 +255,25 @@
         }
     }
 
+    override suspend fun reportLockoutStarted(durationMs: Int) {
+        return withContext(backgroundDispatcher) {
+            lockPatternUtils.reportPasswordLockout(durationMs, selectedUserId)
+        }
+    }
+
     override suspend fun getFailedAuthenticationAttemptCount(): Int {
         return withContext(backgroundDispatcher) {
             lockPatternUtils.getCurrentFailedPasswordAttempts(selectedUserId)
         }
     }
 
-    override suspend fun getThrottlingEndTimestamp(): Long {
+    override suspend fun getLockoutEndTimestamp(): Long {
         return withContext(backgroundDispatcher) {
             lockPatternUtils.getLockoutAttemptDeadline(selectedUserId)
         }
     }
 
-    override suspend fun setThrottleDuration(durationMs: Int) {
+    override suspend fun setLockoutDuration(durationMs: Int) {
         withContext(backgroundDispatcher) {
             lockPatternUtils.setLockoutAttemptDeadline(selectedUserId, durationMs)
         }
@@ -273,13 +285,16 @@
         return withContext(backgroundDispatcher) {
             try {
                 val matched = lockPatternUtils.checkCredential(credential, selectedUserId) {}
-                AuthenticationResultModel(isSuccessful = matched, throttleDurationMs = 0)
+                AuthenticationResultModel(isSuccessful = matched, lockoutDurationMs = 0)
             } catch (ex: LockPatternUtils.RequestThrottledException) {
-                AuthenticationResultModel(isSuccessful = false, throttleDurationMs = ex.timeoutMs)
+                AuthenticationResultModel(isSuccessful = false, lockoutDurationMs = ex.timeoutMs)
             }
         }
     }
 
+    private val selectedUserId: Int
+        get() = userRepository.getSelectedUserInfo().id
+
     /**
      * Returns a [StateFlow] that's automatically kept fresh. The passed-in [getFreshValue] is
      * invoked on a background thread every time the selected user is changed and every time a new
diff --git a/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt b/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt
index 1ba0220..797154e 100644
--- a/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt
@@ -20,15 +20,16 @@
 import com.android.internal.widget.LockPatternView
 import com.android.internal.widget.LockscreenCredential
 import com.android.systemui.authentication.data.repository.AuthenticationRepository
+import com.android.systemui.authentication.shared.model.AuthenticationLockoutModel
 import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.authentication.shared.model.AuthenticationPatternCoordinate
-import com.android.systemui.authentication.shared.model.AuthenticationThrottlingModel
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.user.data.repository.UserRepository
 import com.android.systemui.util.time.SystemClock
 import javax.inject.Inject
+import kotlin.math.ceil
 import kotlin.math.max
 import kotlin.time.Duration.Companion.seconds
 import kotlinx.coroutines.CoroutineDispatcher
@@ -84,25 +85,25 @@
     val authenticationMethod: Flow<AuthenticationMethodModel> = repository.authenticationMethod
 
     /**
-     * The current authentication throttling state, set when the user has to wait before being able
-     * to try another authentication attempt. `null` indicates throttling isn't active.
+     * The current authentication lockout (aka "throttling") state, set when the user has to wait
+     * before being able to try another authentication attempt. `null` indicates lockout isn't
+     * active.
      */
-    val throttling: StateFlow<AuthenticationThrottlingModel?> = repository.throttling
+    val lockout: StateFlow<AuthenticationLockoutModel?> = repository.lockout
 
     /**
      * Whether the auto confirm feature is enabled for the currently-selected user.
      *
      * Note that the length of the PIN is also important to take into consideration, please see
      * [hintedPinLength].
-     *
-     * During throttling, this is always disabled (`false`).
      */
     val isAutoConfirmEnabled: StateFlow<Boolean> =
-        combine(repository.isAutoConfirmFeatureEnabled, repository.throttling) {
+        combine(repository.isAutoConfirmFeatureEnabled, repository.hasLockoutOccurred) {
                 featureEnabled,
-                throttling ->
-                // Disable auto-confirm during throttling.
-                featureEnabled && throttling == null
+                hasLockoutOccurred ->
+                // Disable auto-confirm if lockout occurred since the last successful
+                // authentication attempt.
+                featureEnabled && !hasLockoutOccurred
             }
             .stateIn(
                 scope = applicationScope,
@@ -139,7 +140,7 @@
     /** Whether the "enhanced PIN privacy" setting is enabled for the current user. */
     val isPinEnhancedPrivacyEnabled: StateFlow<Boolean> = repository.isPinEnhancedPrivacyEnabled
 
-    private var throttlingCountdownJob: Job? = null
+    private var lockoutCountdownJob: Job? = null
 
     init {
         applicationScope.launch {
@@ -188,8 +189,8 @@
         val authMethod = getAuthenticationMethod()
         val skipCheck =
             when {
-                // Throttling is active, the UI layer should not have called this; skip the attempt.
-                throttling.value != null -> true
+                // Lockout is active, the UI layer should not have called this; skip the attempt.
+                lockout.value != null -> true
                 // The input is too short; skip the attempt.
                 input.isTooShort(authMethod) -> true
                 // Auto-confirm attempt when the feature is not enabled; skip the attempt.
@@ -215,18 +216,22 @@
             )
         }
 
-        // Check if we need to throttle and, if so, kick off the throttle countdown:
-        if (!authenticationResult.isSuccessful && authenticationResult.throttleDurationMs > 0) {
-            repository.setThrottleDuration(
-                durationMs = authenticationResult.throttleDurationMs,
-            )
-            startThrottlingCountdown()
+        // Check if lockout should start and, if so, kick off the countdown:
+        if (!authenticationResult.isSuccessful && authenticationResult.lockoutDurationMs > 0) {
+            repository.apply {
+                setLockoutDuration(durationMs = authenticationResult.lockoutDurationMs)
+                reportLockoutStarted(durationMs = authenticationResult.lockoutDurationMs)
+                hasLockoutOccurred.value = true
+            }
+            startLockoutCountdown()
         }
 
         if (authenticationResult.isSuccessful) {
-            // Since authentication succeeded, we should refresh throttling to make sure that our
-            // state is completely reflecting the upstream source of truth.
-            refreshThrottling()
+            // Since authentication succeeded, refresh lockout to make sure the state is completely
+            // reflecting the upstream source of truth.
+            refreshLockout()
+
+            repository.hasLockoutOccurred.value = false
         }
 
         return if (authenticationResult.isSuccessful) {
@@ -244,52 +249,52 @@
         }
     }
 
-    /** Starts refreshing the throttling state every second. */
-    private suspend fun startThrottlingCountdown() {
-        cancelThrottlingCountdown()
-        throttlingCountdownJob =
+    /** Starts refreshing the lockout state every second. */
+    private suspend fun startLockoutCountdown() {
+        cancelLockoutCountdown()
+        lockoutCountdownJob =
             applicationScope.launch {
-                while (refreshThrottling()) {
+                while (refreshLockout()) {
                     delay(1.seconds.inWholeMilliseconds)
                 }
             }
     }
 
-    /** Cancels any throttling state countdown started in [startThrottlingCountdown]. */
-    private fun cancelThrottlingCountdown() {
-        throttlingCountdownJob?.cancel()
-        throttlingCountdownJob = null
+    /** Cancels any lockout state countdown started in [startLockoutCountdown]. */
+    private fun cancelLockoutCountdown() {
+        lockoutCountdownJob?.cancel()
+        lockoutCountdownJob = null
     }
 
     /** Notifies that the currently-selected user has changed. */
     private suspend fun onSelectedUserChanged() {
-        cancelThrottlingCountdown()
-        if (refreshThrottling()) {
-            startThrottlingCountdown()
+        cancelLockoutCountdown()
+        if (refreshLockout()) {
+            startLockoutCountdown()
         }
     }
 
     /**
-     * Refreshes the throttling state, hydrating the repository with the latest state.
+     * Refreshes the lockout state, hydrating the repository with the latest state.
      *
-     * @return Whether throttling is active or not.
+     * @return Whether lockout is active or not.
      */
-    private suspend fun refreshThrottling(): Boolean {
-        withContext("$TAG#refreshThrottling", backgroundDispatcher) {
+    private suspend fun refreshLockout(): Boolean {
+        withContext("$TAG#refreshLockout", backgroundDispatcher) {
             val failedAttemptCount = async { repository.getFailedAuthenticationAttemptCount() }
-            val deadline = async { repository.getThrottlingEndTimestamp() }
+            val deadline = async { repository.getLockoutEndTimestamp() }
             val remainingMs = max(0, deadline.await() - clock.elapsedRealtime())
-            repository.throttling.value =
+            repository.lockout.value =
                 if (remainingMs > 0) {
-                    AuthenticationThrottlingModel(
+                    AuthenticationLockoutModel(
                         failedAttemptCount = failedAttemptCount.await(),
-                        remainingMs = remainingMs.toInt(),
+                        remainingSeconds = ceil(remainingMs / 1000f).toInt(),
                     )
                 } else {
-                    null // Throttling ended.
+                    null // Lockout ended.
                 }
         }
-        return repository.throttling.value != null
+        return repository.lockout.value != null
     }
 
     private fun AuthenticationMethodModel.createCredential(
diff --git a/packages/SystemUI/src/com/android/systemui/authentication/shared/model/AuthenticationThrottlingModel.kt b/packages/SystemUI/src/com/android/systemui/authentication/shared/model/AuthenticationLockoutModel.kt
similarity index 60%
rename from packages/SystemUI/src/com/android/systemui/authentication/shared/model/AuthenticationThrottlingModel.kt
rename to packages/SystemUI/src/com/android/systemui/authentication/shared/model/AuthenticationLockoutModel.kt
index d0d398e..8ee2d5e 100644
--- a/packages/SystemUI/src/com/android/systemui/authentication/shared/model/AuthenticationThrottlingModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/authentication/shared/model/AuthenticationLockoutModel.kt
@@ -16,17 +16,20 @@
 
 package com.android.systemui.authentication.shared.model
 
-/** Models a state for throttling the next authentication attempt. */
-data class AuthenticationThrottlingModel(
+/** Models a state for temporarily locking out the next authentication attempt. */
+data class AuthenticationLockoutModel(
 
-    /** Number of failed authentication attempts so far. If not throttling this will be `0`. */
+    /** Number of failed authentication attempts so far. If not locked out this will be `0`. */
     val failedAttemptCount: Int = 0,
 
     /**
-     * Remaining amount of time, in milliseconds, before another authentication attempt can be done.
-     * If not throttling this will be `0`.
+     * Remaining amount of time, in seconds, before another authentication attempt can be done. If
+     * not locked out this will be `0`.
      *
-     * This number is changed throughout the timeout.
+     * This number is changed throughout the lockout.
+     *
+     * Note: this isn't precise (in milliseconds), but rounded up to ensure "at most" this amount of
+     * seconds remains.
      */
-    val remainingMs: Int = 0,
+    val remainingSeconds: Int = 0,
 )
diff --git a/packages/SystemUI/src/com/android/systemui/authentication/shared/model/AuthenticationResultModel.kt b/packages/SystemUI/src/com/android/systemui/authentication/shared/model/AuthenticationResultModel.kt
index f2a3e74..addc75e 100644
--- a/packages/SystemUI/src/com/android/systemui/authentication/shared/model/AuthenticationResultModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/authentication/shared/model/AuthenticationResultModel.kt
@@ -21,5 +21,5 @@
     /** Whether authentication was successful. */
     val isSuccessful: Boolean = false,
     /** If [isSuccessful] is `false`, how long the user must wait before trying again. */
-    val throttleDurationMs: Int = 0,
+    val lockoutDurationMs: Int = 0,
 )
diff --git a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
index 24cd9b5..b1a153a 100644
--- a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
@@ -66,8 +66,6 @@
     public static final int MODE_ON = 1;
     public static final int MODE_OFF = 2;
     public static final int MODE_ESTIMATE = 3;
-    @VisibleForTesting
-    public static final long LAYOUT_TRANSITION_DURATION = 200;
 
     private final AccessorizedBatteryDrawable mDrawable;
     private final ImageView mBatteryIconView;
@@ -136,7 +134,7 @@
 
     private void setupLayoutTransition() {
         LayoutTransition transition = new LayoutTransition();
-        transition.setDuration(LAYOUT_TRANSITION_DURATION);
+        transition.setDuration(200);
 
         // Animates appearing/disappearing of the battery percentage text using fade-in/fade-out
         // and disables all other animation types
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index 877afce..5fba761 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -70,6 +70,7 @@
 import com.android.systemui.biometrics.domain.interactor.LogContextInteractor;
 import com.android.systemui.biometrics.domain.interactor.PromptCredentialInteractor;
 import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractor;
+import com.android.systemui.biometrics.shared.SideFpsControllerRefactor;
 import com.android.systemui.biometrics.shared.model.UdfpsOverlayParams;
 import com.android.systemui.biometrics.ui.viewmodel.CredentialViewModel;
 import com.android.systemui.biometrics.ui.viewmodel.PromptViewModel;
@@ -88,6 +89,8 @@
 
 import dagger.Lazy;
 
+import kotlin.Unit;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -101,7 +104,6 @@
 import javax.inject.Inject;
 import javax.inject.Provider;
 
-import kotlin.Unit;
 import kotlinx.coroutines.CoroutineScope;
 
 /**
@@ -317,7 +319,9 @@
 
         mSidefpsProps = !sidefpsProps.isEmpty() ? sidefpsProps : null;
         if (mSidefpsProps != null) {
-            mSideFpsController = mSidefpsControllerFactory.get();
+            if (!SideFpsControllerRefactor.isEnabled()) {
+                mSideFpsController = mSidefpsControllerFactory.get();
+            }
         }
 
         mFingerprintManager.registerBiometricStateListener(new BiometricStateListener() {
@@ -1194,7 +1198,7 @@
      * Whether the passed userId has enrolled SFPS.
      */
     public boolean isSfpsEnrolled(int userId) {
-        if (mSideFpsController == null) {
+        if (mSidefpsProps == null) {
             return false;
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
index 91cee9e..ac99fc6 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
@@ -23,9 +23,9 @@
 import android.graphics.PorterDuff
 import android.graphics.PorterDuffColorFilter
 import android.graphics.Rect
-import android.hardware.biometrics.BiometricOverlayConstants
-import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_KEYGUARD
-import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_SETTINGS
+import android.hardware.biometrics.BiometricRequestConstants
+import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_KEYGUARD
+import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_SETTINGS
 import android.hardware.biometrics.SensorLocationInternal
 import android.hardware.display.DisplayManager
 import android.hardware.fingerprint.FingerprintManager
@@ -58,6 +58,7 @@
 import com.android.keyguard.KeyguardPINView
 import com.android.systemui.Dumpable
 import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor
+import com.android.systemui.biometrics.shared.SideFpsControllerRefactor
 import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
@@ -91,7 +92,7 @@
     @Main private val mainExecutor: DelayableExecutor,
     @Main private val handler: Handler,
     private val alternateBouncerInteractor: AlternateBouncerInteractor,
-    @Application private val scope: CoroutineScope,
+    @Application private val applicationScope: CoroutineScope,
     dumpManager: DumpManager,
     fpsUnlockTracker: FpsUnlockTracker
 ) : Dumpable {
@@ -110,7 +111,7 @@
             handler,
             sensorProps,
             { reason -> onOrientationChanged(reason) },
-            BiometricOverlayConstants.REASON_UNKNOWN
+            BiometricRequestConstants.REASON_UNKNOWN
         )
 
     @VisibleForTesting val orientationListener = orientationReasonListener.orientationListener
@@ -169,25 +170,27 @@
             }
 
     init {
-        fpsUnlockTracker.startTracking()
-        fingerprintManager?.setSidefpsController(
-            object : ISidefpsController.Stub() {
-                override fun show(
-                    sensorId: Int,
-                    @BiometricOverlayConstants.ShowReason reason: Int
-                ) =
-                    if (reason.isReasonToAutoShow(activityTaskManager)) {
-                        show(SideFpsUiRequestSource.AUTO_SHOW, reason)
-                    } else {
-                        hide(SideFpsUiRequestSource.AUTO_SHOW)
-                    }
+        if (!SideFpsControllerRefactor.isEnabled) {
+            fpsUnlockTracker.startTracking()
+            fingerprintManager?.setSidefpsController(
+                object : ISidefpsController.Stub() {
+                    override fun show(
+                        sensorId: Int,
+                        @BiometricRequestConstants.RequestReason reason: Int
+                    ) =
+                        if (reason.isReasonToAutoShow(activityTaskManager)) {
+                            show(SideFpsUiRequestSource.AUTO_SHOW, reason)
+                        } else {
+                            hide(SideFpsUiRequestSource.AUTO_SHOW)
+                        }
 
-                override fun hide(sensorId: Int) = hide(SideFpsUiRequestSource.AUTO_SHOW)
-            }
-        )
-        listenForAlternateBouncerVisibility()
+                    override fun hide(sensorId: Int) = hide(SideFpsUiRequestSource.AUTO_SHOW)
+                }
+            )
+            listenForAlternateBouncerVisibility()
 
-        dumpManager.registerDumpable(this)
+            dumpManager.registerDumpable(this)
+        }
     }
 
     private fun listenForAlternateBouncerVisibility() {
@@ -195,7 +198,7 @@
             alternateBouncerInteractor.setAlternateBouncerUIAvailable(true, "SideFpsController")
         }
 
-        scope.launch {
+        applicationScope.launch {
             alternateBouncerInteractor.isVisible.collect { isVisible: Boolean ->
                 if (isVisible) {
                     show(SideFpsUiRequestSource.ALTERNATE_BOUNCER, REASON_AUTH_KEYGUARD)
@@ -209,8 +212,10 @@
     /** Shows the side fps overlay if not already shown. */
     fun show(
         request: SideFpsUiRequestSource,
-        @BiometricOverlayConstants.ShowReason reason: Int = BiometricOverlayConstants.REASON_UNKNOWN
+        @BiometricRequestConstants.RequestReason
+        reason: Int = BiometricRequestConstants.REASON_UNKNOWN
     ) {
+        SideFpsControllerRefactor.assertInLegacyMode()
         if (!displayStateInteractor.isInRearDisplayMode.value) {
             requests.add(request)
             mainExecutor.execute {
@@ -229,6 +234,7 @@
 
     /** Hides the fps overlay if shown. */
     fun hide(request: SideFpsUiRequestSource) {
+        SideFpsControllerRefactor.assertInLegacyMode()
         requests.remove(request)
         mainExecutor.execute {
             if (requests.isEmpty()) {
@@ -239,6 +245,7 @@
 
     /** Hide the arrow indicator. */
     fun hideIndicator() {
+        SideFpsControllerRefactor.assertInLegacyMode()
         val lottieAnimationView =
             overlayView?.findViewById(R.id.sidefps_animation) as LottieAnimationView?
         lottieAnimationView?.visibility = INVISIBLE
@@ -246,6 +253,7 @@
 
     /** Show the arrow indicator. */
     fun showIndicator() {
+        SideFpsControllerRefactor.assertInLegacyMode()
         val lottieAnimationView =
             overlayView?.findViewById(R.id.sidefps_animation) as LottieAnimationView?
         lottieAnimationView?.visibility = VISIBLE
@@ -279,13 +287,13 @@
         pw.println("currentRotation=${displayInfo.rotation}")
     }
 
-    private fun onOrientationChanged(@BiometricOverlayConstants.ShowReason reason: Int) {
+    private fun onOrientationChanged(@BiometricRequestConstants.RequestReason reason: Int) {
         if (overlayView != null) {
             createOverlayForDisplay(reason)
         }
     }
 
-    private fun createOverlayForDisplay(@BiometricOverlayConstants.ShowReason reason: Int) {
+    private fun createOverlayForDisplay(@BiometricRequestConstants.RequestReason reason: Int) {
         val view = layoutInflater.inflate(R.layout.sidefps_view, null, false)
         overlayView = view
         val display = context.display!!
@@ -395,7 +403,7 @@
 /** Returns [True] when the device has a side fingerprint sensor. */
 fun FingerprintManager?.hasSideFpsSensor(): Boolean = this?.sideFpsSensorProperties != null
 
-@BiometricOverlayConstants.ShowReason
+@BiometricRequestConstants.RequestReason
 private fun Int.isReasonToAutoShow(activityTaskManager: ActivityTaskManager): Boolean =
     when (this) {
         REASON_AUTH_KEYGUARD -> false
@@ -434,7 +442,7 @@
 
 private fun LottieAnimationView.addOverlayDynamicColor(
     context: Context,
-    @BiometricOverlayConstants.ShowReason reason: Int
+    @BiometricRequestConstants.RequestReason reason: Int
 ) {
     fun update() {
         val isKeyguard = reason == REASON_AUTH_KEYGUARD
@@ -501,7 +509,7 @@
     handler: Handler,
     sensorProps: FingerprintSensorPropertiesInternal,
     onOrientationChanged: (reason: Int) -> Unit,
-    @BiometricOverlayConstants.ShowReason var reason: Int
+    @BiometricRequestConstants.RequestReason var reason: Int
 ) {
     val orientationListener =
         BiometricDisplayListener(
@@ -516,7 +524,7 @@
 
 /**
  * The source of a request to show the side fps visual indicator. This is distinct from
- * [BiometricOverlayConstants] which corrresponds with the reason fingerprint authentication is
+ * [BiometricRequestConstants] which corresponds with the reason fingerprint authentication is
  * requested.
  */
 enum class SideFpsUiRequestSource {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsLottieViewWrapper.kt b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsIndicatorView.kt
similarity index 96%
rename from packages/SystemUI/src/com/android/systemui/biometrics/SideFpsLottieViewWrapper.kt
rename to packages/SystemUI/src/com/android/systemui/biometrics/SideFpsIndicatorView.kt
index e98f6db..d5e25ac 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsLottieViewWrapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsIndicatorView.kt
@@ -19,6 +19,6 @@
 import android.util.AttributeSet
 import com.android.systemui.util.wrapper.LottieViewWrapper
 
-class SideFpsLottieViewWrapper
+class SideFpsIndicatorView
 @JvmOverloads
 constructor(context: Context, attrs: AttributeSet? = null) : LottieViewWrapper(context, attrs)
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index bb6ef41..65668b5 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -19,10 +19,10 @@
 import static android.app.StatusBarManager.SESSION_BIOMETRIC_PROMPT;
 import static android.app.StatusBarManager.SESSION_KEYGUARD;
 import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_GOOD;
-import static android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_BP;
-import static android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_KEYGUARD;
-import static android.hardware.biometrics.BiometricOverlayConstants.REASON_ENROLL_ENROLLING;
-import static android.hardware.biometrics.BiometricOverlayConstants.REASON_ENROLL_FIND_SENSOR;
+import static android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_BP;
+import static android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_KEYGUARD;
+import static android.hardware.biometrics.BiometricRequestConstants.REASON_ENROLL_ENROLLING;
+import static android.hardware.biometrics.BiometricRequestConstants.REASON_ENROLL_FIND_SENSOR;
 
 import static com.android.internal.util.LatencyTracker.ACTION_UDFPS_ILLUMINATE;
 import static com.android.internal.util.Preconditions.checkNotNull;
@@ -106,6 +106,8 @@
 
 import dagger.Lazy;
 
+import kotlin.Unit;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -115,8 +117,6 @@
 import javax.inject.Inject;
 import javax.inject.Provider;
 
-import kotlin.Unit;
-
 import kotlinx.coroutines.ExperimentalCoroutinesApi;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
index 452cd6a..dae6d08 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
@@ -21,13 +21,13 @@
 import android.content.Context
 import android.graphics.PixelFormat
 import android.graphics.Rect
-import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_BP
-import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_KEYGUARD
-import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_OTHER
-import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_SETTINGS
-import android.hardware.biometrics.BiometricOverlayConstants.REASON_ENROLL_ENROLLING
-import android.hardware.biometrics.BiometricOverlayConstants.REASON_ENROLL_FIND_SENSOR
-import android.hardware.biometrics.BiometricOverlayConstants.ShowReason
+import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_BP
+import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_KEYGUARD
+import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_OTHER
+import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_SETTINGS
+import android.hardware.biometrics.BiometricRequestConstants.REASON_ENROLL_ENROLLING
+import android.hardware.biometrics.BiometricRequestConstants.REASON_ENROLL_FIND_SENSOR
+import android.hardware.biometrics.BiometricRequestConstants.RequestReason
 import android.hardware.fingerprint.IUdfpsOverlayControllerCallback
 import android.os.Build
 import android.os.RemoteException
@@ -96,7 +96,7 @@
     private val unlockedScreenOffAnimationController: UnlockedScreenOffAnimationController,
     private var udfpsDisplayModeProvider: UdfpsDisplayModeProvider,
     val requestId: Long,
-    @ShowReason val requestReason: Int,
+    @RequestReason val requestReason: Int,
     private val controllerCallback: IUdfpsOverlayControllerCallback,
     private val onTouch: (View, MotionEvent, Boolean) -> Boolean,
     private val activityLaunchAnimator: ActivityLaunchAnimator,
@@ -461,7 +461,7 @@
     }
 }
 
-@ShowReason
+@RequestReason
 private fun Int.isImportantForAccessibility() =
     this == REASON_ENROLL_FIND_SENSOR ||
             this == REASON_ENROLL_ENROLLING ||
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerLegacy.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerLegacy.kt
index a2ac66f..63fe26a 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerLegacy.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerLegacy.kt
@@ -197,11 +197,42 @@
                 listenForGoneToAodTransition(this)
                 listenForLockscreenAodTransitions(this)
                 listenForAodToOccludedTransitions(this)
+                listenForAlternateBouncerToAodTransitions(this)
+                listenForDreamingToAodTransitions(this)
             }
         }
     }
 
     @VisibleForTesting
+    suspend fun listenForDreamingToAodTransitions(scope: CoroutineScope): Job {
+        return scope.launch {
+            transitionInteractor.transition(KeyguardState.DREAMING, KeyguardState.AOD).collect {
+                transitionStep ->
+                view.onDozeAmountChanged(
+                    transitionStep.value,
+                    transitionStep.value,
+                    ANIMATE_APPEAR_ON_SCREEN_OFF,
+                )
+            }
+        }
+    }
+
+    @VisibleForTesting
+    suspend fun listenForAlternateBouncerToAodTransitions(scope: CoroutineScope): Job {
+        return scope.launch {
+            transitionInteractor
+                .transition(KeyguardState.ALTERNATE_BOUNCER, KeyguardState.AOD)
+                .collect { transitionStep ->
+                    view.onDozeAmountChanged(
+                        transitionStep.value,
+                        transitionStep.value,
+                        UdfpsKeyguardViewLegacy.ANIMATION_BETWEEN_AOD_AND_LOCKSCREEN,
+                    )
+                }
+        }
+    }
+
+    @VisibleForTesting
     suspend fun listenForAodToOccludedTransitions(scope: CoroutineScope): Job {
         return scope.launch {
             transitionInteractor.transition(KeyguardState.AOD, KeyguardState.OCCLUDED).collect {
@@ -246,7 +277,10 @@
     suspend fun listenForLockscreenAodTransitions(scope: CoroutineScope): Job {
         return scope.launch {
             transitionInteractor.dozeAmountTransition.collect { transitionStep ->
-                if (transitionStep.transitionState == TransitionState.CANCELED) {
+                if (
+                    transitionStep.from == KeyguardState.AOD &&
+                        transitionStep.transitionState == TransitionState.CANCELED
+                ) {
                     if (
                         transitionInteractor.startedKeyguardTransitionStep.first().to !=
                             KeyguardState.AOD
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsShell.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsShell.kt
index e3dbcb5..88b9e1b 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsShell.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsShell.kt
@@ -18,13 +18,13 @@
 
 import android.content.Context
 import android.graphics.Rect
-import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_BP
-import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_KEYGUARD
-import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_OTHER
-import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_SETTINGS
-import android.hardware.biometrics.BiometricOverlayConstants.REASON_ENROLL_ENROLLING
-import android.hardware.biometrics.BiometricOverlayConstants.REASON_ENROLL_FIND_SENSOR
-import android.hardware.biometrics.BiometricOverlayConstants.REASON_UNKNOWN
+import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_BP
+import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_KEYGUARD
+import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_OTHER
+import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_SETTINGS
+import android.hardware.biometrics.BiometricRequestConstants.REASON_ENROLL_ENROLLING
+import android.hardware.biometrics.BiometricRequestConstants.REASON_ENROLL_FIND_SENSOR
+import android.hardware.biometrics.BiometricRequestConstants.REASON_UNKNOWN
 import android.hardware.fingerprint.IUdfpsOverlayControllerCallback
 import android.util.Log
 import android.view.LayoutInflater
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/dagger/BiometricsModule.kt b/packages/SystemUI/src/com/android/systemui/biometrics/dagger/BiometricsModule.kt
index 72fcfe7..8ae6f87 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/dagger/BiometricsModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/dagger/BiometricsModule.kt
@@ -18,8 +18,11 @@
 
 import android.content.res.Resources
 import com.android.internal.R
+import com.android.systemui.CoreStartable
 import com.android.systemui.biometrics.EllipseOverlapDetectorParams
 import com.android.systemui.biometrics.UdfpsUtils
+import com.android.systemui.biometrics.data.repository.BiometricStatusRepository
+import com.android.systemui.biometrics.data.repository.BiometricStatusRepositoryImpl
 import com.android.systemui.biometrics.data.repository.DisplayStateRepository
 import com.android.systemui.biometrics.data.repository.DisplayStateRepositoryImpl
 import com.android.systemui.biometrics.data.repository.FacePropertyRepository
@@ -33,11 +36,14 @@
 import com.android.systemui.biometrics.udfps.BoundingBoxOverlapDetector
 import com.android.systemui.biometrics.udfps.EllipseOverlapDetector
 import com.android.systemui.biometrics.udfps.OverlapDetector
+import com.android.systemui.biometrics.ui.binder.SideFpsOverlayViewBinder
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.util.concurrency.ThreadFactory
 import dagger.Binds
 import dagger.Module
 import dagger.Provides
+import dagger.multibindings.ClassKey
+import dagger.multibindings.IntoMap
 import java.util.concurrent.Executor
 import javax.inject.Qualifier
 
@@ -46,6 +52,11 @@
 interface BiometricsModule {
 
     @Binds
+    @IntoMap
+    @ClassKey(SideFpsOverlayViewBinder::class)
+    fun bindsSideFpsOverlayViewBinder(viewBinder: SideFpsOverlayViewBinder): CoreStartable
+
+    @Binds
     @SysUISingleton
     fun faceSettings(impl: FaceSettingsRepositoryImpl): FaceSettingsRepository
 
@@ -57,6 +68,10 @@
 
     @Binds
     @SysUISingleton
+    fun biometricStatusRepository(impl: BiometricStatusRepositoryImpl): BiometricStatusRepository
+
+    @Binds
+    @SysUISingleton
     fun fingerprintRepository(
         impl: FingerprintPropertyRepositoryImpl
     ): FingerprintPropertyRepository
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/BiometricStatusRepository.kt b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/BiometricStatusRepository.kt
new file mode 100644
index 0000000..ad2136a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/BiometricStatusRepository.kt
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.biometrics.data.repository
+
+import android.hardware.biometrics.AuthenticationStateListener
+import android.hardware.biometrics.BiometricManager
+import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_BP
+import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_KEYGUARD
+import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_OTHER
+import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_SETTINGS
+import android.hardware.biometrics.BiometricRequestConstants.REASON_ENROLL_ENROLLING
+import android.hardware.biometrics.BiometricRequestConstants.REASON_ENROLL_FIND_SENSOR
+import com.android.systemui.biometrics.shared.model.AuthenticationReason
+import com.android.systemui.biometrics.shared.model.AuthenticationReason.SettingsOperations
+import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.shareIn
+
+/** A repository for the state of biometric authentication. */
+interface BiometricStatusRepository {
+    /**
+     * The logical reason for the current fingerprint auth operation if one is on-going, otherwise
+     * [NotRunning].
+     */
+    val fingerprintAuthenticationReason: Flow<AuthenticationReason>
+}
+
+@SysUISingleton
+class BiometricStatusRepositoryImpl
+@Inject
+constructor(
+    @Application private val applicationScope: CoroutineScope,
+    private val biometricManager: BiometricManager?
+) : BiometricStatusRepository {
+
+    override val fingerprintAuthenticationReason: Flow<AuthenticationReason> =
+        conflatedCallbackFlow {
+                val updateFingerprintAuthenticateReason = { reason: AuthenticationReason ->
+                    trySendWithFailureLogging(
+                        reason,
+                        TAG,
+                        "Error sending fingerprintAuthenticateReason reason"
+                    )
+                }
+
+                val authenticationStateListener =
+                    object : AuthenticationStateListener.Stub() {
+                        override fun onAuthenticationStarted(requestReason: Int) {
+                            val authenticationReason =
+                                when (requestReason) {
+                                    REASON_AUTH_BP ->
+                                        AuthenticationReason.BiometricPromptAuthentication
+                                    REASON_AUTH_KEYGUARD ->
+                                        AuthenticationReason.DeviceEntryAuthentication
+                                    REASON_AUTH_OTHER -> AuthenticationReason.OtherAuthentication
+                                    REASON_AUTH_SETTINGS ->
+                                        AuthenticationReason.SettingsAuthentication(
+                                            SettingsOperations.OTHER
+                                        )
+                                    REASON_ENROLL_ENROLLING ->
+                                        AuthenticationReason.SettingsAuthentication(
+                                            SettingsOperations.ENROLL_ENROLLING
+                                        )
+                                    REASON_ENROLL_FIND_SENSOR ->
+                                        AuthenticationReason.SettingsAuthentication(
+                                            SettingsOperations.ENROLL_FIND_SENSOR
+                                        )
+                                    else -> AuthenticationReason.Unknown
+                                }
+                            updateFingerprintAuthenticateReason(authenticationReason)
+                        }
+
+                        override fun onAuthenticationStopped() {
+                            updateFingerprintAuthenticateReason(AuthenticationReason.NotRunning)
+                        }
+                    }
+
+                updateFingerprintAuthenticateReason(AuthenticationReason.NotRunning)
+                biometricManager?.registerAuthenticationStateListener(authenticationStateListener)
+                awaitClose {
+                    biometricManager?.unregisterAuthenticationStateListener(
+                        authenticationStateListener
+                    )
+                }
+            }
+            .shareIn(applicationScope, started = SharingStarted.Eagerly, replay = 1)
+
+    companion object {
+        private const val TAG = "BiometricStatusRepositoryImpl"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/domain/BiometricsDomainLayerModule.kt b/packages/SystemUI/src/com/android/systemui/biometrics/domain/BiometricsDomainLayerModule.kt
index b9b2fd8..ec3fd9f 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/domain/BiometricsDomainLayerModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/domain/BiometricsDomainLayerModule.kt
@@ -15,6 +15,8 @@
  */
 package com.android.systemui.biometrics.domain
 
+import com.android.systemui.biometrics.domain.interactor.BiometricStatusInteractor
+import com.android.systemui.biometrics.domain.interactor.BiometricStatusInteractorImpl
 import com.android.systemui.biometrics.domain.interactor.CredentialInteractor
 import com.android.systemui.biometrics.domain.interactor.CredentialInteractorImpl
 import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor
@@ -38,6 +40,12 @@
 
     @Binds
     @SysUISingleton
+    fun providesBiometricStatusInteractor(
+        impl: BiometricStatusInteractorImpl
+    ): BiometricStatusInteractor
+
+    @Binds
+    @SysUISingleton
     fun providesCredentialInteractor(impl: CredentialInteractorImpl): CredentialInteractor
 
     @Binds
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/BiometricStatusInteractor.kt b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/BiometricStatusInteractor.kt
new file mode 100644
index 0000000..55a2d3d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/BiometricStatusInteractor.kt
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.biometrics.domain.interactor
+
+import android.app.ActivityTaskManager
+import com.android.systemui.biometrics.data.repository.BiometricStatusRepository
+import com.android.systemui.biometrics.shared.model.AuthenticationReason
+import com.android.systemui.biometrics.shared.model.AuthenticationReason.SettingsOperations
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
+
+/** Encapsulates business logic for interacting with biometric authentication state. */
+interface BiometricStatusInteractor {
+    /**
+     * The logical reason for the current side fingerprint sensor auth operation if one is on-going,
+     * filtered for when the overlay should be shown, otherwise [NotRunning].
+     */
+    val sfpsAuthenticationReason: Flow<AuthenticationReason>
+}
+
+class BiometricStatusInteractorImpl
+@Inject
+constructor(
+    private val activityTaskManager: ActivityTaskManager,
+    biometricStatusRepository: BiometricStatusRepository,
+) : BiometricStatusInteractor {
+
+    override val sfpsAuthenticationReason: Flow<AuthenticationReason> =
+        biometricStatusRepository.fingerprintAuthenticationReason.map { reason: AuthenticationReason
+            ->
+            if (reason.isReasonToAlwaysUpdateSfpsOverlay(activityTaskManager)) {
+                reason
+            } else {
+                AuthenticationReason.NotRunning
+            }
+        }
+
+    companion object {
+        private const val TAG = "BiometricStatusInteractor"
+    }
+}
+
+/** True if the sfps overlay should always be updated for this request source, false otherwise. */
+private fun AuthenticationReason.isReasonToAlwaysUpdateSfpsOverlay(
+    activityTaskManager: ActivityTaskManager
+): Boolean =
+    when (this) {
+        AuthenticationReason.DeviceEntryAuthentication -> false
+        AuthenticationReason.SettingsAuthentication(SettingsOperations.OTHER) ->
+            when (activityTaskManager.topClass()) {
+                // TODO(b/186176653): exclude fingerprint overlays from this list view
+                "com.android.settings.biometrics.fingerprint.FingerprintSettings" -> false
+                else -> true
+            }
+        else -> true
+    }
+
+internal fun ActivityTaskManager.topClass(): String =
+    getTasks(1).firstOrNull()?.topActivity?.className ?: ""
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/SideFpsSensorInteractor.kt b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/SideFpsSensorInteractor.kt
index f513799..f4231ac 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/SideFpsSensorInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/SideFpsSensorInteractor.kt
@@ -141,7 +141,6 @@
                             }
                         }
                     }
-
                 SideFpsSensorLocation(
                     left = sensorLeft,
                     top = sensorTop,
@@ -149,7 +148,15 @@
                     isSensorVerticalInDefaultOrientation = isSensorVerticalInDefaultOrientation
                 )
             }
-            .distinctUntilChanged()
+            .distinctUntilChanged(
+                areEquivalent = { old: SideFpsSensorLocation, new: SideFpsSensorLocation ->
+                    old.left == new.left &&
+                        old.top == new.top &&
+                        old.length == new.length &&
+                        old.isSensorVerticalInDefaultOrientation ==
+                            new.isSensorVerticalInDefaultOrientation
+                }
+            )
             .onEach {
                 logger.sensorLocationStateChanged(
                     it.left,
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/shared/SideFpsControllerRefactor.kt b/packages/SystemUI/src/com/android/systemui/biometrics/shared/SideFpsControllerRefactor.kt
new file mode 100644
index 0000000..899b07e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/shared/SideFpsControllerRefactor.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.biometrics.shared
+
+import com.android.systemui.flags.FlagToken
+import com.android.systemui.flags.RefactorFlagUtils
+import com.android.systemui.shared.Flags
+
+/** Helper for reading or using the sidefps controller refactor flag state. */
+@Suppress("NOTHING_TO_INLINE")
+object SideFpsControllerRefactor {
+    /** The aconfig flag name */
+    const val FLAG_NAME = Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
+
+    /** A token used for dependency declaration */
+    val token: FlagToken
+        get() = FlagToken(FLAG_NAME, isEnabled)
+
+    /** Is the refactor enabled */
+    @JvmStatic
+    inline val isEnabled
+        get() = Flags.sidefpsControllerRefactor()
+
+    /**
+     * 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/biometrics/shared/model/AuthenticationReason.kt b/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/AuthenticationReason.kt
new file mode 100644
index 0000000..0c3debbe
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/AuthenticationReason.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.biometrics.shared.model
+
+/**
+ * The logical reason for a fingerprint auth operation if one is on-going, otherwise [NotRunning].
+ */
+sealed interface AuthenticationReason {
+    /** Device entry requested authentication */
+    data object DeviceEntryAuthentication : AuthenticationReason
+
+    /** Settings requested authentication */
+    data class SettingsAuthentication(val settingsOperation: SettingsOperations) :
+        AuthenticationReason
+
+    /** App requested authentication */
+    data object BiometricPromptAuthentication : AuthenticationReason
+
+    /** Authentication requested for other reason */
+    data object OtherAuthentication : AuthenticationReason
+
+    /** Authentication requested for unknown reason */
+    data object Unknown : AuthenticationReason
+
+    /** Authentication is not running */
+    data object NotRunning : AuthenticationReason
+
+    /** Settings operations that request biometric authentication */
+    enum class SettingsOperations {
+        ENROLL_ENROLLING,
+        ENROLL_FIND_SENSOR,
+        OTHER
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsLottieViewWrapper.kt b/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/LottieCallback.kt
similarity index 66%
copy from packages/SystemUI/src/com/android/systemui/biometrics/SideFpsLottieViewWrapper.kt
copy to packages/SystemUI/src/com/android/systemui/biometrics/shared/model/LottieCallback.kt
index e98f6db..0b30055 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsLottieViewWrapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/LottieCallback.kt
@@ -13,12 +13,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.systemui.biometrics
 
-import android.content.Context
-import android.util.AttributeSet
-import com.android.systemui.util.wrapper.LottieViewWrapper
+package com.android.systemui.biometrics.shared.model
 
-class SideFpsLottieViewWrapper
-@JvmOverloads
-constructor(context: Context, attrs: AttributeSet? = null) : LottieViewWrapper(context, attrs)
+import com.airbnb.lottie.model.KeyPath
+
+/** Represents properties of a LottieAnimationView callback */
+data class LottieCallback(val keypath: KeyPath, val color: Int)
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
index 32d9067..90e4a38 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
@@ -376,6 +376,22 @@
                     }
                 }
 
+                // Talkback directional guidance
+                backgroundView.setOnHoverListener { _, event ->
+                    launch {
+                        viewModel.onAnnounceAccessibilityHint(
+                            event,
+                            accessibilityManager.isTouchExplorationEnabled
+                        )
+                    }
+                    false
+                }
+                launch {
+                    viewModel.accessibilityHint.collect { message ->
+                        if (message.isNotBlank()) view.announceForAccessibility(message)
+                    }
+                }
+
                 // Play haptics
                 launch {
                     viewModel.hapticsToPlay.collect { hapticFeedbackConstant ->
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt
new file mode 100644
index 0000000..a8c9446
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.biometrics.ui.binder
+
+import android.content.Context
+import android.graphics.PorterDuff
+import android.graphics.PorterDuffColorFilter
+import android.view.LayoutInflater
+import android.view.View
+import android.view.WindowManager
+import android.view.accessibility.AccessibilityEvent
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.repeatOnLifecycle
+import com.airbnb.lottie.LottieAnimationView
+import com.airbnb.lottie.LottieComposition
+import com.airbnb.lottie.LottieProperty
+import com.android.app.animation.Interpolators
+import com.android.keyguard.KeyguardPINView
+import com.android.systemui.CoreStartable
+import com.android.systemui.biometrics.FpsUnlockTracker
+import com.android.systemui.biometrics.domain.interactor.BiometricStatusInteractor
+import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor
+import com.android.systemui.biometrics.domain.interactor.SideFpsSensorInteractor
+import com.android.systemui.biometrics.shared.SideFpsControllerRefactor
+import com.android.systemui.biometrics.shared.model.AuthenticationReason.NotRunning
+import com.android.systemui.biometrics.shared.model.LottieCallback
+import com.android.systemui.biometrics.ui.viewmodel.SideFpsOverlayViewModel
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.keyguard.domain.interactor.DeviceEntrySideFpsOverlayInteractor
+import com.android.systemui.keyguard.ui.viewmodel.SideFpsProgressBarViewModel
+import com.android.systemui.lifecycle.repeatWhenAttached
+import com.android.systemui.res.R
+import com.android.systemui.util.kotlin.sample
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.launch
+
+/** Binds the side fingerprint sensor indicator view to [SideFpsOverlayViewModel]. */
+@SysUISingleton
+class SideFpsOverlayViewBinder
+@Inject
+constructor(
+    @Application private val applicationScope: CoroutineScope,
+    @Application private val applicationContext: Context,
+    private val biometricStatusInteractor: BiometricStatusInteractor,
+    private val displayStateInteractor: DisplayStateInteractor,
+    private val deviceEntrySideFpsOverlayInteractor: DeviceEntrySideFpsOverlayInteractor,
+    private val fpsUnlockTracker: FpsUnlockTracker,
+    private val layoutInflater: LayoutInflater,
+    private val sideFpsProgressBarViewModel: SideFpsProgressBarViewModel,
+    private val sfpsSensorInteractor: SideFpsSensorInteractor,
+    private val windowManager: WindowManager
+) : CoreStartable {
+
+    override fun start() {
+        if (!SideFpsControllerRefactor.isEnabled) {
+            return
+        }
+        applicationScope
+            .launch {
+                combine(
+                        biometricStatusInteractor.sfpsAuthenticationReason,
+                        deviceEntrySideFpsOverlayInteractor.showIndicatorForDeviceEntry,
+                        sideFpsProgressBarViewModel.isVisible,
+                        ::Triple
+                    )
+                    .sample(displayStateInteractor.isInRearDisplayMode, ::Pair)
+                    .collect { (combinedFlows, isInRearDisplayMode: Boolean) ->
+                        val (
+                            systemServerAuthReason,
+                            showIndicatorForDeviceEntry,
+                            progressBarIsVisible) =
+                            combinedFlows
+                        if (!isInRearDisplayMode) {
+                            if (progressBarIsVisible) {
+                                hide()
+                            } else if (systemServerAuthReason != NotRunning) {
+                                show()
+                            } else if (showIndicatorForDeviceEntry) {
+                                show()
+                            } else {
+                                hide()
+                            }
+                        }
+                    }
+            }
+            .invokeOnCompletion { fpsUnlockTracker.stopTracking() }
+    }
+
+    private var overlayView: View? = null
+    private var lottie: LottieAnimationView? = null
+
+    /** Show the side fingerprint sensor indicator */
+    private fun show() {
+        overlayView?.let {
+            if (it.isAttachedToWindow) {
+                lottie = it.requireViewById<LottieAnimationView>(R.id.sidefps_animation)
+                lottie?.pauseAnimation()
+                windowManager.removeView(it)
+            }
+        }
+
+        overlayView = layoutInflater.inflate(R.layout.sidefps_view, null, false)
+        val overlayViewModel =
+            SideFpsOverlayViewModel(
+                applicationContext,
+                biometricStatusInteractor,
+                deviceEntrySideFpsOverlayInteractor,
+                displayStateInteractor,
+                sfpsSensorInteractor,
+                sideFpsProgressBarViewModel
+            )
+        bind(overlayView!!, overlayViewModel, fpsUnlockTracker, windowManager)
+        overlayView!!.visibility = View.INVISIBLE
+        windowManager.addView(overlayView, overlayViewModel.defaultOverlayViewParams)
+    }
+
+    /** Hide the side fingerprint sensor indicator */
+    private fun hide() {
+        if (overlayView != null) {
+            windowManager.removeView(overlayView)
+            overlayView = null
+        }
+    }
+
+    companion object {
+        private const val TAG = "SideFpsOverlayViewBinder"
+
+        /** Binds overlayView (side fingerprint sensor indicator view) to SideFpsOverlayViewModel */
+        fun bind(
+            overlayView: View,
+            viewModel: SideFpsOverlayViewModel,
+            fpsUnlockTracker: FpsUnlockTracker,
+            windowManager: WindowManager
+        ) {
+            overlayView.repeatWhenAttached {
+                fpsUnlockTracker.startTracking()
+
+                val lottie = it.requireViewById<LottieAnimationView>(R.id.sidefps_animation)
+                lottie.addLottieOnCompositionLoadedListener { composition: LottieComposition ->
+                    viewModel.setLottieBounds(composition.bounds)
+                    overlayView.visibility = View.VISIBLE
+                }
+                it.alpha = 0f
+                val overlayShowAnimator =
+                    it.animate()
+                        .alpha(1f)
+                        .setDuration(KeyguardPINView.ANIMATION_DURATION)
+                        .setInterpolator(Interpolators.ALPHA_IN)
+
+                overlayShowAnimator.start()
+
+                it.setAccessibilityDelegate(
+                    object : View.AccessibilityDelegate() {
+                        override fun dispatchPopulateAccessibilityEvent(
+                            host: View,
+                            event: AccessibilityEvent
+                        ): Boolean {
+                            return if (
+                                event.getEventType() ===
+                                    android.view.accessibility.AccessibilityEvent
+                                        .TYPE_WINDOW_STATE_CHANGED
+                            ) {
+                                true
+                            } else {
+                                super.dispatchPopulateAccessibilityEvent(host, event)
+                            }
+                        }
+                    }
+                )
+
+                repeatOnLifecycle(Lifecycle.State.STARTED) {
+                    launch {
+                        viewModel.lottieCallbacks.collect { callbacks ->
+                            lottie.addOverlayDynamicColor(callbacks)
+                        }
+                    }
+
+                    launch {
+                        viewModel.overlayViewParams.collect { params ->
+                            windowManager.updateViewLayout(it, params)
+                            lottie.resumeAnimation()
+                        }
+                    }
+
+                    launch {
+                        viewModel.overlayViewProperties.collect { properties ->
+                            it.rotation = properties.overlayViewRotation
+                            lottie.setAnimation(properties.indicatorAsset)
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+private fun LottieAnimationView.addOverlayDynamicColor(colorCallbacks: List<LottieCallback>) {
+    addLottieOnCompositionLoadedListener {
+        for (callback in colorCallbacks) {
+            addValueCallback(callback.keypath, LottieProperty.COLOR_FILTER) {
+                PorterDuffColorFilter(callback.color, PorterDuff.Mode.SRC_ATOP)
+            }
+        }
+        resumeAnimation()
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
index 647aaf3..6d0a58e 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
@@ -21,9 +21,12 @@
 import android.util.Log
 import android.view.HapticFeedbackConstants
 import android.view.MotionEvent
+import com.android.systemui.Flags.bpTalkback
+import com.android.systemui.biometrics.UdfpsUtils
 import com.android.systemui.biometrics.Utils
 import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor
 import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractor
+import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor
 import com.android.systemui.biometrics.shared.model.BiometricModalities
 import com.android.systemui.biometrics.shared.model.BiometricModality
 import com.android.systemui.biometrics.shared.model.DisplayRotation
@@ -35,7 +38,9 @@
 import kotlinx.coroutines.coroutineScope
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableSharedFlow
 import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asSharedFlow
 import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.distinctUntilChanged
@@ -49,7 +54,9 @@
 constructor(
     displayStateInteractor: DisplayStateInteractor,
     promptSelectorInteractor: PromptSelectorInteractor,
-    @Application context: Context,
+    @Application private val context: Context,
+    private val udfpsOverlayInteractor: UdfpsOverlayInteractor,
+    private val udfpsUtils: UdfpsUtils
 ) {
     /** The set of modalities available for this prompt */
     val modalities: Flow<BiometricModalities> =
@@ -69,6 +76,11 @@
     val faceIconHeight: Int =
         context.resources.getDimensionPixelSize(R.dimen.biometric_dialog_face_icon_size)
 
+    private val _accessibilityHint = MutableSharedFlow<String>()
+
+    /** Hint for talkback directional guidance */
+    val accessibilityHint: Flow<String> = _accessibilityHint.asSharedFlow()
+
     private val _isAuthenticating: MutableStateFlow<Boolean> = MutableStateFlow(false)
 
     /** If the user is currently authenticating (i.e. at least one biometric is scanning). */
@@ -516,6 +528,40 @@
         return false
     }
 
+    /** Sets the message used for UDFPS directional guidance */
+    suspend fun onAnnounceAccessibilityHint(
+        event: MotionEvent,
+        touchExplorationEnabled: Boolean,
+    ): Boolean {
+        if (bpTalkback() && modalities.first().hasUdfps && touchExplorationEnabled) {
+            // TODO(b/315184924): Remove uses of UdfpsUtils
+            val scaledTouch =
+                udfpsUtils.getTouchInNativeCoordinates(
+                    event.getPointerId(0),
+                    event,
+                    udfpsOverlayInteractor.udfpsOverlayParams.value
+                )
+            if (
+                !udfpsUtils.isWithinSensorArea(
+                    event.getPointerId(0),
+                    event,
+                    udfpsOverlayInteractor.udfpsOverlayParams.value
+                )
+            ) {
+                _accessibilityHint.emit(
+                    udfpsUtils.onTouchOutsideOfSensorArea(
+                        touchExplorationEnabled,
+                        context,
+                        scaledTouch.x,
+                        scaledTouch.y,
+                        udfpsOverlayInteractor.udfpsOverlayParams.value
+                    )
+                )
+            }
+        }
+        return false
+    }
+
     /**
      * Switch to the credential view.
      *
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModel.kt
new file mode 100644
index 0000000..ce72603
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModel.kt
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.biometrics.ui.viewmodel
+
+import android.content.Context
+import android.content.res.Configuration
+import android.graphics.Color
+import android.graphics.PixelFormat
+import android.graphics.Point
+import android.graphics.Rect
+import android.view.Gravity
+import android.view.WindowManager
+import android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION
+import android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY
+import com.airbnb.lottie.model.KeyPath
+import com.android.systemui.biometrics.Utils
+import com.android.systemui.biometrics.domain.interactor.BiometricStatusInteractor
+import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor
+import com.android.systemui.biometrics.domain.interactor.SideFpsSensorInteractor
+import com.android.systemui.biometrics.domain.model.SideFpsSensorLocation
+import com.android.systemui.biometrics.shared.model.AuthenticationReason
+import com.android.systemui.biometrics.shared.model.DisplayRotation
+import com.android.systemui.biometrics.shared.model.LottieCallback
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.keyguard.domain.interactor.DeviceEntrySideFpsOverlayInteractor
+import com.android.systemui.keyguard.ui.viewmodel.SideFpsProgressBarViewModel
+import com.android.systemui.res.R
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
+
+/** Models UI of the side fingerprint sensor indicator view. */
+class SideFpsOverlayViewModel
+@Inject
+constructor(
+    @Application private val applicationContext: Context,
+    biometricStatusInteractor: BiometricStatusInteractor,
+    deviceEntrySideFpsOverlayInteractor: DeviceEntrySideFpsOverlayInteractor,
+    displayStateInteractor: DisplayStateInteractor,
+    sfpsSensorInteractor: SideFpsSensorInteractor,
+    sideFpsProgressBarViewModel: SideFpsProgressBarViewModel
+) {
+    /** Contains properties of the side fingerprint sensor indicator */
+    data class OverlayViewProperties(
+        /** The raw asset for the indicator animation */
+        val indicatorAsset: Int,
+        /** Rotation of the overlayView */
+        val overlayViewRotation: Float,
+    )
+
+    private val _lottieBounds: MutableStateFlow<Rect?> = MutableStateFlow(null)
+
+    /** Used for setting lottie bounds once the composition has loaded. */
+    fun setLottieBounds(bounds: Rect) {
+        _lottieBounds.value = bounds
+    }
+
+    private val displayRotation = displayStateInteractor.currentRotation
+    private val sensorLocation = sfpsSensorInteractor.sensorLocation
+
+    /** Default LayoutParams for the overlayView */
+    val defaultOverlayViewParams: WindowManager.LayoutParams
+        get() =
+            WindowManager.LayoutParams(
+                    WindowManager.LayoutParams.WRAP_CONTENT,
+                    WindowManager.LayoutParams.WRAP_CONTENT,
+                    WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
+                    Utils.FINGERPRINT_OVERLAY_LAYOUT_PARAM_FLAGS,
+                    PixelFormat.TRANSLUCENT
+                )
+                .apply {
+                    title = TAG
+                    fitInsetsTypes = 0 // overrides default, avoiding status bars during layout
+                    gravity = Gravity.TOP or Gravity.LEFT
+                    layoutInDisplayCutoutMode =
+                        WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
+                    privateFlags = PRIVATE_FLAG_TRUSTED_OVERLAY or PRIVATE_FLAG_NO_MOVE_ANIMATION
+                }
+
+    private val indicatorAsset: Flow<Int> =
+        combine(displayRotation, sensorLocation) { rotation: DisplayRotation, sensorLocation ->
+                val yAligned = sensorLocation.isSensorVerticalInDefaultOrientation
+                val newAsset: Int =
+                    when (rotation) {
+                        DisplayRotation.ROTATION_0 ->
+                            if (yAligned) {
+                                R.raw.sfps_pulse
+                            } else {
+                                R.raw.sfps_pulse_landscape
+                            }
+                        DisplayRotation.ROTATION_180 ->
+                            if (yAligned) {
+                                R.raw.sfps_pulse
+                            } else {
+                                R.raw.sfps_pulse_landscape
+                            }
+                        else ->
+                            if (yAligned) {
+                                R.raw.sfps_pulse_landscape
+                            } else {
+                                R.raw.sfps_pulse
+                            }
+                    }
+                newAsset
+            }
+            .distinctUntilChanged()
+
+    private val overlayViewRotation: Flow<Float> =
+        combine(
+                displayRotation,
+                sensorLocation,
+            ) { rotation: DisplayRotation, sensorLocation ->
+                val yAligned = sensorLocation.isSensorVerticalInDefaultOrientation
+                when (rotation) {
+                    DisplayRotation.ROTATION_90 -> if (yAligned) 0f else 180f
+                    DisplayRotation.ROTATION_180 -> 180f
+                    DisplayRotation.ROTATION_270 -> if (yAligned) 180f else 0f
+                    else -> 0f
+                }
+            }
+            .distinctUntilChanged()
+
+    /** Contains properties (animation asset and view rotation) for overlayView */
+    val overlayViewProperties: Flow<OverlayViewProperties> =
+        combine(indicatorAsset, overlayViewRotation) { asset: Int, rotation: Float ->
+            OverlayViewProperties(asset, rotation)
+        }
+
+    /** LayoutParams for placement of overlayView (the side fingerprint sensor indicator view) */
+    val overlayViewParams: Flow<WindowManager.LayoutParams> =
+        combine(
+            _lottieBounds,
+            sensorLocation,
+            displayRotation,
+        ) { bounds: Rect?, sensorLocation: SideFpsSensorLocation, displayRotation: DisplayRotation
+            ->
+            val topLeft = Point(sensorLocation.left, sensorLocation.top)
+
+            if (sensorLocation.isSensorVerticalInDefaultOrientation) {
+                if (displayRotation == DisplayRotation.ROTATION_0) {
+                    topLeft.x -= bounds!!.width()
+                } else if (displayRotation == DisplayRotation.ROTATION_270) {
+                    topLeft.y -= bounds!!.height()
+                }
+            } else {
+                if (displayRotation == DisplayRotation.ROTATION_180) {
+                    topLeft.y -= bounds!!.height()
+                } else if (displayRotation == DisplayRotation.ROTATION_270) {
+                    topLeft.x -= bounds!!.width()
+                }
+            }
+            defaultOverlayViewParams.apply {
+                x = topLeft.x
+                y = topLeft.y
+            }
+        }
+
+    /** List of LottieCallbacks use for adding dynamic color to the overlayView */
+    val lottieCallbacks: Flow<List<LottieCallback>> =
+        combine(
+            biometricStatusInteractor.sfpsAuthenticationReason,
+            deviceEntrySideFpsOverlayInteractor.showIndicatorForDeviceEntry.distinctUntilChanged(),
+            sideFpsProgressBarViewModel.isVisible,
+        ) { reason: AuthenticationReason, showIndicatorForDeviceEntry: Boolean, progressBarIsVisible
+            ->
+            val callbacks = mutableListOf<LottieCallback>()
+            if (showIndicatorForDeviceEntry) {
+                val indicatorColor =
+                    com.android.settingslib.Utils.getColorAttrDefaultColor(
+                        applicationContext,
+                        com.android.internal.R.attr.materialColorPrimaryFixed
+                    )
+                val outerRimColor =
+                    com.android.settingslib.Utils.getColorAttrDefaultColor(
+                        applicationContext,
+                        com.android.internal.R.attr.materialColorPrimaryFixedDim
+                    )
+                val chevronFill =
+                    com.android.settingslib.Utils.getColorAttrDefaultColor(
+                        applicationContext,
+                        com.android.internal.R.attr.materialColorOnPrimaryFixed
+                    )
+                callbacks.add(LottieCallback(KeyPath(".blue600", "**"), indicatorColor))
+                callbacks.add(LottieCallback(KeyPath(".blue400", "**"), outerRimColor))
+                callbacks.add(LottieCallback(KeyPath(".black", "**"), chevronFill))
+            } else {
+                if (!isDarkMode(applicationContext)) {
+                    callbacks.add(LottieCallback(KeyPath(".black", "**"), Color.WHITE))
+                }
+                for (key in listOf(".blue600", ".blue400")) {
+                    callbacks.add(
+                        LottieCallback(
+                            KeyPath(key, "**"),
+                            applicationContext.getColor(
+                                com.android.settingslib.color.R.color.settingslib_color_blue400
+                            ),
+                        )
+                    )
+                }
+            }
+            callbacks
+        }
+
+    companion object {
+        private const val TAG = "SideFpsOverlayViewModel"
+    }
+}
+
+private fun isDarkMode(context: Context): Boolean {
+    val darkMode = context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
+    return darkMode == Configuration.UI_MODE_NIGHT_YES
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/KeyguardBouncerRepository.kt b/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/KeyguardBouncerRepository.kt
index 1e0e16c..c2a1d8f 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/KeyguardBouncerRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/KeyguardBouncerRepository.kt
@@ -18,6 +18,7 @@
 
 import android.os.Build
 import android.util.Log
+import com.android.systemui.biometrics.shared.SideFpsControllerRefactor
 import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN
 import com.android.systemui.bouncer.shared.model.BouncerShowMessageModel
 import com.android.systemui.dagger.SysUISingleton
@@ -121,6 +122,7 @@
 
     fun setAlternateBouncerUIAvailable(isAvailable: Boolean)
 
+    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
     fun setSideFpsShowing(isShowing: Boolean)
 }
 
@@ -261,7 +263,9 @@
         _isBackButtonEnabled.value = isBackButtonEnabled
     }
 
+    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
     override fun setSideFpsShowing(isShowing: Boolean) {
+        SideFpsControllerRefactor.assertInLegacyMode()
         _sideFpsShowing.value = isShowing
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
index 1122877..724c0fe 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
@@ -19,8 +19,8 @@
 import android.content.Context
 import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
 import com.android.systemui.authentication.domain.interactor.AuthenticationResult
+import com.android.systemui.authentication.shared.model.AuthenticationLockoutModel
 import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
-import com.android.systemui.authentication.shared.model.AuthenticationThrottlingModel
 import com.android.systemui.bouncer.data.repository.BouncerRepository
 import com.android.systemui.classifier.FalsingClassifier
 import com.android.systemui.classifier.domain.interactor.FalsingInteractor
@@ -32,7 +32,6 @@
 import com.android.systemui.scene.shared.flag.SceneContainerFlags
 import com.android.systemui.util.kotlin.pairwise
 import javax.inject.Inject
-import kotlin.time.Duration.Companion.milliseconds
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.async
 import kotlinx.coroutines.flow.MutableSharedFlow
@@ -61,24 +60,25 @@
 
     /** The user-facing message to show in the bouncer. */
     val message: StateFlow<String?> =
-        combine(repository.message, authenticationInteractor.throttling) { message, throttling ->
-                messageOrThrottlingMessage(message, throttling)
+        combine(repository.message, authenticationInteractor.lockout) { message, lockout ->
+                messageOrLockoutMessage(message, lockout)
             }
             .stateIn(
                 scope = applicationScope,
                 started = SharingStarted.WhileSubscribed(),
                 initialValue =
-                    messageOrThrottlingMessage(
+                    messageOrLockoutMessage(
                         repository.message.value,
-                        authenticationInteractor.throttling.value,
+                        authenticationInteractor.lockout.value,
                     )
             )
 
     /**
-     * The current authentication throttling state, set when the user has to wait before being able
-     * to try another authentication attempt. `null` indicates throttling isn't active.
+     * The current authentication lockout (aka "throttling") state, set when the user has to wait
+     * before being able to try another authentication attempt. `null` indicates lockout isn't
+     * active.
      */
-    val throttling: StateFlow<AuthenticationThrottlingModel?> = authenticationInteractor.throttling
+    val lockout: StateFlow<AuthenticationLockoutModel?> = authenticationInteractor.lockout
 
     /** Whether the auto confirm feature is enabled for the currently-selected user. */
     val isAutoConfirmEnabled: StateFlow<Boolean> = authenticationInteractor.isAutoConfirmEnabled
@@ -103,9 +103,9 @@
 
     init {
         if (flags.isEnabled()) {
-            // Clear the message if moved from throttling to no-longer throttling.
+            // Clear the message if moved from locked-out to no-longer locked-out.
             applicationScope.launch {
-                throttling.pairwise().collect { (previous, current) ->
+                lockout.pairwise().collect { (previous, current) ->
                     if (previous != null && current == null) {
                         clearMessage()
                     }
@@ -214,9 +214,9 @@
      * Shows the error message.
      *
      * Callers should use this instead of [authenticate] when they know ahead of time that an auth
-     * attempt will fail but aren't interested in the other side effects like triggering throttling.
+     * attempt will fail but aren't interested in the other side effects like triggering lockout.
      * For example, if the user entered a pattern that's too short, the system can show the error
-     * message without having the attempt trigger throttling.
+     * message without having the attempt trigger lockout.
      */
     private suspend fun showErrorMessage() {
         repository.setMessage(errorMessage(authenticationInteractor.getAuthenticationMethod()))
@@ -251,15 +251,15 @@
         }
     }
 
-    private fun messageOrThrottlingMessage(
+    private fun messageOrLockoutMessage(
         message: String?,
-        throttlingModel: AuthenticationThrottlingModel?,
+        lockoutModel: AuthenticationLockoutModel?,
     ): String {
         return when {
-            throttlingModel != null ->
+            lockoutModel != null ->
                 applicationContext.getString(
                     com.android.internal.R.string.lockscreen_too_many_failed_attempts_countdown,
-                    throttlingModel.remainingMs.milliseconds.inWholeSeconds,
+                    lockoutModel.remainingSeconds,
                 )
             message != null -> message
             else -> ""
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractor.kt
index aa7758f..621ca5d 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractor.kt
@@ -28,6 +28,7 @@
 import com.android.keyguard.KeyguardUpdateMonitor
 import com.android.keyguard.KeyguardUpdateMonitorCallback
 import com.android.systemui.DejankUtils
+import com.android.systemui.biometrics.shared.SideFpsControllerRefactor
 import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepository
 import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants
 import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN
@@ -116,9 +117,11 @@
 
     /** Allow for interaction when just about fully visible */
     val isInteractable: Flow<Boolean> = bouncerExpansion.map { it > 0.9 }
+    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
     val sideFpsShowing: Flow<Boolean> = repository.sideFpsShowing
     private var currentUserActiveUnlockRunning = false
 
+    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
     /** This callback needs to be a class field so it does not get garbage collected. */
     val keyguardUpdateMonitorCallback =
         object : KeyguardUpdateMonitorCallback() {
@@ -135,7 +138,10 @@
         }
 
     init {
-        keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
+        // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
+        if (!SideFpsControllerRefactor.isEnabled) {
+            keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
+        }
         applicationScope.launch {
             trustRepository.isCurrentUserActiveUnlockRunning.collect {
                 currentUserActiveUnlockRunning = it
@@ -333,8 +339,10 @@
         repository.setPrimaryStartDisappearAnimation(runnable)
     }
 
+    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
     /** Determine whether to show the side fps animation. */
     fun updateSideFpsVisibility() {
+        SideFpsControllerRefactor.assertInLegacyMode()
         val sfpsEnabled: Boolean =
             context.resources.getBoolean(R.bool.config_show_sidefps_hint_on_bouncer)
         val fpsDetectionRunning: Boolean = keyguardUpdateMonitor.isFingerprintDetectionRunning
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/KeyguardBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/KeyguardBouncerViewBinder.kt
index ac3d4b6..5dcd661 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/KeyguardBouncerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/KeyguardBouncerViewBinder.kt
@@ -27,6 +27,7 @@
 import com.android.keyguard.KeyguardSecurityModel
 import com.android.keyguard.KeyguardSecurityView
 import com.android.keyguard.dagger.KeyguardBouncerComponent
+import com.android.systemui.biometrics.shared.SideFpsControllerRefactor
 import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor
 import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE
 import com.android.systemui.bouncer.ui.BouncerViewDelegate
@@ -233,15 +234,21 @@
                             .collect { view.systemUiVisibility = it }
                     }
 
-                    launch {
-                        viewModel.shouldUpdateSideFps.collect {
-                            viewModel.updateSideFpsVisibility()
+                    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
+                    if (!SideFpsControllerRefactor.isEnabled) {
+                        launch {
+                            viewModel.shouldUpdateSideFps.collect {
+                                viewModel.updateSideFpsVisibility()
+                            }
                         }
                     }
 
-                    launch {
-                        viewModel.sideFpsShowing.collect {
-                            securityContainerController.updateSideFpsVisibility(it)
+                    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
+                    if (!SideFpsControllerRefactor.isEnabled) {
+                        launch {
+                            viewModel.sideFpsShowing.collect {
+                                securityContainerController.updateSideFpsVisibility(it)
+                            }
                         }
                     }
                     awaitCancellation()
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/helper/BouncerSceneLayout.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/helper/BouncerSceneLayout.kt
index 5385442..7f97718 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/helper/BouncerSceneLayout.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/helper/BouncerSceneLayout.kt
@@ -21,13 +21,13 @@
 /** Enumerates all known adaptive layout configurations. */
 enum class BouncerSceneLayout {
     /** The default UI with the bouncer laid out normally. */
-    STANDARD,
+    STANDARD_BOUNCER,
     /** The bouncer is displayed vertically stacked with the user switcher. */
-    STACKED,
+    BELOW_USER_SWITCHER,
     /** The bouncer is displayed side-by-side with the user switcher or an empty space. */
-    SIDE_BY_SIDE,
+    BESIDE_USER_SWITCHER,
     /** The bouncer is split in two with both sides shown side-by-side. */
-    SPLIT,
+    SPLIT_BOUNCER,
 }
 
 /** Enumerates the supported window size classes. */
@@ -48,19 +48,19 @@
     isSideBySideSupported: Boolean,
 ): BouncerSceneLayout {
     return when (height) {
-        SizeClass.COMPACT -> BouncerSceneLayout.SPLIT
+        SizeClass.COMPACT -> BouncerSceneLayout.SPLIT_BOUNCER
         SizeClass.MEDIUM ->
             when (width) {
-                SizeClass.COMPACT -> BouncerSceneLayout.STANDARD
-                SizeClass.MEDIUM -> BouncerSceneLayout.STANDARD
-                SizeClass.EXPANDED -> BouncerSceneLayout.SIDE_BY_SIDE
+                SizeClass.COMPACT -> BouncerSceneLayout.STANDARD_BOUNCER
+                SizeClass.MEDIUM -> BouncerSceneLayout.STANDARD_BOUNCER
+                SizeClass.EXPANDED -> BouncerSceneLayout.BESIDE_USER_SWITCHER
             }
         SizeClass.EXPANDED ->
             when (width) {
-                SizeClass.COMPACT -> BouncerSceneLayout.STANDARD
-                SizeClass.MEDIUM -> BouncerSceneLayout.STACKED
-                SizeClass.EXPANDED -> BouncerSceneLayout.SIDE_BY_SIDE
+                SizeClass.COMPACT -> BouncerSceneLayout.STANDARD_BOUNCER
+                SizeClass.MEDIUM -> BouncerSceneLayout.BELOW_USER_SWITCHER
+                SizeClass.EXPANDED -> BouncerSceneLayout.BESIDE_USER_SWITCHER
             }
-    }.takeIf { it != BouncerSceneLayout.SIDE_BY_SIDE || isSideBySideSupported }
-        ?: BouncerSceneLayout.STANDARD
+    }.takeIf { it != BouncerSceneLayout.BESIDE_USER_SWITCHER || isSideBySideSupported }
+        ?: BouncerSceneLayout.STANDARD_BOUNCER
 }
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModel.kt
index e379dab..0d7f6dc 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModel.kt
@@ -50,12 +50,12 @@
     abstract val authenticationMethod: AuthenticationMethodModel
 
     /**
-     * String resource ID of the failure message to be shown during throttling.
+     * String resource ID of the failure message to be shown during lockout.
      *
      * The message must include 2 number parameters: the first one indicating how many unsuccessful
-     * attempts were made, and the second one indicating in how many seconds throttling will expire.
+     * attempts were made, and the second one indicating in how many seconds lockout will expire.
      */
-    @get:StringRes abstract val throttlingMessageId: Int
+    @get:StringRes abstract val lockoutMessageId: Int
 
     /** Notifies that the UI has been shown to the user. */
     fun onShown() {
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt
index 58fa857..4b14343 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt
@@ -36,7 +36,6 @@
 import com.android.systemui.user.ui.viewmodel.UserViewModel
 import dagger.Module
 import dagger.Provides
-import kotlin.math.ceil
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.SupervisorJob
@@ -106,17 +105,17 @@
         get() = bouncerInteractor.isUserSwitcherVisible
 
     private val isInputEnabled: StateFlow<Boolean> =
-        bouncerInteractor.throttling
+        bouncerInteractor.lockout
             .map { it == null }
             .stateIn(
                 scope = applicationScope,
                 started = SharingStarted.WhileSubscribed(),
-                initialValue = bouncerInteractor.throttling.value == null,
+                initialValue = bouncerInteractor.lockout.value == null,
             )
 
     // Handle to the scope of the child ViewModel (stored in [authMethod]).
     private var childViewModelScope: CoroutineScope? = null
-    private val _throttlingDialogMessage = MutableStateFlow<String?>(null)
+    private val _dialogMessage = MutableStateFlow<String?>(null)
 
     /** View-model for the current UI, based on the current authentication method. */
     val authMethodViewModel: StateFlow<AuthMethodBouncerViewModel?> =
@@ -129,20 +128,20 @@
             )
 
     /**
-     * A message for a throttling dialog to show when the user has attempted the wrong credential
-     * too many times and now must wait a while before attempting again.
+     * A message for a dialog to show when the user has attempted the wrong credential too many
+     * times and now must wait a while before attempting again.
      *
      * If `null`, no dialog should be shown.
      *
-     * Once the dialog is shown, the UI should call [onThrottlingDialogDismissed] when the user
-     * dismisses this dialog.
+     * Once the dialog is shown, the UI should call [onDialogDismissed] when the user dismisses this
+     * dialog.
      */
-    val throttlingDialogMessage: StateFlow<String?> = _throttlingDialogMessage.asStateFlow()
+    val dialogMessage: StateFlow<String?> = _dialogMessage.asStateFlow()
 
     /** The user-facing message to show in the bouncer. */
     val message: StateFlow<MessageViewModel> =
-        combine(bouncerInteractor.message, bouncerInteractor.throttling) { message, throttling ->
-                toMessageViewModel(message, isThrottled = throttling != null)
+        combine(bouncerInteractor.message, bouncerInteractor.lockout) { message, lockout ->
+                toMessageViewModel(message, isLockedOut = lockout != null)
             }
             .stateIn(
                 scope = applicationScope,
@@ -150,7 +149,7 @@
                 initialValue =
                     toMessageViewModel(
                         message = bouncerInteractor.message.value,
-                        isThrottled = bouncerInteractor.throttling.value != null,
+                        isLockedOut = bouncerInteractor.lockout.value != null,
                     ),
             )
 
@@ -198,28 +197,28 @@
     init {
         if (flags.isEnabled()) {
             applicationScope.launch {
-                combine(bouncerInteractor.throttling, authMethodViewModel) {
-                        throttling,
+                combine(bouncerInteractor.lockout, authMethodViewModel) {
+                        lockout,
                         authMethodViewModel ->
-                        if (throttling != null && authMethodViewModel != null) {
+                        if (lockout != null && authMethodViewModel != null) {
                             applicationContext.getString(
-                                authMethodViewModel.throttlingMessageId,
-                                throttling.failedAttemptCount,
-                                ceil(throttling.remainingMs / 1000f).toInt(),
+                                authMethodViewModel.lockoutMessageId,
+                                lockout.failedAttemptCount,
+                                lockout.remainingSeconds,
                             )
                         } else {
                             null
                         }
                     }
                     .distinctUntilChanged()
-                    .collect { dialogMessage -> _throttlingDialogMessage.value = dialogMessage }
+                    .collect { dialogMessage -> _dialogMessage.value = dialogMessage }
             }
         }
     }
 
-    /** Notifies that a throttling dialog has been dismissed by the user. */
-    fun onThrottlingDialogDismissed() {
-        _throttlingDialogMessage.value = null
+    /** Notifies that the dialog has been dismissed by the user. */
+    fun onDialogDismissed() {
+        _dialogMessage.value = null
     }
 
     private fun isSideBySideSupported(authMethod: AuthMethodBouncerViewModel?): Boolean {
@@ -232,11 +231,11 @@
 
     private fun toMessageViewModel(
         message: String?,
-        isThrottled: Boolean,
+        isLockedOut: Boolean,
     ): MessageViewModel {
         return MessageViewModel(
             text = message ?: "",
-            isUpdateAnimated = !isThrottled,
+            isUpdateAnimated = !isLockedOut,
         )
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModel.kt
index 649ae2f..1c9d1f0 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModel.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.bouncer.ui.viewmodel
 
 import android.view.View
+import com.android.systemui.biometrics.shared.SideFpsControllerRefactor
 import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
 import com.android.systemui.bouncer.shared.model.BouncerShowMessageModel
 import com.android.systemui.bouncer.ui.BouncerView
@@ -61,9 +62,11 @@
     /** Observe whether keyguard is authenticated already. */
     val keyguardAuthenticated: Flow<Boolean> = interactor.keyguardAuthenticatedBiometrics
 
+    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
     /** Observe whether the side fps is showing. */
     val sideFpsShowing: Flow<Boolean> = interactor.sideFpsShowing
 
+    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
     /** Observe whether we should update fps is showing. */
     val shouldUpdateSideFps: Flow<Unit> =
         merge(
@@ -87,7 +90,9 @@
         interactor.onMessageShown()
     }
 
+    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
     fun updateSideFpsVisibility() {
+        SideFpsControllerRefactor.assertInLegacyMode()
         interactor.updateSideFpsVisibility()
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModel.kt
index 3b7e321..b682717 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModel.kt
@@ -46,7 +46,7 @@
 
     override val authenticationMethod = AuthenticationMethodModel.Password
 
-    override val throttlingMessageId = R.string.kg_too_many_failed_password_attempts_dialog_message
+    override val lockoutMessageId = R.string.kg_too_many_failed_password_attempts_dialog_message
 
     /** Whether the input method editor (for example, the software keyboard) is visible. */
     private var isImeVisible: Boolean = false
@@ -56,13 +56,13 @@
 
     /** Whether the UI should request focus on the text field element. */
     val isTextFieldFocusRequested =
-        combine(interactor.throttling, isTextFieldFocused) { throttling, hasFocus ->
+        combine(interactor.lockout, isTextFieldFocused) { throttling, hasFocus ->
                 throttling == null && !hasFocus
             }
             .stateIn(
                 scope = viewModelScope,
                 started = SharingStarted.WhileSubscribed(),
-                initialValue = interactor.throttling.value == null && !isTextFieldFocused.value,
+                initialValue = interactor.lockout.value == null && !isTextFieldFocused.value,
             )
 
     override fun onHidden() {
@@ -104,7 +104,7 @@
      * hidden.
      */
     suspend fun onImeVisibilityChanged(isVisible: Boolean) {
-        if (isImeVisible && !isVisible && interactor.throttling.value == null) {
+        if (isImeVisible && !isVisible && interactor.lockout.value == null) {
             interactor.onImeHiddenByUser()
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModel.kt
index b1c5ab6..69f8032 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModel.kt
@@ -80,7 +80,7 @@
 
     override val authenticationMethod = AuthenticationMethodModel.Pattern
 
-    override val throttlingMessageId = R.string.kg_too_many_failed_pattern_attempts_dialog_message
+    override val lockoutMessageId = R.string.kg_too_many_failed_pattern_attempts_dialog_message
 
     /** Notifies that the user has started a drag gesture across the dot grid. */
     fun onDragStart() {
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt
index e25e82f..7f4a029 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt
@@ -104,7 +104,7 @@
 
     override val authenticationMethod: AuthenticationMethodModel = authenticationMethod
 
-    override val throttlingMessageId = R.string.kg_too_many_failed_pin_attempts_dialog_message
+    override val lockoutMessageId = R.string.kg_too_many_failed_pin_attempts_dialog_message
 
     init {
         viewModelScope.launch { simBouncerInteractor.subId.collect { onResetSimFlow() } }
diff --git a/packages/SystemUI/src/com/android/systemui/common/shared/model/NotificationContainerBounds.kt b/packages/SystemUI/src/com/android/systemui/common/shared/model/NotificationContainerBounds.kt
index fdd98bec..3063ebd 100644
--- a/packages/SystemUI/src/com/android/systemui/common/shared/model/NotificationContainerBounds.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/shared/model/NotificationContainerBounds.kt
@@ -18,8 +18,12 @@
 
 /** Models the bounds of the notification container. */
 data class NotificationContainerBounds(
+    /** The position of the left of the container in its window coordinate system, in pixels. */
+    val left: Float = 0f,
     /** The position of the top of the container in its window coordinate system, in pixels. */
     val top: Float = 0f,
+    /** The position of the right of the container in its window coordinate system, in pixels. */
+    val right: Float = 0f,
     /** The position of the bottom of the container in its window coordinate system, in pixels. */
     val bottom: Float = 0f,
     /** Whether any modifications to top/bottom should be smoothly animated. */
diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalRepository.kt b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalRepository.kt
index 3119b9e..1f4be40 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalRepository.kt
@@ -18,18 +18,26 @@
 
 import com.android.systemui.Flags.communalHub
 import com.android.systemui.communal.shared.model.CommunalSceneKey
+import com.android.systemui.communal.shared.model.ObservableCommunalTransitionState
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.flags.FeatureFlagsClassic
 import com.android.systemui.flags.Flags
 import com.android.systemui.scene.data.repository.SceneContainerRepository
 import com.android.systemui.scene.shared.flag.SceneContainerFlags
 import com.android.systemui.scene.shared.model.SceneKey
 import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.stateIn
 
 /** Encapsulates the state of communal mode. */
 interface CommunalRepository {
@@ -45,14 +53,26 @@
      */
     val desiredScene: StateFlow<CommunalSceneKey>
 
+    /** Exposes the transition state of the communal [SceneTransitionLayout]. */
+    val transitionState: StateFlow<ObservableCommunalTransitionState>
+
     /** Updates the requested scene. */
     fun setDesiredScene(desiredScene: CommunalSceneKey)
+
+    /**
+     * Updates the transition state of the hub [SceneTransitionLayout].
+     *
+     * Note that you must call is with `null` when the UI is done or risk a memory leak.
+     */
+    fun setTransitionState(transitionState: Flow<ObservableCommunalTransitionState>?)
 }
 
+@OptIn(ExperimentalCoroutinesApi::class)
 @SysUISingleton
 class CommunalRepositoryImpl
 @Inject
 constructor(
+    @Background backgroundScope: CoroutineScope,
     private val featureFlagsClassic: FeatureFlagsClassic,
     sceneContainerFlags: SceneContainerFlags,
     sceneContainerRepository: SceneContainerRepository,
@@ -61,13 +81,34 @@
         get() = featureFlagsClassic.isEnabled(Flags.COMMUNAL_SERVICE_ENABLED) && communalHub()
 
     private val _desiredScene: MutableStateFlow<CommunalSceneKey> =
-        MutableStateFlow(CommunalSceneKey.Blank)
+        MutableStateFlow(CommunalSceneKey.DEFAULT)
     override val desiredScene: StateFlow<CommunalSceneKey> = _desiredScene.asStateFlow()
 
+    private val defaultTransitionState =
+        ObservableCommunalTransitionState.Idle(CommunalSceneKey.DEFAULT)
+    private val _transitionState = MutableStateFlow<Flow<ObservableCommunalTransitionState>?>(null)
+    override val transitionState: StateFlow<ObservableCommunalTransitionState> =
+        _transitionState
+            .flatMapLatest { innerFlowOrNull -> innerFlowOrNull ?: flowOf(defaultTransitionState) }
+            .stateIn(
+                scope = backgroundScope,
+                started = SharingStarted.Lazily,
+                initialValue = defaultTransitionState,
+            )
+
     override fun setDesiredScene(desiredScene: CommunalSceneKey) {
         _desiredScene.value = desiredScene
     }
 
+    /**
+     * Updates the transition state of the hub [SceneTransitionLayout].
+     *
+     * Note that you must call is with `null` when the UI is done or risk a memory leak.
+     */
+    override fun setTransitionState(transitionState: Flow<ObservableCommunalTransitionState>?) {
+        _transitionState.value = transitionState
+    }
+
     override val isCommunalHubShowing: Flow<Boolean> =
         if (sceneContainerFlags.isEnabled()) {
             sceneContainerRepository.desiredScene.map { scene -> scene.key == SceneKey.Communal }
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 e630fd4..e342c6b 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
@@ -25,6 +25,7 @@
 import com.android.systemui.communal.domain.model.CommunalContentModel
 import com.android.systemui.communal.shared.model.CommunalContentSize
 import com.android.systemui.communal.shared.model.CommunalSceneKey
+import com.android.systemui.communal.shared.model.ObservableCommunalTransitionState
 import com.android.systemui.communal.widgets.EditWidgetsActivityStarter
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
@@ -62,6 +63,19 @@
      */
     val desiredScene: StateFlow<CommunalSceneKey> = communalRepository.desiredScene
 
+    /** Transition state of the hub mode. */
+    val transitionState: StateFlow<ObservableCommunalTransitionState> =
+        communalRepository.transitionState
+
+    /**
+     * Updates the transition state of the hub [SceneTransitionLayout].
+     *
+     * Note that you must call is with `null` when the UI is done or risk a memory leak.
+     */
+    fun setTransitionState(transitionState: Flow<ObservableCommunalTransitionState>?) {
+        communalRepository.setTransitionState(transitionState)
+    }
+
     /**
      * Flow that emits a boolean if the communal UI is showing, ie. the [desiredScene] is the
      * [CommunalSceneKey.Communal].
@@ -108,7 +122,7 @@
         if (!smartspaceRepository.isSmartspaceRemoteViewsEnabled) {
             flowOf(emptyList())
         } else {
-            smartspaceRepository.lockscreenSmartspaceTargets.map { targets ->
+            smartspaceRepository.communalSmartspaceTargets.map { targets ->
                 targets
                     .filter { target ->
                         target.featureType == SmartspaceTarget.FEATURE_TIMER &&
diff --git a/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalSceneKey.kt b/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalSceneKey.kt
index 2be909c..c68dd4f 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalSceneKey.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalSceneKey.kt
@@ -29,4 +29,8 @@
     override fun toString(): String {
         return loggingName
     }
+
+    companion object {
+        val DEFAULT = Blank
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/communal/shared/model/ObservableCommunalTransitionState.kt b/packages/SystemUI/src/com/android/systemui/communal/shared/model/ObservableCommunalTransitionState.kt
new file mode 100644
index 0000000..d834715
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/communal/shared/model/ObservableCommunalTransitionState.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.communal.shared.model
+
+import kotlinx.coroutines.flow.Flow
+
+/**
+ * This is a fork of the `com.android.compose.animation.scene.ObservableTransitionState` class.
+ *
+ * TODO(b/315490861): remove this fork, once we can compile Compose into System UI.
+ */
+sealed class ObservableCommunalTransitionState {
+    /** No transition/animation is currently running. */
+    data class Idle(val scene: CommunalSceneKey) : ObservableCommunalTransitionState()
+
+    /** There is a transition animating between two scenes. */
+    data class Transition(
+        val fromScene: CommunalSceneKey,
+        val toScene: CommunalSceneKey,
+        val progress: Flow<Float>,
+
+        /**
+         * Whether the transition was originally triggered by user input rather than being
+         * programmatic. If this value is initially true, it will remain true until the transition
+         * fully completes, even if the user input that triggered the transition has ended. Any
+         * sub-transitions launched by this one will inherit this value. For example, if the user
+         * drags a pointer but does not exceed the threshold required to transition to another
+         * scene, this value will remain true after the pointer is no longer touching the screen and
+         * will be true in any transition created to animate back to the original position.
+         */
+        val isInitiatedByUserInput: Boolean,
+
+        /**
+         * Whether user input is currently driving the transition. For example, if a user is
+         * dragging a pointer, this emits true. Once they lift their finger, this emits false while
+         * the transition completes/settles.
+         */
+        val isUserInputOngoing: Flow<Boolean>,
+    ) : ObservableCommunalTransitionState()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/smartspace/CommunalSmartspaceController.kt b/packages/SystemUI/src/com/android/systemui/communal/smartspace/CommunalSmartspaceController.kt
new file mode 100644
index 0000000..c5610c87
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/communal/smartspace/CommunalSmartspaceController.kt
@@ -0,0 +1,195 @@
+/*
+ * 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.communal.smartspace
+
+import android.app.smartspace.SmartspaceConfig
+import android.app.smartspace.SmartspaceManager
+import android.app.smartspace.SmartspaceSession
+import android.app.smartspace.SmartspaceTarget
+import android.content.Context
+import android.util.Log
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.plugins.BcSmartspaceDataPlugin
+import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceTargetListener
+import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceView
+import com.android.systemui.plugins.BcSmartspaceDataPlugin.UI_SURFACE_GLANCEABLE_HUB
+import com.android.systemui.smartspace.SmartspacePrecondition
+import com.android.systemui.smartspace.SmartspaceTargetFilter
+import com.android.systemui.smartspace.dagger.SmartspaceModule.Companion.DREAM_SMARTSPACE_PRECONDITION
+import com.android.systemui.smartspace.dagger.SmartspaceModule.Companion.DREAM_SMARTSPACE_TARGET_FILTER
+import com.android.systemui.smartspace.dagger.SmartspaceModule.Companion.GLANCEABLE_HUB_SMARTSPACE_DATA_PLUGIN
+import com.android.systemui.util.concurrency.Execution
+import java.util.Optional
+import java.util.concurrent.Executor
+import javax.inject.Inject
+import javax.inject.Named
+
+/** Controller for managing the smartspace view on the dream */
+@SysUISingleton
+class CommunalSmartspaceController
+@Inject
+constructor(
+    private val context: Context,
+    private val smartspaceManager: SmartspaceManager?,
+    private val execution: Execution,
+    @Main private val uiExecutor: Executor,
+    @Named(DREAM_SMARTSPACE_PRECONDITION) private val precondition: SmartspacePrecondition,
+    @Named(DREAM_SMARTSPACE_TARGET_FILTER)
+    private val optionalTargetFilter: Optional<SmartspaceTargetFilter>,
+    @Named(GLANCEABLE_HUB_SMARTSPACE_DATA_PLUGIN) optionalPlugin: Optional<BcSmartspaceDataPlugin>,
+) {
+    companion object {
+        private const val TAG = "CommunalSmartspaceCtrlr"
+    }
+
+    private var session: SmartspaceSession? = null
+    private val plugin: BcSmartspaceDataPlugin? = optionalPlugin.orElse(null)
+    private var targetFilter: SmartspaceTargetFilter? = optionalTargetFilter.orElse(null)
+
+    // A shadow copy of listeners is maintained to track whether the session should remain open.
+    private var listeners = mutableSetOf<SmartspaceTargetListener>()
+
+    private var unfilteredListeners = mutableSetOf<SmartspaceTargetListener>()
+
+    // Smartspace can be used on multiple displays, such as when the user casts their screen
+    private var smartspaceViews = mutableSetOf<SmartspaceView>()
+
+    var preconditionListener =
+        object : SmartspacePrecondition.Listener {
+            override fun onCriteriaChanged() {
+                reloadSmartspace()
+            }
+        }
+
+    init {
+        precondition.addListener(preconditionListener)
+    }
+
+    var filterListener =
+        object : SmartspaceTargetFilter.Listener {
+            override fun onCriteriaChanged() {
+                reloadSmartspace()
+            }
+        }
+
+    init {
+        targetFilter?.addListener(filterListener)
+    }
+
+    private val sessionListener =
+        SmartspaceSession.OnTargetsAvailableListener { targets ->
+            execution.assertIsMainThread()
+
+            val filteredTargets =
+                targets.filter { targetFilter?.filterSmartspaceTarget(it) ?: true }
+            plugin?.onTargetsAvailable(filteredTargets)
+        }
+
+    private fun hasActiveSessionListeners(): Boolean {
+        return smartspaceViews.isNotEmpty() ||
+            listeners.isNotEmpty() ||
+            unfilteredListeners.isNotEmpty()
+    }
+
+    private fun connectSession() {
+        if (smartspaceManager == null) {
+            return
+        }
+        if (plugin == null) {
+            return
+        }
+        if (session != null || !hasActiveSessionListeners()) {
+            return
+        }
+
+        if (!precondition.conditionsMet()) {
+            return
+        }
+
+        val newSession =
+            smartspaceManager.createSmartspaceSession(
+                SmartspaceConfig.Builder(context, UI_SURFACE_GLANCEABLE_HUB).build()
+            )
+        Log.d(TAG, "Starting smartspace session for dream")
+        newSession.addOnTargetsAvailableListener(uiExecutor, sessionListener)
+        this.session = newSession
+
+        plugin?.registerSmartspaceEventNotifier { e -> session?.notifySmartspaceEvent(e) }
+
+        reloadSmartspace()
+    }
+
+    /** Disconnects the smartspace view from the smartspace service and cleans up any resources. */
+    private fun disconnect() {
+        if (hasActiveSessionListeners()) return
+
+        execution.assertIsMainThread()
+
+        if (session == null) {
+            return
+        }
+
+        session?.let {
+            it.removeOnTargetsAvailableListener(sessionListener)
+            it.close()
+        }
+
+        session = null
+
+        plugin?.registerSmartspaceEventNotifier(null)
+        plugin?.onTargetsAvailable(emptyList())
+        Log.d(TAG, "Ending smartspace session for dream")
+    }
+
+    fun addListener(listener: SmartspaceTargetListener) {
+        addAndRegisterListener(listener, plugin)
+    }
+
+    fun removeListener(listener: SmartspaceTargetListener) {
+        removeAndUnregisterListener(listener, plugin)
+    }
+
+    private fun addAndRegisterListener(
+        listener: SmartspaceTargetListener,
+        smartspaceDataPlugin: BcSmartspaceDataPlugin?
+    ) {
+        execution.assertIsMainThread()
+        smartspaceDataPlugin?.registerListener(listener)
+        listeners.add(listener)
+
+        connectSession()
+    }
+
+    private fun removeAndUnregisterListener(
+        listener: SmartspaceTargetListener,
+        smartspaceDataPlugin: BcSmartspaceDataPlugin?
+    ) {
+        execution.assertIsMainThread()
+        smartspaceDataPlugin?.unregisterListener(listener)
+        listeners.remove(listener)
+        disconnect()
+    }
+
+    private fun reloadSmartspace() {
+        session?.requestSmartspaceUpdate()
+    }
+
+    private fun onTargetsAvailableUnfiltered(targets: List<SmartspaceTarget>) {
+        unfilteredListeners.forEach { it.onSmartspaceTargetsUpdated(targets) }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt
index 333fc19..708f137 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt
@@ -22,6 +22,7 @@
 import com.android.systemui.communal.domain.interactor.CommunalInteractor
 import com.android.systemui.communal.domain.model.CommunalContentModel
 import com.android.systemui.communal.shared.model.CommunalSceneKey
+import com.android.systemui.communal.shared.model.ObservableCommunalTransitionState
 import com.android.systemui.media.controls.ui.MediaHost
 import com.android.systemui.shade.ShadeViewController
 import javax.inject.Provider
@@ -43,6 +44,15 @@
         communalInteractor.onSceneChanged(scene)
     }
 
+    /**
+     * Updates the transition state of the hub [SceneTransitionLayout].
+     *
+     * Note that you must call is with `null` when the UI is done or risk a memory leak.
+     */
+    fun setTransitionState(transitionState: Flow<ObservableCommunalTransitionState>?) {
+        communalInteractor.setTransitionState(transitionState)
+    }
+
     // TODO(b/308813166): remove once CommunalContainer is moved lower in z-order and doesn't block
     //  touches anymore.
     /** Called when a touch is received outside the edge swipe area when hub mode is closed. */
diff --git a/packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt b/packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt
index 7b94fc1..573a748 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt
@@ -76,6 +76,10 @@
                     Intent(applicationContext, WidgetPickerActivity::class.java)
                 )
             },
+            onEditDone = {
+                // TODO(b/315154364): in a separate change, lock the device and transition to GH
+                finish()
+            }
         )
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/complication/DreamHomeControlsComplication.java b/packages/SystemUI/src/com/android/systemui/complication/DreamHomeControlsComplication.java
index 7ac1cc7..9d4ed20 100644
--- a/packages/SystemUI/src/com/android/systemui/complication/DreamHomeControlsComplication.java
+++ b/packages/SystemUI/src/com/android/systemui/complication/DreamHomeControlsComplication.java
@@ -25,11 +25,15 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
 import android.util.Log;
 import android.view.View;
 import android.widget.ImageView;
 
+import androidx.annotation.Nullable;
+
 import com.android.internal.logging.UiEventLogger;
+import com.android.settingslib.Utils;
 import com.android.systemui.CoreStartable;
 import com.android.systemui.animation.ActivityLaunchAnimator;
 import com.android.systemui.complication.dagger.DreamHomeControlsComplicationComponent;
@@ -43,6 +47,7 @@
 import com.android.systemui.dreams.DreamOverlayStateController;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.shared.condition.Monitor;
+import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.util.ViewController;
 import com.android.systemui.util.condition.ConditionalCoreStartable;
 
@@ -195,34 +200,70 @@
 
         private final ActivityStarter mActivityStarter;
         private final Context mContext;
+        private final ConfigurationController mConfigurationController;
         private final ControlsComponent mControlsComponent;
 
         private final UiEventLogger mUiEventLogger;
 
+        private final ConfigurationController.ConfigurationListener mConfigurationListener =
+                new ConfigurationController.ConfigurationListener() {
+                    @Override
+                    public void onUiModeChanged() {
+                        reloadResources();
+                    }
+                };
+
         @Inject
         DreamHomeControlsChipViewController(
                 @Named(DREAM_HOME_CONTROLS_CHIP_VIEW) ImageView view,
                 ActivityStarter activityStarter,
                 Context context,
+                ConfigurationController configurationController,
                 ControlsComponent controlsComponent,
                 UiEventLogger uiEventLogger) {
             super(view);
 
             mActivityStarter = activityStarter;
             mContext = context;
+            mConfigurationController = configurationController;
             mControlsComponent = controlsComponent;
             mUiEventLogger = uiEventLogger;
         }
 
         @Override
         protected void onViewAttached() {
-            mView.setImageResource(mControlsComponent.getTileImageId());
-            mView.setContentDescription(mContext.getString(mControlsComponent.getTileTitleId()));
+            reloadResources();
             mView.setOnClickListener(this::onClickHomeControls);
+            mConfigurationController.addCallback(mConfigurationListener);
         }
 
         @Override
-        protected void onViewDetached() {}
+        protected void onViewDetached() {
+            mConfigurationController.removeCallback(mConfigurationListener);
+        }
+
+        private void reloadResources() {
+            final String title = getControlsTitle();
+            if (title != null) {
+                mView.setContentDescription(title);
+            }
+            mView.setImageResource(mControlsComponent.getTileImageId());
+            mView.setImageTintList(Utils.getColorAttr(mContext, android.R.attr.textColorPrimary));
+            final Drawable background = mView.getBackground();
+            if (background != null) {
+                background.setTintList(
+                        Utils.getColorAttr(mContext, com.android.internal.R.attr.colorSurface));
+            }
+        }
+
+        @Nullable
+        private String getControlsTitle() {
+            try {
+                return mContext.getString(mControlsComponent.getTileTitleId());
+            } catch (Resources.NotFoundException e) {
+                return null;
+            }
+        }
 
         private void onClickHomeControls(View v) {
             if (DEBUG) Log.d(TAG, "home controls complication tapped");
diff --git a/packages/SystemUI/src/com/android/systemui/complication/dagger/DreamHomeControlsComplicationComponent.java b/packages/SystemUI/src/com/android/systemui/complication/dagger/DreamHomeControlsComplicationComponent.java
index 08d0595..b6dcfcb 100644
--- a/packages/SystemUI/src/com/android/systemui/complication/dagger/DreamHomeControlsComplicationComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/complication/dagger/DreamHomeControlsComplicationComponent.java
@@ -24,9 +24,8 @@
 import android.view.LayoutInflater;
 import android.widget.ImageView;
 
-import com.android.settingslib.Utils;
-import com.android.systemui.res.R;
 import com.android.systemui.complication.DreamHomeControlsComplication;
+import com.android.systemui.res.R;
 import com.android.systemui.shared.shadow.DoubleShadowIconDrawable;
 import com.android.systemui.shared.shadow.DoubleShadowTextHelper;
 
@@ -98,7 +97,7 @@
         @DreamHomeControlsComplicationScope
         @Named(DREAM_HOME_CONTROLS_BACKGROUND_DRAWABLE)
         static Drawable providesHomeControlsBackground(Context context, Resources resources) {
-            final Drawable background = new DoubleShadowIconDrawable(createShadowInfo(
+            return new DoubleShadowIconDrawable(createShadowInfo(
                             resources,
                             R.dimen.dream_overlay_bottom_affordance_key_text_shadow_radius,
                             R.dimen.dream_overlay_bottom_affordance_key_text_shadow_dx,
@@ -117,11 +116,6 @@
                             R.dimen.dream_overlay_bottom_affordance_width),
                     resources.getDimensionPixelSize(R.dimen.dream_overlay_bottom_affordance_inset)
             );
-
-            background.setTintList(
-                    Utils.getColorAttr(context, com.android.internal.R.attr.colorSurface));
-
-            return background;
         }
 
         private static DoubleShadowTextHelper.ShadowInfo createShadowInfo(Resources resources,
diff --git a/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt b/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt
index 65d4495..3a92739 100644
--- a/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt
+++ b/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt
@@ -63,6 +63,7 @@
         activity: ComponentActivity,
         viewModel: BaseCommunalViewModel,
         onOpenWidgetPicker: () -> Unit,
+        onEditDone: () -> Unit,
     )
 
     /** Create a [View] to represent [viewModel] on screen. */
diff --git a/packages/SystemUI/src/com/android/systemui/contrast/ContrastDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/contrast/ContrastDialogDelegate.kt
index 63b01ed..0daa058 100644
--- a/packages/SystemUI/src/com/android/systemui/contrast/ContrastDialogDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/contrast/ContrastDialogDelegate.kt
@@ -35,23 +35,22 @@
 import javax.inject.Inject
 
 /** Dialog to select contrast options */
-class ContrastDialogDelegate @Inject constructor(
-    private val sysuiDialogFactory : SystemUIDialog.Factory,
+class ContrastDialogDelegate
+@Inject
+constructor(
+    private val sysuiDialogFactory: SystemUIDialog.Factory,
     @Main private val mainExecutor: Executor,
     private val uiModeManager: UiModeManager,
     private val userTracker: UserTracker,
     private val secureSettings: SecureSettings,
 ) : SystemUIDialog.Delegate, UiModeManager.ContrastChangeListener {
 
-    override fun createDialog(): SystemUIDialog {
-        return sysuiDialogFactory.create(this)
-    }
-
     @VisibleForTesting lateinit var contrastButtons: Map<Int, FrameLayout>
     lateinit var dialogView: View
     @VisibleForTesting var initialContrast: Float = fromContrastLevel(CONTRAST_LEVEL_STANDARD)
 
-    override fun onCreate(dialog: SystemUIDialog, savedInstanceState: Bundle?) {
+    override fun createDialog(): SystemUIDialog {
+        val dialog = sysuiDialogFactory.create(this)
         dialogView = dialog.layoutInflater.inflate(R.layout.contrast_dialog, null)
         with(dialog) {
             setView(dialogView)
@@ -67,12 +66,16 @@
             }
             setPositiveButton(com.android.settingslib.R.string.done) { _, _ -> dialog.dismiss() }
         }
+
+        return dialog
+    }
+
+    override fun onCreate(dialog: SystemUIDialog, savedInstanceState: Bundle?) {
         contrastButtons =
             mapOf(
-                CONTRAST_LEVEL_STANDARD to dialogView.requireViewById(
-                    R.id.contrast_button_standard),
-                CONTRAST_LEVEL_MEDIUM to dialogView.requireViewById(R.id.contrast_button_medium),
-                CONTRAST_LEVEL_HIGH to dialogView.requireViewById(R.id.contrast_button_high)
+                CONTRAST_LEVEL_STANDARD to dialog.requireViewById(R.id.contrast_button_standard),
+                CONTRAST_LEVEL_MEDIUM to dialog.requireViewById(R.id.contrast_button_medium),
+                CONTRAST_LEVEL_HIGH to dialog.requireViewById(R.id.contrast_button_high)
             )
 
         contrastButtons.forEach { (contrastLevel, contrastButton) ->
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index 0405ca4..ca8268d 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -82,6 +82,7 @@
 import com.android.systemui.qs.QSFragmentStartableModule;
 import com.android.systemui.qs.footer.dagger.FooterActionsModule;
 import com.android.systemui.recents.Recents;
+import com.android.systemui.recordissue.RecordIssueModule;
 import com.android.systemui.retail.dagger.RetailModeModule;
 import com.android.systemui.scene.ui.view.WindowRootViewComponent;
 import com.android.systemui.screenrecord.ScreenRecordModule;
@@ -209,6 +210,7 @@
         PrivacyModule.class,
         QRCodeScannerModule.class,
         QSFragmentStartableModule.class,
+        RecordIssueModule.class,
         ReferenceModule.class,
         RetailModeModule.class,
         ScreenshotModule.class,
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/DeviceEntryModule.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/DeviceEntryModule.kt
index cd764c0..b915418 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/DeviceEntryModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/DeviceEntryModule.kt
@@ -1,6 +1,5 @@
 package com.android.systemui.deviceentry
 
-import com.android.systemui.deviceentry.data.repository.DeviceEntryHapticsRepositoryModule
 import com.android.systemui.deviceentry.data.repository.DeviceEntryRepositoryModule
 import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
 import dagger.Module
@@ -10,7 +9,6 @@
     includes =
         [
             DeviceEntryRepositoryModule::class,
-            DeviceEntryHapticsRepositoryModule::class,
         ],
 )
 abstract class DeviceEntryModule {
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepository.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepository.kt
deleted file mode 100644
index 1458404..0000000
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepository.kt
+++ /dev/null
@@ -1,72 +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.deviceentry.data.repository
-
-import com.android.systemui.dagger.SysUISingleton
-import dagger.Binds
-import dagger.Module
-import javax.inject.Inject
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.asStateFlow
-
-/** Interface for classes that can access device-entry haptics application state. */
-interface DeviceEntryHapticsRepository {
-    /**
-     * Whether a successful biometric haptic has been requested. Has not yet been handled if true.
-     */
-    val successHapticRequest: Flow<Boolean>
-
-    /** Whether an error biometric haptic has been requested. Has not yet been handled if true. */
-    val errorHapticRequest: Flow<Boolean>
-
-    fun requestSuccessHaptic()
-    fun handleSuccessHaptic()
-    fun requestErrorHaptic()
-    fun handleErrorHaptic()
-}
-
-/** Encapsulates application state for device entry haptics. */
-@SysUISingleton
-class DeviceEntryHapticsRepositoryImpl @Inject constructor() : DeviceEntryHapticsRepository {
-    private val _successHapticRequest = MutableStateFlow(false)
-    override val successHapticRequest: Flow<Boolean> = _successHapticRequest.asStateFlow()
-
-    private val _errorHapticRequest = MutableStateFlow(false)
-    override val errorHapticRequest: Flow<Boolean> = _errorHapticRequest.asStateFlow()
-
-    override fun requestSuccessHaptic() {
-        _successHapticRequest.value = true
-    }
-
-    override fun handleSuccessHaptic() {
-        _successHapticRequest.value = false
-    }
-
-    override fun requestErrorHaptic() {
-        _errorHapticRequest.value = true
-    }
-
-    override fun handleErrorHaptic() {
-        _errorHapticRequest.value = false
-    }
-}
-
-@Module
-interface DeviceEntryHapticsRepositoryModule {
-    @Binds fun repository(impl: DeviceEntryHapticsRepositoryImpl): DeviceEntryHapticsRepository
-}
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepository.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepository.kt
index f27bbe6..08e8c2d 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepository.kt
@@ -7,26 +7,36 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.keyguard.data.repository.KeyguardRepository
+import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
+import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
 import com.android.systemui.statusbar.phone.KeyguardBypassController
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.user.data.repository.UserRepository
+import com.android.systemui.util.kotlin.sample
 import dagger.Binds
 import dagger.Module
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.filterNotNull
 import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.flow.stateIn
 import kotlinx.coroutines.withContext
 
 /** Interface for classes that can access device-entry-related application state. */
 interface DeviceEntryRepository {
+    /** Whether the device is immediately entering the device after a biometric unlock. */
+    val enteringDeviceFromBiometricUnlock: Flow<BiometricUnlockSource>
+
     /**
      * Whether the device is unlocked.
      *
@@ -73,7 +83,14 @@
     private val lockPatternUtils: LockPatternUtils,
     private val keyguardBypassController: KeyguardBypassController,
     keyguardStateController: KeyguardStateController,
+    keyguardRepository: KeyguardRepository,
 ) : DeviceEntryRepository {
+    override val enteringDeviceFromBiometricUnlock =
+        keyguardRepository.biometricUnlockState
+            .filter { BiometricUnlockModel.dismissesKeyguard(it) }
+            .sample(
+                keyguardRepository.biometricUnlockSource.filterNotNull(),
+            )
 
     private val _isUnlocked = MutableStateFlow(false)
 
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricAuthInteractor.kt
new file mode 100644
index 0000000..1a6bd04
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricAuthInteractor.kt
@@ -0,0 +1,70 @@
+/*
+ * 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.deviceentry.domain.interactor
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.deviceentry.shared.DeviceEntryBiometricMode
+import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
+import com.android.systemui.keyguard.shared.model.FailedFaceAuthenticationStatus
+import javax.inject.Inject
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.emptyFlow
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.map
+
+/** Business logic for device entry biometric states that may differ based on the biometric mode. */
+@ExperimentalCoroutinesApi
+@SysUISingleton
+class DeviceEntryBiometricAuthInteractor
+@Inject
+constructor(
+    biometricSettingsRepository: BiometricSettingsRepository,
+    deviceEntryFaceAuthInteractor: DeviceEntryFaceAuthInteractor,
+) {
+    private val biometricMode: Flow<DeviceEntryBiometricMode> =
+        combine(
+            biometricSettingsRepository.isFingerprintEnrolledAndEnabled,
+            biometricSettingsRepository.isFaceAuthEnrolledAndEnabled,
+        ) { fingerprintEnrolled, faceEnrolled ->
+            if (fingerprintEnrolled && faceEnrolled) {
+                DeviceEntryBiometricMode.CO_EXPERIENCE
+            } else if (fingerprintEnrolled) {
+                DeviceEntryBiometricMode.FINGERPRINT_ONLY
+            } else if (faceEnrolled) {
+                DeviceEntryBiometricMode.FACE_ONLY
+            } else {
+                DeviceEntryBiometricMode.NONE
+            }
+        }
+    private val faceOnly: Flow<Boolean> =
+        biometricMode.map { it == DeviceEntryBiometricMode.FACE_ONLY }
+
+    /**
+     * Triggered if face is the only biometric that can be used for device entry and a face failure
+     * occurs.
+     */
+    val faceOnlyFaceFailure: Flow<FailedFaceAuthenticationStatus> =
+        faceOnly.flatMapLatest { faceOnly ->
+            if (faceOnly) {
+                deviceEntryFaceAuthInteractor.faceFailure
+            } else {
+                emptyFlow()
+            }
+        }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractor.kt
new file mode 100644
index 0000000..70716c6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractor.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.deviceentry.domain.interactor
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.data.repository.DeviceEntryFaceAuthRepository
+import com.android.systemui.keyguard.shared.model.FailedFaceAuthenticationStatus
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.filterIsInstance
+
+@SysUISingleton
+class DeviceEntryFaceAuthInteractor
+@Inject
+constructor(
+    repository: DeviceEntryFaceAuthRepository,
+) {
+    val faceFailure: Flow<FailedFaceAuthenticationStatus> =
+        repository.authenticationStatus.filterIsInstance<FailedFaceAuthenticationStatus>()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFingerprintAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFingerprintAuthInteractor.kt
new file mode 100644
index 0000000..efa1c0a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFingerprintAuthInteractor.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.deviceentry.domain.interactor
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository
+import com.android.systemui.keyguard.shared.model.FailFingerprintAuthenticationStatus
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.filterIsInstance
+
+@SysUISingleton
+class DeviceEntryFingerprintAuthInteractor
+@Inject
+constructor(
+    repository: DeviceEntryFingerprintAuthRepository,
+) {
+    val fingerprintFailure: Flow<FailFingerprintAuthenticationStatus> =
+        repository.authenticationStatus.filterIsInstance<FailFingerprintAuthenticationStatus>()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractor.kt
index 53d6f73..649a971 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractor.kt
@@ -19,7 +19,6 @@
 import com.android.systemui.biometrics.data.repository.FingerprintPropertyRepository
 import com.android.systemui.biometrics.shared.model.FingerprintSensorType
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.deviceentry.data.repository.DeviceEntryHapticsRepository
 import com.android.systemui.keyevent.domain.interactor.KeyEventInteractor
 import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
 import com.android.systemui.power.domain.interactor.PowerInteractor
@@ -34,11 +33,12 @@
 import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.merge
 import kotlinx.coroutines.flow.onStart
 
 /**
  * Business logic for device entry haptic events. Determines whether the haptic should play. In
- * particular, there are extra guards for whether device entry error and successes hatpics should
+ * particular, there are extra guards for whether device entry error and successes haptics should
  * play when the physical fingerprint sensor is located on the power button.
  */
 @ExperimentalCoroutinesApi
@@ -46,7 +46,9 @@
 class DeviceEntryHapticsInteractor
 @Inject
 constructor(
-    private val repository: DeviceEntryHapticsRepository,
+    deviceEntryInteractor: DeviceEntryInteractor,
+    deviceEntryFingerprintAuthInteractor: DeviceEntryFingerprintAuthInteractor,
+    deviceEntryBiometricAuthInteractor: DeviceEntryBiometricAuthInteractor,
     fingerprintPropertyRepository: FingerprintPropertyRepository,
     biometricSettingsRepository: BiometricSettingsRepository,
     keyEventInteractor: KeyEventInteractor,
@@ -77,9 +79,8 @@
                 emit(recentPowerButtonPressThresholdMs * -1L - 1L)
             }
 
-    val playSuccessHaptic: Flow<Boolean> =
-        repository.successHapticRequest
-            .filter { it }
+    val playSuccessHaptic: Flow<Unit> =
+        deviceEntryInteractor.enteringDeviceFromBiometricUnlock
             .sample(
                 combine(
                     powerButtonSideFpsEnrolled,
@@ -88,7 +89,7 @@
                     ::Triple
                 )
             )
-            .map { (sideFpsEnrolled, powerButtonDown, lastPowerButtonWakeup) ->
+            .filter { (sideFpsEnrolled, powerButtonDown, lastPowerButtonWakeup) ->
                 val sideFpsAllowsHaptic =
                     !powerButtonDown &&
                         systemClock.uptimeMillis() - lastPowerButtonWakeup >
@@ -96,38 +97,28 @@
                 val allowHaptic = !sideFpsEnrolled || sideFpsAllowsHaptic
                 if (!allowHaptic) {
                     logger.d("Skip success haptic. Recent power button press or button is down.")
-                    handleSuccessHaptic() // immediately handle, don't vibrate
                 }
                 allowHaptic
             }
-    val playErrorHaptic: Flow<Boolean> =
-        repository.errorHapticRequest
-            .filter { it }
+            .map {} // map to Unit
+
+    private val playErrorHapticForBiometricFailure: Flow<Unit> =
+        merge(
+                deviceEntryFingerprintAuthInteractor.fingerprintFailure,
+                deviceEntryBiometricAuthInteractor.faceOnlyFaceFailure,
+            )
+            .map {} // map to Unit
+    val playErrorHaptic: Flow<Unit> =
+        playErrorHapticForBiometricFailure
             .sample(combine(powerButtonSideFpsEnrolled, powerButtonDown, ::Pair))
-            .map { (sideFpsEnrolled, powerButtonDown) ->
+            .filter { (sideFpsEnrolled, powerButtonDown) ->
                 val allowHaptic = !sideFpsEnrolled || !powerButtonDown
                 if (!allowHaptic) {
                     logger.d("Skip error haptic. Power button is down.")
-                    handleErrorHaptic() // immediately handle, don't vibrate
                 }
                 allowHaptic
             }
-
-    fun vibrateSuccess() {
-        repository.requestSuccessHaptic()
-    }
-
-    fun vibrateError() {
-        repository.requestErrorHaptic()
-    }
-
-    fun handleSuccessHaptic() {
-        repository.handleSuccessHaptic()
-    }
-
-    fun handleErrorHaptic() {
-        repository.handleErrorHaptic()
-    }
+            .map {} // map to Unit
 
     private val recentPowerButtonPressThresholdMs = 400L
 }
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt
index 4cddb9c..47be8ab 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt
@@ -23,6 +23,7 @@
 import com.android.systemui.deviceentry.data.repository.DeviceEntryRepository
 import com.android.systemui.keyguard.data.repository.DeviceEntryFaceAuthRepository
 import com.android.systemui.keyguard.data.repository.TrustRepository
+import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
 import com.android.systemui.scene.domain.interactor.SceneInteractor
 import com.android.systemui.scene.shared.flag.SceneContainerFlags
 import com.android.systemui.scene.shared.model.SceneKey
@@ -30,6 +31,7 @@
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.collectLatest
@@ -60,6 +62,9 @@
     trustRepository: TrustRepository,
     flags: SceneContainerFlags,
 ) {
+    val enteringDeviceFromBiometricUnlock: Flow<BiometricUnlockSource> =
+        repository.enteringDeviceFromBiometricUnlock
+
     /**
      * Whether the device is unlocked.
      *
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/shared/DeviceEntryBiometricMode.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/shared/DeviceEntryBiometricMode.kt
new file mode 100644
index 0000000..6d885b3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/shared/DeviceEntryBiometricMode.kt
@@ -0,0 +1,29 @@
+/*
+ * 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.deviceentry.shared
+
+/** Models the biometrics that can be used to enter the device. */
+enum class DeviceEntryBiometricMode {
+    /** No biometrics can be used to enter the device from the lockscreen. */
+    NONE,
+    /** Only face can be used to enter the device from the lockscreen. */
+    FACE_ONLY,
+    /** Only fingerprint can be used to enter the device from the lockscreen. */
+    FINGERPRINT_ONLY,
+    /** Both face and fingerprint can be used to enter the device from the lockscreen. */
+    CO_EXPERIENCE,
+}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeAuthRemover.java b/packages/SystemUI/src/com/android/systemui/doze/DozeAuthRemover.java
index 9c13a8c..3fac865 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeAuthRemover.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeAuthRemover.java
@@ -43,7 +43,7 @@
         if (newState == DozeMachine.State.DOZE || newState == DozeMachine.State.DOZE_AOD) {
             int currentUser = mSelectedUserInteractor.getSelectedUserId();
             if (mKeyguardUpdateMonitor.getUserUnlockedWithBiometric(currentUser)) {
-                mKeyguardUpdateMonitor.clearBiometricRecognized();
+                mKeyguardUpdateMonitor.clearFingerprintRecognized();
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/dump/LogBufferFreezer.kt b/packages/SystemUI/src/com/android/systemui/dump/LogBufferFreezer.kt
index 29f4642..a97d505 100644
--- a/packages/SystemUI/src/com/android/systemui/dump/LogBufferFreezer.kt
+++ b/packages/SystemUI/src/com/android/systemui/dump/LogBufferFreezer.kt
@@ -20,6 +20,7 @@
 import android.content.Context
 import android.content.Intent
 import android.content.IntentFilter
+import android.os.Trace
 import android.os.UserHandle
 import android.util.Log
 import com.android.systemui.broadcast.BroadcastDispatcher
@@ -53,6 +54,8 @@
     }
 
     private fun onBugreportStarted() {
+        Trace.instantForTrack(Trace.TRACE_TAG_APP, "bugreport",
+                "BUGREPORT_STARTED broadcast received")
         pendingToken?.run()
 
         Log.i(TAG, "Freezing log buffers")
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsClassicDebug.java b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsClassicDebug.java
index 87c12b4..72b0891 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsClassicDebug.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsClassicDebug.java
@@ -25,7 +25,6 @@
 import static com.android.systemui.flags.FlagManager.EXTRA_VALUE;
 import static com.android.systemui.flags.FlagsCommonModule.ALL_FLAGS;
 import static com.android.systemui.shared.Flags.exampleSharedFlag;
-
 import static java.util.Objects.requireNonNull;
 
 import android.content.BroadcastReceiver;
@@ -508,9 +507,7 @@
                 enabled = isEnabled((ResourceBooleanFlag) f);
                 overridden = readBooleanFlagOverride(f.getName()) != null;
             } else if (f instanceof SysPropBooleanFlag) {
-                // TODO(b/223379190): Teamfood not supported for sysprop flags yet.
                 enabled = isEnabled((SysPropBooleanFlag) f);
-                teamfood = false;
                 overridden = !mSystemProperties.get(f.getName()).isEmpty();
             } else {
                 // TODO: add support for other flag types.
@@ -519,7 +516,7 @@
             }
 
             if (enabled) {
-                return new ReleasedFlag(f.getName(), f.getNamespace(), teamfood, overridden);
+                return new ReleasedFlag(f.getName(), f.getNamespace(), overridden);
             } else {
                 return new UnreleasedFlag(f.getName(), f.getNamespace(), teamfood, overridden);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt b/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt
index 6a0e882..5ec51f4 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt
@@ -16,7 +16,16 @@
 
 package com.android.systemui.flags
 
+import com.android.server.notification.Flags.FLAG_CROSS_APP_POLITE_NOTIFICATIONS
+import com.android.server.notification.Flags.FLAG_POLITE_NOTIFICATIONS
+import com.android.server.notification.Flags.FLAG_VIBRATE_WHILE_UNLOCKED
+import com.android.server.notification.Flags.crossAppPoliteNotifications
+import com.android.server.notification.Flags.politeNotifications
+import com.android.server.notification.Flags.vibrateWhileUnlocked
+import com.android.systemui.Flags.FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR
+import com.android.systemui.Flags.keyguardBottomAreaRefactor
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.shared.KeyguardShadeMigrationNssl
 import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor
 import com.android.systemui.statusbar.notification.shared.NotificationIconContainerRefactor
 import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor
@@ -29,5 +38,18 @@
     override fun defineDependencies() {
         NotificationsLiveDataStoreRefactor.token dependsOn NotificationIconContainerRefactor.token
         FooterViewRefactor.token dependsOn NotificationIconContainerRefactor.token
+
+        val keyguardBottomAreaRefactor = FlagToken(
+                FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR, keyguardBottomAreaRefactor())
+        KeyguardShadeMigrationNssl.token dependsOn keyguardBottomAreaRefactor
+
+        val crossAppPoliteNotifToken =
+                FlagToken(FLAG_CROSS_APP_POLITE_NOTIFICATIONS, crossAppPoliteNotifications())
+        val politeNotifToken = FlagToken(FLAG_POLITE_NOTIFICATIONS, politeNotifications())
+        crossAppPoliteNotifToken dependsOn politeNotifToken
+
+        val vibrateWhileUnlockedToken =
+                FlagToken(FLAG_VIBRATE_WHILE_UNLOCKED, vibrateWhileUnlocked())
+        vibrateWhileUnlockedToken dependsOn politeNotifToken
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FlagDependenciesBase.kt b/packages/SystemUI/src/com/android/systemui/flags/FlagDependenciesBase.kt
index ae3b501..e96660f 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FlagDependenciesBase.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/FlagDependenciesBase.kt
@@ -25,7 +25,7 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.util.Compile
 import com.android.systemui.util.asIndenting
-import com.android.systemui.util.withIncreasedIndent
+import com.android.systemui.util.printCollection
 import dagger.Binds
 import dagger.Module
 import dagger.multibindings.ClassKey
@@ -59,10 +59,8 @@
 
     override fun dump(pw: PrintWriter, args: Array<out String>) {
         pw.asIndenting().run {
-            println("allDependencies: ${allDependencies.size}")
-            withIncreasedIndent { allDependencies.forEach(::println) }
-            println("unmetDependencies: ${unmetDependencies.size}")
-            withIncreasedIndent { unmetDependencies.forEach(::println) }
+            printCollection("allDependencies", allDependencies)
+            printCollection("unmetDependencies", unmetDependencies)
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index e8ceabf..b1d4587 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -111,7 +111,7 @@
     // TODO(b/301955929)
     @JvmField
     val NOTIF_LS_BACKGROUND_THREAD =
-            unreleasedFlag("notification_lockscreen_mgr_bg_thread", teamfood = true)
+            releasedFlag("notification_lockscreen_mgr_bg_thread")
 
     // 200 - keyguard/lockscreen
     // ** Flag retired **
@@ -278,10 +278,6 @@
             "qs_user_detail_shortcut"
         )
 
-    // TODO(b/296357483): Tracking Bug
-    @JvmField
-    val QS_PIPELINE_NEW_TILES = unreleasedFlag("qs_pipeline_new_tiles")
-
     // TODO(b/254512383): Tracking Bug
     @JvmField
     val FULL_SCREEN_USER_SWITCHER =
@@ -441,11 +437,6 @@
     // 1200 - predictive back
     @Keep
     @JvmField
-    val WM_ENABLE_PREDICTIVE_BACK =
-        sysPropBooleanFlag("persist.wm.debug.predictive_back", default = true)
-
-    @Keep
-    @JvmField
     val WM_ENABLE_PREDICTIVE_BACK_ANIM =
         sysPropBooleanFlag("persist.wm.debug.predictive_back_anim", default = true)
 
diff --git a/packages/SystemUI/src/com/android/systemui/flags/RefactorFlagUtils.kt b/packages/SystemUI/src/com/android/systemui/flags/RefactorFlagUtils.kt
index ae67e60..4d89a82 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/RefactorFlagUtils.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/RefactorFlagUtils.kt
@@ -79,6 +79,22 @@
         check(!isEnabled) { "Legacy code path not supported when $flagName is enabled." }
 
     /**
+     * Called to ensure the new code is only run when the flag is enabled. This will throw an
+     * exception if the flag is disabled to ensure that the refactor author catches issues in
+     * testing.
+     *
+     * Example usage:
+     * ```
+     * public void setSomeNewController(SomeController someController) {
+     *     SomeRefactor.assertInNewMode();
+     *     mSomeController = someController;
+     * }
+     * ````
+     */
+    inline fun assertInNewMode(isEnabled: Boolean, flagName: Any) =
+        check(isEnabled) { "New code path not supported when $flagName is disabled." }
+
+    /**
      * This will [Log.wtf] with the given message, assuming [ASSERT_TAG] is loggable at that level.
      * This means an engineer can prevent this from crashing by running the command:
      * ```
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
index 5cc2e0a..45433e6 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
@@ -60,6 +60,7 @@
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.SystemProperties;
+import android.os.Trace;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
@@ -1052,6 +1053,7 @@
             if (ActivityManager.isUserAMonkey()) {
                 return;
             }
+            Trace.instantForTrack(Trace.TRACE_TAG_APP, "bugreport", "BugReportAction#onPress");
             // Add a little delay before executing, to give the
             // dialog a chance to go away before it takes a
             // screenshot.
@@ -1065,6 +1067,8 @@
                         mUiEventLogger.log(GlobalActionsEvent.GA_BUGREPORT_PRESS);
                         if (!mIActivityManager.launchBugReportHandlerApp()) {
                             Log.w(TAG, "Bugreport handler could not be launched");
+                            Trace.instantForTrack(Trace.TRACE_TAG_APP, "bugreport",
+                                    "BugReportAction#requestingInteractiveBugReport");
                             mIActivityManager.requestInteractiveBugReport();
                         }
                     } catch (RemoteException e) {
@@ -1084,6 +1088,8 @@
                 // Take a "full" bugreport.
                 mMetricsLogger.action(MetricsEvent.ACTION_BUGREPORT_FROM_POWER_MENU_FULL);
                 mUiEventLogger.log(GlobalActionsEvent.GA_BUGREPORT_LONG_PRESS);
+                Trace.instantForTrack(Trace.TRACE_TAG_APP, "bugreport",
+                        "BugReportAction#requestingFullBugReport");
                 mIActivityManager.requestFullBugReport();
             } catch (RemoteException e) {
             }
diff --git a/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderHapticFeedbackConfig.kt b/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderHapticFeedbackConfig.kt
index 7b33e11..6cb68ba 100644
--- a/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderHapticFeedbackConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderHapticFeedbackConfig.kt
@@ -42,4 +42,6 @@
     @FloatRange(from = 0.0, to = 1.0) val upperBookendScale: Float = 1f,
     /** Vibration scale at the lower bookend of the slider */
     @FloatRange(from = 0.0, to = 1.0) val lowerBookendScale: Float = 0.05f,
+    /** Exponent for power function compensation */
+    @FloatRange(from = 0.0, fromInclusive = false) val exponent: Float = 1f / 0.89f,
 )
diff --git a/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProvider.kt b/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProvider.kt
index f313fb3..9e6245a 100644
--- a/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProvider.kt
@@ -21,9 +21,11 @@
 import android.view.VelocityTracker
 import android.view.animation.AccelerateInterpolator
 import androidx.annotation.FloatRange
+import androidx.annotation.VisibleForTesting
 import com.android.systemui.statusbar.VibratorHelper
 import kotlin.math.abs
 import kotlin.math.min
+import kotlin.math.pow
 
 /**
  * Listener of slider events that triggers haptic feedback.
@@ -63,18 +65,29 @@
      * @param[absoluteVelocity] Velocity of the handle when it reached the bookend.
      */
     private fun vibrateOnEdgeCollision(absoluteVelocity: Float) {
+        val powerScale = scaleOnEdgeCollision(absoluteVelocity)
+        val vibration =
+            VibrationEffect.startComposition()
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, powerScale)
+                .compose()
+        vibratorHelper.vibrate(vibration, VIBRATION_ATTRIBUTES_PIPELINING)
+    }
+
+    /**
+     * Get the velocity-based scale at the bookends
+     *
+     * @param[absoluteVelocity] Velocity of the handle when it reached the bookend.
+     * @return The power scale for the vibration.
+     */
+    @VisibleForTesting
+    fun scaleOnEdgeCollision(absoluteVelocity: Float): Float {
         val velocityInterpolated =
             velocityAccelerateInterpolator.getInterpolation(
                 min(absoluteVelocity / config.maxVelocityToScale, 1f)
             )
         val bookendScaleRange = config.upperBookendScale - config.lowerBookendScale
         val bookendsHitScale = bookendScaleRange * velocityInterpolated + config.lowerBookendScale
-
-        val vibration =
-            VibrationEffect.startComposition()
-                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, bookendsHitScale)
-                .compose()
-        vibratorHelper.vibrate(vibration, VIBRATION_ATTRIBUTES_PIPELINING)
+        return bookendsHitScale.pow(config.exponent)
     }
 
     /**
@@ -96,6 +109,31 @@
         val deltaProgress = abs(normalizedSliderProgress - dragTextureLastProgress)
         if (deltaProgress < config.deltaProgressForDragThreshold) return
 
+        val powerScale = scaleOnDragTexture(absoluteVelocity, normalizedSliderProgress)
+
+        // Trigger the vibration composition
+        val composition = VibrationEffect.startComposition()
+        repeat(config.numberOfLowTicks) {
+            composition.addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK, powerScale)
+        }
+        vibratorHelper.vibrate(composition.compose(), VIBRATION_ATTRIBUTES_PIPELINING)
+        dragTextureLastTime = currentTime
+        dragTextureLastProgress = normalizedSliderProgress
+    }
+
+    /**
+     * Get the scale of the drag texture vibration.
+     *
+     * @param[absoluteVelocity] Absolute velocity of the handle.
+     * @param[normalizedSliderProgress] Progress of the slider handled normalized to the range from
+     *   0F to 1F (inclusive).
+     *     @return the scale of the vibration.
+     */
+    @VisibleForTesting
+    fun scaleOnDragTexture(
+        absoluteVelocity: Float,
+        @FloatRange(from = 0.0, to = 1.0) normalizedSliderProgress: Float
+    ): Float {
         val velocityInterpolated =
             velocityAccelerateInterpolator.getInterpolation(
                 min(absoluteVelocity / config.maxVelocityToScale, 1f)
@@ -113,15 +151,7 @@
 
         // Total scale
         val scale = positionBasedScale + velocityBasedScale
-
-        // Trigger the vibration composition
-        val composition = VibrationEffect.startComposition()
-        repeat(config.numberOfLowTicks) {
-            composition.addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK, scale)
-        }
-        vibratorHelper.vibrate(composition.compose(), VIBRATION_ATTRIBUTES_PIPELINING)
-        dragTextureLastTime = currentTime
-        dragTextureLastProgress = normalizedSliderProgress
+        return scale.pow(config.exponent)
     }
 
     override fun onHandleAcquiredByTouch() {}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 33dd3d9..edf9648 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -35,7 +35,7 @@
 import static android.view.WindowManager.TransitionOldType;
 import static android.view.WindowManager.TransitionType;
 
-import static com.android.systemui.flags.Flags.REFACTOR_GETCURRENTUSER;
+import static com.android.systemui.Flags.refactorGetCurrentUser;
 
 import android.annotation.NonNull;
 import android.app.ActivityManager;
@@ -609,7 +609,7 @@
         public void setCurrentUser(int userId) {
             trace("Deprecated/NOT USED: setCurrentUser userId=" + userId);
             checkPermission();
-            if (!mFlags.isEnabled(REFACTOR_GETCURRENTUSER)) {
+            if (!refactorGetCurrentUser()) {
                 mKeyguardViewMediator.setCurrentUser(userId);
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 3009087..d7a1906 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -38,7 +38,7 @@
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE;
 import static com.android.systemui.DejankUtils.whitelistIpcs;
-import static com.android.systemui.flags.Flags.REFACTOR_GETCURRENTUSER;
+import static com.android.systemui.Flags.refactorGetCurrentUser;
 import static com.android.systemui.keyguard.ui.viewmodel.LockscreenToDreamingTransitionViewModel.DREAMING_ANIMATION_DURATION_MS;
 import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
 
@@ -141,6 +141,7 @@
 import com.android.systemui.flags.Flags;
 import com.android.systemui.flags.SystemPropertiesHelper;
 import com.android.systemui.keyguard.dagger.KeyguardModule;
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
 import com.android.systemui.keyguard.shared.model.TransitionStep;
 import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
 import com.android.systemui.log.SessionTracker;
@@ -616,7 +617,7 @@
         public void onUserSwitching(int userId) {
             if (DEBUG) Log.d(TAG, String.format("onUserSwitching %d", userId));
             synchronized (KeyguardViewMediator.this) {
-                if (mFeatureFlags.isEnabled(REFACTOR_GETCURRENTUSER)) {
+                if (refactorGetCurrentUser()) {
                     notifyTrustedChangedLocked(mUpdateMonitor.getUserHasTrust(userId));
                 }
                 resetKeyguardDonePendingLocked();
@@ -1319,6 +1320,7 @@
     private DeviceConfigProxy mDeviceConfig;
     private DozeParameters mDozeParameters;
     private SelectedUserInteractor mSelectedUserInteractor;
+    private KeyguardInteractor mKeyguardInteractor;
 
     private final KeyguardStateController mKeyguardStateController;
     private final KeyguardStateController.Callback mKeyguardStateControllerCallback =
@@ -1400,7 +1402,8 @@
             Lazy<DreamingToLockscreenTransitionViewModel> dreamingToLockscreenTransitionViewModel,
             SystemPropertiesHelper systemPropertiesHelper,
             Lazy<WindowManagerLockscreenVisibilityManager> wmLockscreenVisibilityManager,
-            SelectedUserInteractor selectedUserInteractor) {
+            SelectedUserInteractor selectedUserInteractor,
+            KeyguardInteractor keyguardInteractor) {
         mContext = context;
         mUserTracker = userTracker;
         mFalsingCollector = falsingCollector;
@@ -1441,6 +1444,7 @@
                 }));
         mDozeParameters = dozeParameters;
         mSelectedUserInteractor = selectedUserInteractor;
+        mKeyguardInteractor = keyguardInteractor;
 
         mStatusBarStateController = statusBarStateController;
         statusBarStateController.addCallback(this);
@@ -1498,7 +1502,7 @@
 
         mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
 
-        if (!mFeatureFlags.isEnabled(REFACTOR_GETCURRENTUSER)) {
+        if (!refactorGetCurrentUser()) {
             KeyguardUpdateMonitor.setCurrentUser(mUserTracker.getUserId());
         }
 
@@ -2611,14 +2615,15 @@
         }
 
         if (mGoingToSleep) {
-            mUpdateMonitor.clearBiometricRecognizedWhenKeyguardDone(currentUser);
+            mUpdateMonitor.clearFingerprintRecognizedWhenKeyguardDone(currentUser);
             Log.i(TAG, "Device is going to sleep, aborting keyguardDone");
             return;
         }
         setPendingLock(false); // user may have authenticated during the screen off animation
 
         handleHide();
-        mUpdateMonitor.clearBiometricRecognizedWhenKeyguardDone(currentUser);
+        mKeyguardInteractor.keyguardDoneAnimationsFinished();
+        mUpdateMonitor.clearFingerprintRecognizedWhenKeyguardDone(currentUser);
         Trace.endSection();
     }
 
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 331d892..3925dd1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -52,6 +52,7 @@
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardDataQuickAffordanceModule;
 import com.android.systemui.keyguard.data.repository.KeyguardFaceAuthModule;
 import com.android.systemui.keyguard.data.repository.KeyguardRepositoryModule;
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
 import com.android.systemui.keyguard.domain.interactor.StartKeyguardTransitionModule;
 import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancesMetricsLogger;
 import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancesMetricsLoggerImpl;
@@ -154,7 +155,8 @@
             Lazy<DreamingToLockscreenTransitionViewModel> dreamingToLockscreenTransitionViewModel,
             SystemPropertiesHelper systemPropertiesHelper,
             Lazy<WindowManagerLockscreenVisibilityManager> wmLockscreenVisibilityManager,
-            SelectedUserInteractor selectedUserInteractor) {
+            SelectedUserInteractor selectedUserInteractor,
+            KeyguardInteractor keyguardInteractor) {
         return new KeyguardViewMediator(
                 context,
                 uiEventLogger,
@@ -199,7 +201,8 @@
                 dreamingToLockscreenTransitionViewModel,
                 systemPropertiesHelper,
                 wmLockscreenVisibilityManager,
-                selectedUserInteractor);
+                selectedUserInteractor,
+                keyguardInteractor);
     }
 
     /** */
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt
index e47c448..4d60dd0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt
@@ -187,7 +187,8 @@
         faceManager?.sensorPropertiesInternal?.firstOrNull()?.supportsFaceDetection ?: false
 
     private val _isAuthRunning = MutableStateFlow(false)
-    override val isAuthRunning: StateFlow<Boolean> = _isAuthRunning
+    override val isAuthRunning: StateFlow<Boolean>
+        get() = _isAuthRunning
 
     private val keyguardSessionId: InstanceId?
         get() = sessionTracker.getSessionId(StatusBarManager.SESSION_KEYGUARD)
@@ -253,13 +254,6 @@
                 )
                 .andAllFlows("canFaceAuthRun", faceAuthLog)
                 .flowOn(backgroundDispatcher)
-                .onEach {
-                    faceAuthLogger.canFaceAuthRunChanged(it)
-                    if (!it) {
-                        // Cancel currently running auth if any of the gating checks are false.
-                        cancel()
-                    }
-                }
                 .stateIn(applicationScope, SharingStarted.Eagerly, false)
 
         // Face detection can run only when lockscreen bypass is enabled
@@ -287,12 +281,9 @@
                 )
                 .andAllFlows("canFaceDetectRun", faceDetectLog)
                 .flowOn(backgroundDispatcher)
-                .onEach {
-                    if (!it) {
-                        cancelDetection()
-                    }
-                }
                 .stateIn(applicationScope, SharingStarted.Eagerly, false)
+        observeFaceAuthGatingChecks()
+        observeFaceDetectGatingChecks()
         observeFaceAuthResettingConditions()
         listenForSchedulingWatchdog()
         processPendingAuthRequests()
@@ -313,20 +304,20 @@
     }
 
     private fun observeFaceAuthResettingConditions() {
-        // Clear auth status when keyguard is going away or when the user is switching or device
-        // starts going to sleep.
+        // Clear auth status when keyguard done animations finished or when the user is switching
+        // or device starts going to sleep.
         merge(
                 powerInteractor.isAsleep,
                 if (featureFlags.isEnabled(Flags.KEYGUARD_WM_STATE_REFACTOR)) {
                     keyguardTransitionInteractor.isInTransitionToState(KeyguardState.GONE)
                 } else {
-                    keyguardRepository.isKeyguardGoingAway
+                    keyguardRepository.keyguardDoneAnimationsFinished.map { true }
                 },
                 userRepository.selectedUser.map {
                     it.selectionStatus == SelectionStatus.SELECTION_IN_PROGRESS
                 },
             )
-            .flowOn(backgroundDispatcher)
+            .flowOn(mainDispatcher) // should revoke auth ASAP in the main thread
             .onEach { anyOfThemIsTrue ->
                 if (anyOfThemIsTrue) {
                     clearPendingAuthRequest("Resetting auth status")
@@ -347,6 +338,17 @@
         pendingAuthenticateRequest.value = null
     }
 
+    private fun observeFaceDetectGatingChecks() {
+        canRunDetection
+            .onEach {
+                if (!it) {
+                    cancelDetection()
+                }
+            }
+            .flowOn(mainDispatcher)
+            .launchIn(applicationScope)
+    }
+
     private fun isUdfps() =
         deviceEntryFingerprintAuthRepository.availableFpSensorType.map {
             it == BiometricType.UNDER_DISPLAY_FINGERPRINT
@@ -405,6 +407,20 @@
         )
     }
 
+    private fun observeFaceAuthGatingChecks() {
+        canRunFaceAuth
+            .onEach {
+                faceAuthLogger.canFaceAuthRunChanged(it)
+                if (!it) {
+                    // Cancel currently running auth if any of the gating checks are false.
+                    faceAuthLogger.cancellingFaceAuth()
+                    cancel()
+                }
+            }
+            .flowOn(mainDispatcher)
+            .launchIn(applicationScope)
+    }
+
     private val faceAuthCallback =
         object : FaceManager.AuthenticationCallback() {
             override fun onAuthenticationFailed() {
@@ -539,7 +555,7 @@
                     authenticate(it.uiEvent, it.fallbackToDetection)
                 }
             }
-            .flowOn(backgroundDispatcher)
+            .flowOn(mainDispatcher)
             .launchIn(applicationScope)
     }
 
@@ -635,7 +651,6 @@
     override fun cancel() {
         if (authCancellationSignal == null) return
 
-        faceAuthLogger.cancellingFaceAuth()
         authCancellationSignal?.cancel()
         cancelNotReceivedHandlerJob?.cancel()
         cancelNotReceivedHandlerJob =
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepository.kt
index 96386f3..9a13558d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepository.kt
@@ -41,6 +41,7 @@
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.shareIn
 import kotlinx.coroutines.flow.stateIn
 
 /** Encapsulates state about device entry fingerprint auth mechanism. */
@@ -61,6 +62,9 @@
 
     /** Provide the current status of fingerprint authentication. */
     val authenticationStatus: Flow<FingerprintAuthenticationStatus>
+
+    /** Indicates whether to update the side fingerprint sensor indicator visibility. */
+    val shouldUpdateIndicatorVisibility: Flow<Boolean>
 }
 
 /**
@@ -256,6 +260,37 @@
             awaitClose { keyguardUpdateMonitor.removeCallback(callback) }
         }
 
+    override val shouldUpdateIndicatorVisibility: Flow<Boolean> =
+        conflatedCallbackFlow {
+                val sendShouldUpdateIndicatorVisibility =
+                    { shouldUpdateIndicatorVisibility: Boolean ->
+                        trySendWithFailureLogging(
+                            shouldUpdateIndicatorVisibility,
+                            TAG,
+                            "Error sending shouldUpdateIndicatorVisibility " +
+                                "$shouldUpdateIndicatorVisibility"
+                        )
+                    }
+
+                val callback =
+                    object : KeyguardUpdateMonitorCallback() {
+                        override fun onBiometricRunningStateChanged(
+                            running: Boolean,
+                            biometricSourceType: BiometricSourceType?
+                        ) {
+                            sendShouldUpdateIndicatorVisibility(true)
+                        }
+                        override fun onStrongAuthStateChanged(userId: Int) {
+                            sendShouldUpdateIndicatorVisibility(true)
+                        }
+                    }
+                sendShouldUpdateIndicatorVisibility(false)
+                keyguardUpdateMonitor.registerCallback(callback)
+                awaitClose { keyguardUpdateMonitor.removeCallback(callback) }
+            }
+            .flowOn(mainDispatcher)
+            .shareIn(scope, started = SharingStarted.WhileSubscribed(), replay = 1)
+
     companion object {
         const val TAG = "DeviceEntryFingerprintAuthRepositoryImpl"
     }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepository.kt
index fbd62ce..48b6634 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepository.kt
@@ -28,7 +28,7 @@
 import javax.inject.Inject
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableSharedFlow
-import kotlinx.coroutines.flow.asSharedFlow
+import kotlinx.coroutines.flow.MutableStateFlow
 
 /**
  * Manages blueprint changes for the lockscreen.
@@ -48,17 +48,14 @@
     configurationRepository: ConfigurationRepository,
     blueprints: Set<@JvmSuppressWildcards KeyguardBlueprint>,
 ) {
-    private val blueprintIdMap: TreeMap<String, KeyguardBlueprint> = TreeMap()
-    private val _blueprint: MutableSharedFlow<KeyguardBlueprint> = MutableSharedFlow(replay = 1)
-    val blueprint: Flow<KeyguardBlueprint> = _blueprint.asSharedFlow()
-
+    // This is TreeMap so that we can order the blueprints and assign numerical values to the
+    // blueprints in the adb tool.
+    private val blueprintIdMap: TreeMap<String, KeyguardBlueprint> =
+        TreeMap<String, KeyguardBlueprint>().apply { putAll(blueprints.associateBy { it.id }) }
+    val blueprint: MutableStateFlow<KeyguardBlueprint> = MutableStateFlow(blueprintIdMap[DEFAULT]!!)
+    val refreshBluePrint: MutableSharedFlow<Unit> = MutableSharedFlow(extraBufferCapacity = 1)
     val configurationChange: Flow<Unit> = configurationRepository.onAnyConfigurationChange
 
-    init {
-        blueprintIdMap.putAll(blueprints.associateBy { it.id })
-        applyBlueprint(blueprintIdMap[DEFAULT]!!)
-    }
-
     /**
      * Emits the blueprint value to the collectors.
      *
@@ -96,14 +93,17 @@
 
     /** Emits the blueprint value to the collectors. */
     fun applyBlueprint(blueprint: KeyguardBlueprint?) {
-        blueprint?.let { _blueprint.tryEmit(it) }
+        if (blueprint == this.blueprint.value) {
+            refreshBlueprint()
+            return
+        }
+
+        blueprint?.let { this.blueprint.value = it }
     }
 
     /** Re-emits the last emitted blueprint value if possible. */
     fun refreshBlueprint() {
-        if (_blueprint.replayCache.isNotEmpty()) {
-            _blueprint.tryEmit(_blueprint.replayCache.last())
-        }
+        refreshBluePrint.tryEmit(Unit)
     }
 
     /** Prints all available blueprints to the PrintWriter. */
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
index b51edab6..31ef100 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
@@ -160,6 +160,9 @@
     /** Last point that [KeyguardRootView] was tapped */
     val lastRootViewTapPosition: MutableStateFlow<Point?>
 
+    /** Is the ambient indication area visible? */
+    val ambientIndicationVisible: MutableStateFlow<Boolean>
+
     /** Observable for the [StatusBarState] */
     val statusBarState: StateFlow<StatusBarState>
 
@@ -189,6 +192,17 @@
     /** Observable updated when keyguardDone should be called either now or soon. */
     val keyguardDone: Flow<KeyguardDone>
 
+    /**
+     * Emits after the keyguard is done animating away.
+     *
+     * TODO(b/278086361): Remove once KEYGUARD_WM_STATE_REFACTOR flag is removed.
+     */
+    @Deprecated(
+        "Use KeyguardTransitionInteractor flows instead. The closest match for " +
+            "'keyguardDoneAnimationsFinished' is when the GONE transition is finished."
+    )
+    val keyguardDoneAnimationsFinished: Flow<Unit>
+
     /** Receive whether clock should be centered on lockscreen. */
     val clockShouldBeCentered: Flow<Boolean>
 
@@ -236,6 +250,17 @@
     suspend fun setKeyguardDone(keyguardDoneType: KeyguardDone)
 
     fun setClockShouldBeCentered(shouldBeCentered: Boolean)
+
+    /**
+     * Updates signal that the keyguard done animations are finished
+     *
+     * TODO(b/278086361): Remove once KEYGUARD_WM_STATE_REFACTOR flag is removed.
+     */
+    @Deprecated(
+        "Use KeyguardTransitionInteractor flows instead. The closest match for " +
+            "'keyguardDoneAnimationsFinished' is when the GONE transition is finished."
+    )
+    fun keyguardDoneAnimationsFinished()
 }
 
 /** Encapsulates application state for the keyguard. */
@@ -266,6 +291,11 @@
         _keyguardDone.emit(keyguardDoneType)
     }
 
+    override val keyguardDoneAnimationsFinished: MutableSharedFlow<Unit> = MutableSharedFlow()
+    override fun keyguardDoneAnimationsFinished() {
+        keyguardDoneAnimationsFinished.tryEmit(Unit)
+    }
+
     private val _animateBottomAreaDozingTransitions = MutableStateFlow(false)
     override val animateBottomAreaDozingTransitions =
         _animateBottomAreaDozingTransitions.asStateFlow()
@@ -423,6 +453,8 @@
 
     override val lastRootViewTapPosition: MutableStateFlow<Point?> = MutableStateFlow(null)
 
+    override val ambientIndicationVisible: MutableStateFlow<Boolean> = MutableStateFlow(false)
+
     override val isDreamingWithOverlay: Flow<Boolean> =
         conflatedCallbackFlow {
                 val callback =
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractor.kt
new file mode 100644
index 0000000..de15fd6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractor.kt
@@ -0,0 +1,92 @@
+/*
+ *   Copyright (C) 2023 The Android Open Source Project
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ */
+
+package com.android.systemui.keyguard.domain.interactor
+
+import android.content.Context
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository
+import com.android.systemui.res.R
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.merge
+
+/**
+ * Encapsulates business logic for device entry events that impact the side fingerprint sensor
+ * overlay.
+ */
+@SysUISingleton
+class DeviceEntrySideFpsOverlayInteractor
+@Inject
+constructor(
+    @Application private val context: Context,
+    deviceEntryFingerprintAuthRepository: DeviceEntryFingerprintAuthRepository,
+    private val primaryBouncerInteractor: PrimaryBouncerInteractor,
+    alternateBouncerInteractor: AlternateBouncerInteractor,
+    private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
+) {
+
+    init {
+        alternateBouncerInteractor.setAlternateBouncerUIAvailable(true, TAG)
+    }
+
+    private val showIndicatorForPrimaryBouncer: Flow<Boolean> =
+        merge(
+                primaryBouncerInteractor.isShowing,
+                primaryBouncerInteractor.startingToHide,
+                primaryBouncerInteractor.startingDisappearAnimation.filterNotNull(),
+                deviceEntryFingerprintAuthRepository.shouldUpdateIndicatorVisibility.filter { it }
+            )
+            .map { shouldShowIndicatorForPrimaryBouncer() }
+
+    private val showIndicatorForAlternateBouncer: Flow<Boolean> =
+        alternateBouncerInteractor.isVisible
+
+    /**
+     * Indicates whether the primary or alternate bouncers request showing the side fingerprint
+     * sensor indicator.
+     */
+    val showIndicatorForDeviceEntry: Flow<Boolean> =
+        combine(showIndicatorForPrimaryBouncer, showIndicatorForAlternateBouncer) {
+            showForPrimaryBouncer,
+            showForAlternateBouncer ->
+            showForPrimaryBouncer || showForAlternateBouncer
+        }
+
+    private fun shouldShowIndicatorForPrimaryBouncer(): Boolean {
+        val sfpsEnabled: Boolean =
+            context.resources.getBoolean(R.bool.config_show_sidefps_hint_on_bouncer)
+        val sfpsDetectionRunning = keyguardUpdateMonitor.isFingerprintDetectionRunning
+        val isUnlockingWithFpAllowed = keyguardUpdateMonitor.isUnlockingWithFingerprintAllowed
+        return primaryBouncerInteractor.isBouncerShowing() &&
+            sfpsEnabled &&
+            sfpsDetectionRunning &&
+            isUnlockingWithFpAllowed &&
+            !primaryBouncerInteractor.isAnimatingAway()
+    }
+
+    companion object {
+        private const val TAG = "DeviceEntrySideFpsOverlayInteractor"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
index 0b6b971..7fdcf2f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
@@ -48,7 +48,7 @@
     override fun start() {
         listenForDreamingToOccluded()
         listenForDreamingToGone()
-        listenForDreamingToDozing()
+        listenForDreamingToAodOrDozing()
         listenForTransitionToCamera(scope, keyguardInteractor)
     }
 
@@ -94,7 +94,7 @@
         }
     }
 
-    private fun listenForDreamingToDozing() {
+    private fun listenForDreamingToAodOrDozing() {
         scope.launch {
             combine(
                     keyguardInteractor.dozeTransitionModel,
@@ -102,11 +102,12 @@
                     ::Pair
                 )
                 .collect { (dozeTransitionModel, keyguardState) ->
-                    if (
-                        dozeTransitionModel.to == DozeStateModel.DOZE &&
-                            keyguardState == KeyguardState.DREAMING
-                    ) {
-                        startTransitionTo(KeyguardState.DOZING)
+                    if (keyguardState == KeyguardState.DREAMING) {
+                        if (dozeTransitionModel.to == DozeStateModel.DOZE) {
+                            startTransitionTo(KeyguardState.DOZING)
+                        } else if (dozeTransitionModel.to == DozeStateModel.DOZE_AOD) {
+                            startTransitionTo(KeyguardState.AOD)
+                        }
                     }
                 }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
index cbfd17ff..9fe5c3f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
@@ -214,7 +214,7 @@
     private fun listenForLockscreenToPrimaryBouncerDragging() {
         var transitionId: UUID? = null
         scope.launch("$TAG#listenForLockscreenToPrimaryBouncerDragging") {
-            shadeRepository.shadeModel
+            shadeRepository.legacyShadeExpansion
                 .sample(
                     combine(
                         transitionInteractor.startedKeyguardTransitionStep,
@@ -224,23 +224,23 @@
                     ),
                     ::toQuad
                 )
-                .collect { (shadeModel, keyguardState, statusBarState, isKeyguardUnlocked) ->
+                .collect { (shadeExpansion, keyguardState, statusBarState, isKeyguardUnlocked) ->
                     val id = transitionId
                     if (id != null) {
                         if (keyguardState.to == KeyguardState.PRIMARY_BOUNCER) {
                             // An existing `id` means a transition is started, and calls to
                             // `updateTransition` will control it until FINISHED or CANCELED
                             var nextState =
-                                if (shadeModel.expansionAmount == 0f) {
+                                if (shadeExpansion == 0f) {
                                     TransitionState.FINISHED
-                                } else if (shadeModel.expansionAmount == 1f) {
+                                } else if (shadeExpansion == 1f) {
                                     TransitionState.CANCELED
                                 } else {
                                     TransitionState.RUNNING
                                 }
                             transitionRepository.updateTransition(
                                 id,
-                                1f - shadeModel.expansionAmount,
+                                1f - shadeExpansion,
                                 nextState,
                             )
 
@@ -274,7 +274,7 @@
                         // integrated into KeyguardTransitionRepository
                         if (
                             keyguardState.to == KeyguardState.LOCKSCREEN &&
-                                shadeModel.isUserDragging &&
+                                shadeRepository.legacyShadeTracking.value &&
                                 !isKeyguardUnlocked &&
                                 statusBarState == KEYGUARD
                         ) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt
index 7dab84d..ba44e68 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt
@@ -21,11 +21,15 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.keyguard.data.repository.KeyguardBlueprintRepository
+import com.android.systemui.keyguard.shared.model.KeyguardBlueprint
 import com.android.systemui.keyguard.ui.view.layout.blueprints.DefaultKeyguardBlueprint
 import com.android.systemui.keyguard.ui.view.layout.blueprints.SplitShadeKeyguardBlueprint
 import com.android.systemui.statusbar.policy.SplitShadeStateController
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.merge
 import kotlinx.coroutines.flow.onStart
 import kotlinx.coroutines.launch
 
@@ -39,7 +43,18 @@
     private val splitShadeStateController: SplitShadeStateController,
 ) {
 
-    val blueprint = keyguardBlueprintRepository.blueprint
+    /**
+     * The current blueprint for the lockscreen.
+     *
+     * This flow can also emit the same blueprint value if refreshBlueprint is emitted.
+     */
+    val blueprint: Flow<KeyguardBlueprint> =
+        merge(
+            keyguardBlueprintRepository.blueprint,
+            keyguardBlueprintRepository.refreshBluePrint.map {
+                keyguardBlueprintRepository.blueprint.value
+            }
+        )
 
     init {
         applicationScope.launch {
@@ -91,4 +106,8 @@
     fun refreshBlueprint() {
         keyguardBlueprintRepository.refreshBlueprint()
     }
+
+    fun getCurrentBlueprint(): KeyguardBlueprint {
+        return keyguardBlueprintRepository.blueprint.value
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractor.kt
index 5ed70b5..046916a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractor.kt
@@ -78,6 +78,9 @@
  * flows.
  */
 interface FaceAuthenticationListener {
+    /** Receive face isAuthenticated updates */
+    fun onAuthenticatedChanged(isAuthenticated: Boolean)
+
     /** Receive face authentication status updates */
     fun onAuthenticationStatusChanged(status: FaceAuthenticationStatus)
 
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 702386d..21651ba2 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
@@ -174,6 +174,9 @@
     /** Last point that [KeyguardRootView] view was tapped */
     val lastRootViewTapPosition: Flow<Point?> = repository.lastRootViewTapPosition.asStateFlow()
 
+    /** Is the ambient indication area visible? */
+    val ambientIndicationVisible: Flow<Boolean> = repository.ambientIndicationVisible.asStateFlow()
+
     /** Whether the primary bouncer is showing or not. */
     val primaryBouncerShowing: Flow<Boolean> = bouncerRepository.primaryBouncerShow
 
@@ -224,8 +227,8 @@
         configurationInteractor
             .dimensionPixelSize(R.dimen.keyguard_translate_distance_on_swipe_up)
             .flatMapLatest { translationDistance ->
-                shadeRepository.shadeModel.map {
-                    if (it.expansionAmount == 0f) {
+                shadeRepository.legacyShadeExpansion.map {
+                    if (it == 0f) {
                         // Reset the translation value
                         0f
                     } else {
@@ -233,7 +236,7 @@
                         MathUtils.lerp(
                             translationDistance,
                             0,
-                            Interpolators.FAST_OUT_LINEAR_IN.getInterpolation(it.expansionAmount)
+                            Interpolators.FAST_OUT_LINEAR_IN.getInterpolation(it)
                         )
                     }
                 }
@@ -311,6 +314,14 @@
         repository.lastRootViewTapPosition.value = point
     }
 
+    fun setAmbientIndicationVisible(isVisible: Boolean) {
+        repository.ambientIndicationVisible.value = isVisible
+    }
+
+    fun keyguardDoneAnimationsFinished() {
+        repository.keyguardDoneAnimationsFinished()
+    }
+
     companion object {
         private const val TAG = "KeyguardInteractor"
     }
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 448411e..7882a97 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
@@ -46,6 +46,7 @@
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.res.R
 import com.android.systemui.settings.UserTracker
+import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.shared.customization.data.content.CustomizationProviderContract as Contract
 import com.android.systemui.statusbar.phone.SystemUIDialog
 import com.android.systemui.statusbar.policy.KeyguardStateController
@@ -66,6 +67,7 @@
 @Inject
 constructor(
     private val keyguardInteractor: KeyguardInteractor,
+    private val shadeInteractor: ShadeInteractor,
     private val lockPatternUtils: LockPatternUtils,
     private val keyguardStateController: KeyguardStateController,
     private val userTracker: UserTracker,
@@ -100,9 +102,10 @@
             quickAffordanceAlwaysVisible(position),
             keyguardInteractor.isDozing,
             keyguardInteractor.isKeyguardShowing,
+            shadeInteractor.anyExpansion,
             biometricSettingsRepository.isCurrentUserInLockdown,
-        ) { affordance, isDozing, isKeyguardShowing, isUserInLockdown ->
-            if (!isDozing && isKeyguardShowing && !isUserInLockdown) {
+        ) { affordance, isDozing, isKeyguardShowing, qsExpansion, isUserInLockdown ->
+            if (!isDozing && isKeyguardShowing && (qsExpansion < 1.0f) && !isUserInLockdown) {
                 affordance
             } else {
                 KeyguardQuickAffordanceModel.Hidden
@@ -117,10 +120,14 @@
      * This is useful for experiences like the lock screen preview mode, where the affordances must
      * always be visible.
      */
-    fun quickAffordanceAlwaysVisible(
+    suspend fun quickAffordanceAlwaysVisible(
         position: KeyguardQuickAffordancePosition,
     ): Flow<KeyguardQuickAffordanceModel> {
-        return quickAffordanceInternal(position)
+        return if (isFeatureDisabledByDevicePolicy()) {
+            flowOf(KeyguardQuickAffordanceModel.Hidden)
+        } else {
+            quickAffordanceInternal(position)
+        }
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt
index 532df4a..e3f4739 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt
@@ -16,8 +16,10 @@
 
 package com.android.systemui.keyguard.domain.interactor
 
+import android.app.trust.TrustManager
 import android.content.Context
 import android.hardware.biometrics.BiometricFaceConstants
+import android.hardware.biometrics.BiometricSourceType
 import com.android.keyguard.FaceAuthUiEvent
 import com.android.keyguard.FaceWakeUpTriggersConfig
 import com.android.keyguard.KeyguardUpdateMonitor
@@ -29,7 +31,6 @@
 import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
 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.keyguard.data.repository.BiometricSettingsRepository
 import com.android.systemui.keyguard.data.repository.DeviceEntryFaceAuthRepository
@@ -70,7 +71,6 @@
     private val context: Context,
     @Application private val applicationScope: CoroutineScope,
     @Main private val mainDispatcher: CoroutineDispatcher,
-    @Background private val backgroundDispatcher: CoroutineDispatcher,
     private val repository: DeviceEntryFaceAuthRepository,
     private val primaryBouncerInteractor: Lazy<PrimaryBouncerInteractor>,
     private val alternateBouncerInteractor: AlternateBouncerInteractor,
@@ -83,6 +83,7 @@
     private val faceWakeUpTriggersConfig: FaceWakeUpTriggersConfig,
     private val powerInteractor: PowerInteractor,
     private val biometricSettingsRepository: BiometricSettingsRepository,
+    private val trustManager: TrustManager,
 ) : CoreStartable, KeyguardFaceAuthInteractor {
 
     private val listeners: MutableList<FaceAuthenticationListener> = mutableListOf()
@@ -106,7 +107,6 @@
                     fallbackToDetect = false
                 )
             }
-            .flowOn(backgroundDispatcher)
             .launchIn(applicationScope)
 
         alternateBouncerInteractor.isVisible
@@ -118,7 +118,6 @@
                     fallbackToDetect = false
                 )
             }
-            .flowOn(backgroundDispatcher)
             .launchIn(applicationScope)
 
         merge(
@@ -147,7 +146,6 @@
                     fallbackToDetect = true
                 )
             }
-            .flowOn(backgroundDispatcher)
             .launchIn(applicationScope)
 
         deviceEntryFingerprintAuthRepository.isLockedOut
@@ -160,7 +158,6 @@
                     }
                 }
             }
-            .flowOn(backgroundDispatcher)
             .launchIn(applicationScope)
 
         // User switching should stop face auth and then when it is complete we should trigger face
@@ -184,7 +181,6 @@
                     )
                 }
             }
-            .flowOn(backgroundDispatcher)
             .launchIn(applicationScope)
     }
 
@@ -291,6 +287,19 @@
             .onEach { running -> listeners.forEach { it.onRunningStateChanged(running) } }
             .flowOn(mainDispatcher)
             .launchIn(applicationScope)
+        repository.isAuthenticated
+            .sample(userRepository.selectedUserInfo, ::Pair)
+            .onEach { (isAuthenticated, userInfo) ->
+                if (!isAuthenticated) {
+                    faceAuthenticationLogger.clearFaceRecognized()
+                    trustManager.clearAllBiometricRecognized(BiometricSourceType.FACE, userInfo.id)
+                }
+            }
+            .onEach { (isAuthenticated, _) ->
+                listeners.forEach { it.onAuthenticatedChanged(isAuthenticated) }
+            }
+            .flowOn(mainDispatcher)
+            .launchIn(applicationScope)
 
         biometricSettingsRepository.isFaceAuthEnrolledAndEnabled
             .onEach { enrolledAndEnabled ->
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/BiometricUnlockModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/BiometricUnlockModel.kt
index 8fe6309f..2ae5ce1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/BiometricUnlockModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/BiometricUnlockModel.kt
@@ -51,9 +51,21 @@
     companion object {
         private val wakeAndUnlockModes =
             setOf(WAKE_AND_UNLOCK, WAKE_AND_UNLOCK_FROM_DREAM, WAKE_AND_UNLOCK_PULSING)
+        private val dismissesKeyguardModes =
+            setOf(
+                WAKE_AND_UNLOCK,
+                WAKE_AND_UNLOCK_PULSING,
+                UNLOCK_COLLAPSING,
+                WAKE_AND_UNLOCK_FROM_DREAM,
+                DISMISS_BOUNCER
+            )
 
         fun isWakeAndUnlock(model: BiometricUnlockModel): Boolean {
             return wakeAndUnlockModes.contains(model)
         }
+
+        fun dismissesKeyguard(model: BiometricUnlockModel): Boolean {
+            return dismissesKeyguardModes.contains(model)
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/FingerprintAuthenticationModels.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/FingerprintAuthenticationModels.kt
index 3c143fe..cc385a8 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/FingerprintAuthenticationModels.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/FingerprintAuthenticationModels.kt
@@ -49,7 +49,7 @@
 }
 
 /** Fingerprint authentication failed message. */
-object FailFingerprintAuthenticationStatus : FingerprintAuthenticationStatus()
+data object FailFingerprintAuthenticationStatus : FingerprintAuthenticationStatus()
 
 /** Fingerprint authentication error message */
 data class ErrorFingerprintAuthenticationStatus(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt
index 4b4a19e..dcf4284 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt
@@ -19,6 +19,7 @@
 
 import android.annotation.SuppressLint
 import android.content.res.ColorStateList
+import android.view.HapticFeedbackConstants
 import android.view.View
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.repeatOnLifecycle
@@ -30,6 +31,7 @@
 import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryIconViewModel
 import com.android.systemui.lifecycle.repeatWhenAttached
 import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.statusbar.VibratorHelper
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.launch
 
@@ -51,6 +53,7 @@
         fgViewModel: DeviceEntryForegroundViewModel,
         bgViewModel: DeviceEntryBackgroundViewModel,
         falsingManager: FalsingManager,
+        vibratorHelper: VibratorHelper,
     ) {
         DeviceEntryUdfpsRefactor.isUnexpectedlyInLegacyMode()
         val longPressHandlingView = view.longPressHandlingView
@@ -62,6 +65,10 @@
                     if (falsingManager.isFalseLongTap(FalsingManager.LOW_PENALTY)) {
                         return
                     }
+                    vibratorHelper.performHapticFeedback(
+                        view,
+                        HapticFeedbackConstants.CONFIRM,
+                    )
                     viewModel.onLongPress()
                 }
             }
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 e603ead..01a1ca3 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
@@ -68,7 +68,6 @@
 import kotlinx.coroutines.DisposableHandle
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.stateIn
 import kotlinx.coroutines.launch
 
@@ -253,27 +252,21 @@
 
                     if (deviceEntryHapticsInteractor != null && vibratorHelper != null) {
                         launch {
-                            deviceEntryHapticsInteractor.playSuccessHaptic
-                                .filter { it }
-                                .collect {
-                                    vibratorHelper.performHapticFeedback(
-                                        view,
-                                        HapticFeedbackConstants.CONFIRM,
-                                    )
-                                    deviceEntryHapticsInteractor.handleSuccessHaptic()
-                                }
+                            deviceEntryHapticsInteractor.playSuccessHaptic.collect {
+                                vibratorHelper.performHapticFeedback(
+                                    view,
+                                    HapticFeedbackConstants.CONFIRM,
+                                )
+                            }
                         }
 
                         launch {
-                            deviceEntryHapticsInteractor.playErrorHaptic
-                                .filter { it }
-                                .collect {
-                                    vibratorHelper.performHapticFeedback(
-                                        view,
-                                        HapticFeedbackConstants.REJECT,
-                                    )
-                                    deviceEntryHapticsInteractor.handleErrorHaptic()
-                                }
+                            deviceEntryHapticsInteractor.playErrorHaptic.collect {
+                                vibratorHelper.performHapticFeedback(
+                                    view,
+                                    HapticFeedbackConstants.REJECT,
+                                )
+                            }
                         }
                     }
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/SideFpsProgressBarViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/SideFpsProgressBarViewBinder.kt
index 560e4ad..9a6dca3 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/SideFpsProgressBarViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/SideFpsProgressBarViewBinder.kt
@@ -21,6 +21,7 @@
 import com.android.systemui.CoreStartable
 import com.android.systemui.Flags
 import com.android.systemui.biometrics.SideFpsController
+import com.android.systemui.biometrics.shared.SideFpsControllerRefactor
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.keyguard.ui.view.SideFpsProgressBar
@@ -46,6 +47,7 @@
     private val viewModel: SideFpsProgressBarViewModel,
     private val view: SideFpsProgressBar,
     @Application private val applicationScope: CoroutineScope,
+    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
     private val sfpsController: dagger.Lazy<SideFpsController>,
     private val logger: SideFpsLogger,
     private val commandRegistry: CommandRegistry,
@@ -109,12 +111,14 @@
         view.updateView(visible, location, length, thickness, rotation)
         // We have to hide the SFPS indicator as the progress bar will
         // be shown at the same location
-        if (visible) {
-            logger.hidingSfpsIndicator()
-            sfpsController.get().hideIndicator()
-        } else if (fpDetectRunning) {
-            logger.showingSfpsIndicator()
-            sfpsController.get().showIndicator()
+        if (!SideFpsControllerRefactor.isEnabled) {
+            if (visible) {
+                logger.hidingSfpsIndicator()
+                sfpsController.get().hideIndicator()
+            } else if (fpDetectRunning) {
+                logger.showingSfpsIndicator()
+                sfpsController.get().showIndicator()
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardRemotePreviewManager.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardRemotePreviewManager.kt
index acfd3b0..24240df 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardRemotePreviewManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardRemotePreviewManager.kt
@@ -30,6 +30,7 @@
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants
+import com.android.systemui.util.kotlin.logD
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
@@ -58,11 +59,14 @@
 
             observer =
                 PreviewLifecycleObserver(
-                    renderer,
                     applicationScope,
                     mainDispatcher,
+                    renderer,
                     ::destroyObserver,
                 )
+
+            logD(TAG) { "Created observer $observer" }
+
             // Destroy any previous renderer associated with this token.
             activePreviews[renderer.id]?.let { destroyObserver(it) }
             activePreviews[renderer.id] = observer
@@ -80,6 +84,8 @@
                         observer,
                     )
                 )
+            // NOTE: The process on the other side can retain messenger indefinitely.
+            // (e.g. GC might not trigger and cleanup the reference)
             val msg = Message.obtain()
             msg.replyTo = messenger
             result.putParcelable(KEY_PREVIEW_CALLBACK, msg)
@@ -99,57 +105,84 @@
         }
     }
 
-    private class PreviewLifecycleObserver(
-        private val renderer: KeyguardPreviewRenderer,
-        private val scope: CoroutineScope,
-        private val mainDispatcher: CoroutineDispatcher,
-        private val requestDestruction: (PreviewLifecycleObserver) -> Unit,
-    ) : Handler.Callback, IBinder.DeathRecipient {
+    companion object {
+        internal const val TAG = "KeyguardRemotePreviewManager"
+        @VisibleForTesting const val KEY_PREVIEW_SURFACE_PACKAGE = "surface_package"
+        @VisibleForTesting const val KEY_PREVIEW_CALLBACK = "callback"
+    }
+}
 
-        private var isDestroyedOrDestroying = false
+/**
+ * Handles messages from the other process and handles cleanup.
+ *
+ * NOTE: The other process might hold on to reference of this class indefinitely. It's entirely
+ * possible that GC won't trigger and we'll leak this for all times even if [onDestroy] was called.
+ * This helps make sure no non-Singleton objects are retained beyond destruction to prevent leaks.
+ */
+@VisibleForTesting(VisibleForTesting.PRIVATE)
+class PreviewLifecycleObserver(
+    private val scope: CoroutineScope,
+    private val mainDispatcher: CoroutineDispatcher,
+    renderer: KeyguardPreviewRenderer,
+    onDestroy: (PreviewLifecycleObserver) -> Unit,
+) : Handler.Callback, IBinder.DeathRecipient {
 
-        override fun handleMessage(message: Message): Boolean {
-            if (isDestroyedOrDestroying) {
-                return true
-            }
+    private var isDestroyedOrDestroying = false
+    // These two are null after destruction
+    @VisibleForTesting var renderer: KeyguardPreviewRenderer?
+    @VisibleForTesting var onDestroy: ((PreviewLifecycleObserver) -> Unit)?
 
-            when (message.what) {
-                KeyguardPreviewConstants.MESSAGE_ID_SLOT_SELECTED -> {
-                    message.data.getString(KeyguardPreviewConstants.KEY_SLOT_ID)?.let { slotId ->
-                        renderer.onSlotSelected(slotId = slotId)
-                    }
-                }
-                KeyguardPreviewConstants.MESSAGE_ID_HIDE_SMART_SPACE -> {
-                    renderer.hideSmartspace(
-                        message.data.getBoolean(KeyguardPreviewConstants.KEY_HIDE_SMART_SPACE)
-                    )
-                }
-                else -> requestDestruction(this)
-            }
+    init {
+        this.renderer = renderer
+        this.onDestroy = onDestroy
+    }
 
+    override fun handleMessage(message: Message): Boolean {
+        if (isDestroyedOrDestroying) {
             return true
         }
 
-        override fun binderDied() {
-            requestDestruction(this)
+        when (message.what) {
+            KeyguardPreviewConstants.MESSAGE_ID_SLOT_SELECTED -> {
+                message.data.getString(KeyguardPreviewConstants.KEY_SLOT_ID)?.let { slotId ->
+                    checkNotNull(renderer).onSlotSelected(slotId = slotId)
+                }
+            }
+            KeyguardPreviewConstants.MESSAGE_ID_HIDE_SMART_SPACE -> {
+                checkNotNull(renderer)
+                    .hideSmartspace(
+                        message.data.getBoolean(KeyguardPreviewConstants.KEY_HIDE_SMART_SPACE)
+                    )
+            }
+            else -> checkNotNull(onDestroy).invoke(this)
         }
 
-        fun onDestroy(): Pair<IBinder?, Int>? {
-            if (isDestroyedOrDestroying) {
-                return null
-            }
+        return true
+    }
 
-            isDestroyedOrDestroying = true
-            val hostToken = renderer.hostToken
+    override fun binderDied() {
+        onDestroy?.invoke(this)
+    }
+
+    fun onDestroy(): Pair<IBinder?, Int>? {
+        if (isDestroyedOrDestroying) {
+            return null
+        }
+
+        logD(TAG) { "Destroying $this" }
+
+        isDestroyedOrDestroying = true
+        return renderer?.let { rendererToDestroy ->
+            this.renderer = null
+            this.onDestroy = null
+            val hostToken = rendererToDestroy.hostToken
             hostToken?.unlinkToDeath(this, 0)
-            scope.launch(mainDispatcher) { renderer.destroy() }
-            return renderer.id
+            scope.launch(mainDispatcher) { rendererToDestroy.destroy() }
+            rendererToDestroy.id
         }
     }
 
     companion object {
         private const val TAG = "KeyguardRemotePreviewManager"
-        @VisibleForTesting const val KEY_PREVIEW_SURFACE_PACKAGE = "surface_package"
-        @VisibleForTesting const val KEY_PREVIEW_CALLBACK = "callback"
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/transitions/BaseBlueprintTransition.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/transitions/BaseBlueprintTransition.kt
index 42b1c10..d0626d5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/transitions/BaseBlueprintTransition.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/transitions/BaseBlueprintTransition.kt
@@ -24,6 +24,7 @@
 import android.transition.Visibility
 import android.view.View
 import android.view.ViewGroup
+import androidx.constraintlayout.helper.widget.Layer
 
 class BaseBlueprintTransition : TransitionSet() {
     init {
@@ -31,6 +32,7 @@
         addTransition(AlphaOutVisibility())
             .addTransition(ChangeBounds())
             .addTransition(AlphaInVisibility())
+        excludeTarget(Layer::class.java, /* exclude= */ true)
     }
     class AlphaOutVisibility : Visibility() {
         override fun onDisappear(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodNotificationIconsSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodNotificationIconsSection.kt
index 96efb23..39a0547 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodNotificationIconsSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodNotificationIconsSection.kt
@@ -40,7 +40,7 @@
 import com.android.systemui.statusbar.notification.shared.NotificationIconContainerRefactor
 import com.android.systemui.statusbar.phone.NotificationIconAreaController
 import com.android.systemui.statusbar.phone.NotificationIconContainer
-import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.statusbar.ui.SystemBarUtilsState
 import javax.inject.Inject
 import kotlinx.coroutines.DisposableHandle
 
@@ -49,13 +49,13 @@
 constructor(
     private val context: Context,
     private val configurationState: ConfigurationState,
-    private val configurationController: ConfigurationController,
     private val featureFlags: FeatureFlagsClassic,
     private val iconBindingFailureTracker: StatusBarIconViewBindingFailureTracker,
     private val nicAodViewModel: NotificationIconContainerAlwaysOnDisplayViewModel,
     private val nicAodIconViewStore: AlwaysOnDisplayNotificationIconViewStore,
     private val notificationIconAreaController: NotificationIconAreaController,
     private val smartspaceViewModel: KeyguardSmartspaceViewModel,
+    private val systemBarUtilsState: SystemBarUtilsState,
 ) : KeyguardSection() {
 
     private var nicBindingDisposable: DisposableHandle? = null
@@ -89,11 +89,11 @@
         if (NotificationIconContainerRefactor.isEnabled) {
             nicBindingDisposable?.dispose()
             nicBindingDisposable =
-                NotificationIconContainerViewBinder.bind(
+                NotificationIconContainerViewBinder.bindWhileAttached(
                     nic,
                     nicAodViewModel,
                     configurationState,
-                    configurationController,
+                    systemBarUtilsState,
                     iconBindingFailureTracker,
                     nicAodIconViewStore,
                 )
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt
index 77ab9f4..a693ec9 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt
@@ -49,6 +49,7 @@
 import com.android.systemui.res.R
 import com.android.systemui.shade.NotificationPanelView
 import com.android.systemui.statusbar.NotificationShadeWindowController
+import com.android.systemui.statusbar.VibratorHelper
 import com.android.systemui.statusbar.gesture.TapGestureDetector
 import dagger.Lazy
 import javax.inject.Inject
@@ -76,6 +77,7 @@
     @Application private val scope: CoroutineScope,
     private val swipeUpAnywhereGestureHandler: Lazy<SwipeUpAnywhereGestureHandler>,
     private val tapGestureDetector: Lazy<TapGestureDetector>,
+    private val vibratorHelper: Lazy<VibratorHelper>,
 ) : KeyguardSection() {
     private val deviceEntryIconViewId = R.id.device_entry_icon_view
     private val alternateBouncerViewId = R.id.alternate_bouncer
@@ -114,6 +116,7 @@
                     deviceEntryForegroundViewModel.get(),
                     deviceEntryBackgroundViewModel.get(),
                     falsingManager.get(),
+                    vibratorHelper.get(),
                 )
             }
             constraintLayout.findViewById<FrameLayout?>(alternateBouncerViewId)?.let {
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 a64a422..e7b6e44 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
@@ -26,7 +26,6 @@
 import androidx.constraintlayout.widget.ConstraintSet.TOP
 import com.android.systemui.Flags.migrateClocksToBlueprint
 import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor
 import com.android.systemui.keyguard.shared.KeyguardShadeMigrationNssl
 import com.android.systemui.keyguard.ui.viewmodel.KeyguardSmartspaceViewModel
 import com.android.systemui.res.R
@@ -92,13 +91,7 @@
             connect(R.id.nssl_placeholder, START, PARENT_ID, START)
             connect(R.id.nssl_placeholder, END, PARENT_ID, END)
 
-            val lockId =
-                if (DeviceEntryUdfpsRefactor.isEnabled) {
-                    R.id.device_entry_icon_view
-                } else {
-                    R.id.lock_icon_view
-                }
-            connect(R.id.nssl_placeholder, BOTTOM, lockId, TOP)
+            addNotificationPlaceholderBarrier(this)
         }
     }
 }
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 a25471c..400d0dc 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
@@ -20,7 +20,12 @@
 import android.content.Context
 import android.view.View
 import android.view.ViewGroup
+import androidx.constraintlayout.widget.Barrier
 import androidx.constraintlayout.widget.ConstraintLayout
+import androidx.constraintlayout.widget.ConstraintSet
+import androidx.constraintlayout.widget.ConstraintSet.BOTTOM
+import androidx.constraintlayout.widget.ConstraintSet.TOP
+import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor
 import com.android.systemui.keyguard.shared.KeyguardShadeMigrationNssl
 import com.android.systemui.keyguard.shared.model.KeyguardSection
 import com.android.systemui.res.R
@@ -54,6 +59,29 @@
     private val placeHolderId = R.id.nssl_placeholder
     private var disposableHandle: DisposableHandle? = null
 
+    /**
+     * Align the notification placeholder bottom to the top of either the lock icon or the ambient
+     * indication area, whichever is higher.
+     */
+    protected fun addNotificationPlaceholderBarrier(constraintSet: ConstraintSet) {
+        val lockId =
+            if (DeviceEntryUdfpsRefactor.isEnabled) {
+                R.id.device_entry_icon_view
+            } else {
+                R.id.lock_icon_view
+            }
+
+        constraintSet.apply {
+            createBarrier(
+                R.id.nssl_placeholder_barrier_bottom,
+                Barrier.TOP,
+                0,
+                *intArrayOf(lockId, R.id.ambient_indication_container)
+            )
+            connect(R.id.nssl_placeholder, BOTTOM, R.id.nssl_placeholder_barrier_bottom, TOP)
+        }
+    }
+
     override fun addViews(constraintLayout: ConstraintLayout) {
         if (!KeyguardShadeMigrationNssl.isEnabled) {
             return
@@ -85,9 +113,9 @@
             )
         if (sceneContainerFlags.flexiNotifsEnabled()) {
             NotificationStackAppearanceViewBinder.bind(
+                context,
                 sharedNotificationContainer,
                 notificationStackAppearanceViewModel,
-                sceneContainerFlags,
                 ambientState,
                 controller,
             )
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 921fb3b..b0b5c81 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
@@ -19,14 +19,12 @@
 
 import android.content.Context
 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 com.android.systemui.Flags.migrateClocksToBlueprint
 import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor
 import com.android.systemui.keyguard.shared.KeyguardShadeMigrationNssl
 import com.android.systemui.keyguard.ui.viewmodel.KeyguardSmartspaceViewModel
 import com.android.systemui.res.R
@@ -87,18 +85,17 @@
                 )
                 setGoneMargin(R.id.nssl_placeholder, TOP, bottomMargin)
             } else {
-                connect(R.id.nssl_placeholder, TOP, R.id.keyguard_status_view, TOP, bottomMargin)
+                val splitShadeTopMargin =
+                    context.resources.getDimensionPixelSize(
+                        R.dimen.large_screen_shade_header_height
+                    )
+                connect(R.id.nssl_placeholder, TOP, PARENT_ID, TOP, splitShadeTopMargin)
             }
+
             connect(R.id.nssl_placeholder, START, PARENT_ID, START)
             connect(R.id.nssl_placeholder, END, PARENT_ID, END)
 
-            val lockId =
-                if (DeviceEntryUdfpsRefactor.isEnabled) {
-                    R.id.device_entry_icon_view
-                } else {
-                    R.id.lock_icon_view
-                }
-            connect(R.id.nssl_placeholder, BOTTOM, lockId, TOP)
+            addNotificationPlaceholderBarrier(this)
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt
index bd6aae8..f95713b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt
@@ -19,7 +19,6 @@
 import android.animation.FloatEvaluator
 import android.animation.IntEvaluator
 import com.android.keyguard.KeyguardViewController
-import com.android.systemui.deviceentry.domain.interactor.DeviceEntryHapticsInteractor
 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor
 import com.android.systemui.keyguard.domain.interactor.BurnInInteractor
@@ -56,7 +55,6 @@
     val shadeDependentFlows: ShadeDependentFlows,
     private val sceneContainerFlags: SceneContainerFlags,
     private val keyguardViewController: Lazy<KeyguardViewController>,
-    private val deviceEntryHapticsInteractor: DeviceEntryHapticsInteractor,
     private val deviceEntryInteractor: DeviceEntryInteractor,
 ) {
     private val intEvaluator = IntEvaluator()
@@ -182,8 +180,6 @@
         }
 
     fun onLongPress() {
-        deviceEntryHapticsInteractor.vibrateSuccess()
-
         // TODO (b/309804148): play auth ripple via an interactor
 
         if (sceneContainerFlags.isEnabled()) {
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 4588e02..26dace0 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
@@ -111,10 +111,21 @@
 
     /** An observable for the alpha level for the entire keyguard root view. */
     val alpha: Flow<Float> =
-        merge(
-            keyguardInteractor.keyguardAlpha.distinctUntilChanged(),
-            occludedToLockscreenTransitionViewModel.lockscreenAlpha,
-        )
+        combine(
+                keyguardTransitionInteractor.transitionValue(GONE).onStart { emit(0f) },
+                merge(
+                    keyguardInteractor.keyguardAlpha,
+                    occludedToLockscreenTransitionViewModel.lockscreenAlpha,
+                )
+            ) { transitionToGone, alpha ->
+                if (transitionToGone == 1f) {
+                    // Ensures content is not visible when in GONE state
+                    0f
+                } else {
+                    alpha
+                }
+            }
+            .distinctUntilChanged()
 
     private fun burnIn(): Flow<BurnInModel> {
         val dozingAmount: Flow<Float> =
@@ -169,7 +180,9 @@
                     goneToAodTransitionViewModel
                         .enterFromTopTranslationY(enterFromTopAmount)
                         .onStart { emit(0f) },
-                    occludedToLockscreenTransitionViewModel.lockscreenTranslationY,
+                    occludedToLockscreenTransitionViewModel.lockscreenTranslationY.onStart {
+                        emit(0f)
+                    },
                 ) {
                     keyguardTransitionY,
                     burnInTranslationY,
@@ -182,6 +195,7 @@
                         occludedToLockscreenTransitionTranslationY
                 }
             }
+            .distinctUntilChanged()
 
     val translationX: Flow<Float> = burnIn().map { it.translationX.toFloat() }
 
@@ -229,7 +243,9 @@
             .distinctUntilChanged()
 
     fun onNotificationContainerBoundsChanged(top: Float, bottom: Float) {
-        keyguardInteractor.setNotificationContainerBounds(NotificationContainerBounds(top, bottom))
+        keyguardInteractor.setNotificationContainerBounds(
+            NotificationContainerBounds(top = top, bottom = bottom)
+        )
     }
 
     /** Is there an expanded pulse, are we animating in response? */
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/SideFpsProgressBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/SideFpsProgressBarViewModel.kt
index 2d0712c..1dbf1f1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/SideFpsProgressBarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/SideFpsProgressBarViewModel.kt
@@ -19,6 +19,7 @@
 import android.animation.ValueAnimator
 import android.content.Context
 import android.graphics.Point
+import androidx.annotation.VisibleForTesting
 import androidx.core.animation.doOnEnd
 import com.android.systemui.Flags
 import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor
@@ -213,4 +214,9 @@
             }
         }
     }
+
+    @VisibleForTesting
+    fun setVisible(isVisible: Boolean) {
+        _visible.value = isVisible
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt b/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt
index 8c5690b..3c2facb 100644
--- a/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt
@@ -132,6 +132,10 @@
         logBuffer.log(TAG, DEBUG, "Face authentication failed")
     }
 
+    fun clearFaceRecognized() {
+        logBuffer.log(TAG, DEBUG, "Clear face recognized")
+    }
+
     fun authenticationError(
         errorCode: Int,
         errString: CharSequence?,
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
index dc55179f..d8bb3e6 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
@@ -188,7 +188,7 @@
             LogBufferFactory factory,
             QSPipelineFlagsRepository flags
     ) {
-        if (flags.getPipelineTilesEnabled()) {
+        if (flags.getTilesEnabled()) {
             // we use
             return factory.create("QSLog", 450 /* maxSize */, false /* systrace */);
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt
index 14d4b68..c87fd14 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt
@@ -119,7 +119,7 @@
         ::AnimatingColorTransition
     )
 
-    val bgColor = context.getColor(com.google.android.material.R.color.material_dynamic_secondary95)
+    val bgColor = context.getColor(com.google.android.material.R.color.material_dynamic_neutral20)
     val surfaceColor =
         animatingColorTransitionFactory(bgColor, ::surfaceFromScheme) { surfaceColor ->
             val colorList = ColorStateList.valueOf(surfaceColor)
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
index 9cdf857..992eeca 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
@@ -40,6 +40,7 @@
 import com.android.keyguard.KeyguardUpdateMonitorCallback
 import com.android.systemui.Dumpable
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
@@ -76,6 +77,7 @@
 import java.io.PrintWriter
 import java.util.Locale
 import java.util.TreeMap
+import java.util.concurrent.Executor
 import javax.inject.Inject
 import javax.inject.Provider
 import kotlinx.coroutines.CoroutineScope
@@ -102,6 +104,7 @@
     private val activityStarter: ActivityStarter,
     private val systemClock: SystemClock,
     @Main executor: DelayableExecutor,
+    @Background private val bgExecutor: Executor,
     private val mediaManager: MediaDataManager,
     configurationController: ConfigurationController,
     falsingManager: FalsingManager,
@@ -1030,7 +1033,7 @@
             desiredHostState?.let {
                 if (this.desiredLocation != desiredLocation) {
                     // Only log an event when location changes
-                    logger.logCarouselPosition(desiredLocation)
+                    bgExecutor.execute { logger.logCarouselPosition(desiredLocation) }
                 }
 
                 // This is a hosting view, let's remeasure our players
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
index 8d1ff98a..62c7343 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
@@ -31,7 +31,6 @@
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SWITCHER_SHOWING;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IMMERSIVE_MODE;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
@@ -322,7 +321,6 @@
                 .setFlag(SYSUI_STATE_NAV_BAR_HIDDEN, !isWindowVisible())
                 .setFlag(SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY,
                         allowSystemGestureIgnoringBarVisibility())
-                .setFlag(SYSUI_STATE_IMMERSIVE_MODE, isImmersiveMode())
                 .commitUpdate(mDisplayId);
     }
 
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 9846f4b..e660b97 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -69,7 +69,6 @@
 
 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
 import com.android.internal.policy.GestureNavigationSettingsObserver;
-import com.android.systemui.res.R;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.flags.FeatureFlags;
@@ -81,6 +80,7 @@
 import com.android.systemui.plugins.PluginListener;
 import com.android.systemui.plugins.PluginManager;
 import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.res.R;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.InputChannelCompat;
@@ -1113,6 +1113,7 @@
                             // Capture inputs
                             mInputMonitor.pilferPointers();
                             if (mBackAnimation != null) {
+                                mBackAnimation.onPilferPointers();
                                 // Notify FalsingManager that an intentional gesture has occurred.
                                 mFalsingManager.isFalseTouch(BACK_GESTURE);
                             }
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
index 270bfbe..0e7e69b 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
@@ -263,7 +263,11 @@
      * If the shortcut entry `android:enabled` is set to `true`, the shortcut will be visible in the
      * Widget Picker to all users.
      */
+    // TODO(b/316332684)
+    @Suppress("UNREACHABLE_CODE")
     fun setNoteTaskShortcutEnabled(value: Boolean, user: UserHandle) {
+        return // shortcut should not be enabled until additional features are implemented.
+
         if (!userManager.isUserUnlocked(user)) {
             debugLog { "setNoteTaskShortcutEnabled call but user locked: user=$user" }
             return
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 6d55d05..de490a5 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfig.kt
@@ -27,7 +27,6 @@
 import android.util.Log
 import com.android.keyguard.KeyguardUpdateMonitor
 import com.android.keyguard.KeyguardUpdateMonitorCallback
-import com.android.systemui.res.R
 import com.android.systemui.animation.Expandable
 import com.android.systemui.common.shared.model.ContentDescription
 import com.android.systemui.common.shared.model.Icon
@@ -43,6 +42,7 @@
 import com.android.systemui.notetask.NoteTaskEnabledKey
 import com.android.systemui.notetask.NoteTaskEntryPoint.QUICK_AFFORDANCE
 import com.android.systemui.notetask.NoteTaskInfoResolver
+import com.android.systemui.res.R
 import com.android.systemui.stylus.StylusManager
 import dagger.Lazy
 import java.util.concurrent.Executor
@@ -100,7 +100,8 @@
                     isEnabled &&
                         isUserUnlocked &&
                         isDefaultNotesAppSet &&
-                        (isConfigSelected || isStylusEverUsed)
+                        isConfigSelected &&
+                        isStylusEverUsed
                 ) {
                     val contentDescription = ContentDescription.Resource(pickerNameResourceId)
                     val icon = Icon.Resource(pickerIconResourceId, contentDescription)
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogControllerV2.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogControllerV2.kt
index fdc70a8..76ef8a2 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogControllerV2.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogControllerV2.kt
@@ -278,7 +278,12 @@
                     d.setShowForAllUsers(true)
                     d.addOnDismissListener(onDialogDismissed)
                     if (view != null) {
-                        dialogLaunchAnimator.showFromView(d, view)
+                        val controller = getPrivacyDialogController(view)
+                        if (controller == null) {
+                            d.show()
+                        } else {
+                            dialogLaunchAnimator.show(d, controller)
+                        }
                     } else {
                         d.show()
                     }
@@ -291,6 +296,13 @@
         }
     }
 
+    private fun getPrivacyDialogController(source: View): DialogLaunchAnimator.Controller? {
+        val delegate = DialogLaunchAnimator.Controller.fromView(source) ?: return null
+        return object : DialogLaunchAnimator.Controller by delegate {
+            override fun shouldAnimateExit() = false
+        }
+    }
+
     /** Dismisses the dialog */
     fun dismissDialog() {
         dialog?.dismiss()
diff --git a/packages/SystemUI/src/com/android/systemui/qs/OWNERS b/packages/SystemUI/src/com/android/systemui/qs/OWNERS
new file mode 100644
index 0000000..45a4b50
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/OWNERS
@@ -0,0 +1,10 @@
+set noparent
+
+# Bug component: 78010
+
+apotapov@google.com
+asc@google.com
+bhnm@google.com
+kozynski@google.com
+ostonge@google.com
+pixel@google.com
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
index 6c930b1..3e50dd3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
@@ -43,6 +43,9 @@
 import com.android.systemui.util.ViewController;
 import com.android.systemui.util.animation.DisappearParameters;
 
+import kotlin.Unit;
+import kotlin.jvm.functions.Function1;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -50,9 +53,6 @@
 import java.util.function.Consumer;
 import java.util.stream.Collectors;
 
-import kotlin.Unit;
-import kotlin.jvm.functions.Function1;
-
 /**
  * Controller for QSPanel views.
  *
@@ -232,7 +232,7 @@
             mQsTileRevealController.updateRevealedTiles(tiles);
         }
         boolean shouldChange = false;
-        if (tiles.size() == mRecords.size()) {
+        if (tiles.size() <= mRecords.size()) {
             int i = 0;
             for (QSTile tile : tiles) {
                 if (tile != mRecords.get(i).tile) {
@@ -241,6 +241,17 @@
                 }
                 i++;
             }
+
+            // If the first tiles are the same as the new ones, remove any extras.
+            if (!shouldChange) {
+                while (i < mRecords.size()) {
+                    QSPanelControllerBase.TileRecord record = mRecords.get(i);
+                    mView.removeTile(record);
+                    record.tile.removeCallback(record.callback);
+                    i++;
+                }
+                mCachedSpecs = getTilesSpecs();
+            }
         } else {
             shouldChange = true;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index 1fab58e..828d6ed 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -57,6 +57,8 @@
 import com.android.systemui.tuner.TunerService.Tunable;
 import com.android.systemui.util.settings.SecureSettings;
 
+import dagger.Lazy;
+
 import org.jetbrains.annotations.NotNull;
 
 import java.io.PrintWriter;
@@ -73,8 +75,6 @@
 import javax.inject.Inject;
 import javax.inject.Provider;
 
-import dagger.Lazy;
-
 /** Platform implementation of the quick settings tile host
  *
  * This class keeps track of the set of current tiles and is the in memory source of truth
@@ -151,7 +151,7 @@
 
         mShadeController = shadeController;
 
-        if (featureFlags.getPipelineTilesEnabled()) {
+        if (featureFlags.getTilesEnabled()) {
             mQsFactories.add(newQsTileFactoryProvider.get());
         }
         mQsFactories.add(defaultFactory);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/dagger/QSPipelineModule.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/dagger/QSPipelineModule.kt
index b50798e..4bad45f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/dagger/QSPipelineModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/dagger/QSPipelineModule.kt
@@ -20,6 +20,7 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.log.LogBuffer
 import com.android.systemui.log.LogBufferFactory
+import com.android.systemui.qs.pipeline.data.model.RestoreProcessor
 import com.android.systemui.qs.pipeline.data.repository.DefaultTilesQSHostRepository
 import com.android.systemui.qs.pipeline.data.repository.DefaultTilesRepository
 import com.android.systemui.qs.pipeline.data.repository.InstalledTilesComponentRepository
@@ -39,14 +40,17 @@
 import dagger.Provides
 import dagger.multibindings.ClassKey
 import dagger.multibindings.IntoMap
+import dagger.multibindings.Multibinds
 
-@Module(includes = [QSAutoAddModule::class])
+@Module(includes = [QSAutoAddModule::class, RestoreProcessorsModule::class])
 abstract class QSPipelineModule {
 
     /** Implementation for [TileSpecRepository] */
     @Binds
     abstract fun provideTileSpecRepository(impl: TileSpecSettingsRepository): TileSpecRepository
 
+    @Multibinds abstract fun provideRestoreProcessors(): Set<RestoreProcessor>
+
     @Binds
     abstract fun provideDefaultTilesRepository(
         impl: DefaultTilesQSHostRepository
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/dagger/RestoreProcessorsModule.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/dagger/RestoreProcessorsModule.kt
new file mode 100644
index 0000000..e970c84
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/dagger/RestoreProcessorsModule.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.pipeline.dagger
+
+import com.android.systemui.qs.pipeline.data.model.RestoreProcessor
+import com.android.systemui.qs.pipeline.data.restoreprocessors.WorkTileRestoreProcessor
+import dagger.Binds
+import dagger.Module
+import dagger.multibindings.IntoSet
+
+@Module
+interface RestoreProcessorsModule {
+
+    @Binds
+    @IntoSet
+    fun bindWorkTileRestoreProcessor(impl: WorkTileRestoreProcessor): RestoreProcessor
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/model/RestoreProcessor.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/model/RestoreProcessor.kt
new file mode 100644
index 0000000..8f7de19
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/model/RestoreProcessor.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.pipeline.data.model
+
+/**
+ * Perform processing of the [RestoreData] before or after it's applied to repositories.
+ *
+ * The order in which the restore processors are applied in not deterministic.
+ *
+ * In order to declare a restore processor, add it in [RestoreProcessingModule] using
+ *
+ * ```
+ * @Binds
+ * @IntoSet
+ * ``
+ */
+interface RestoreProcessor {
+
+    /** Should be called before applying the restore to the necessary repositories */
+    suspend fun preProcessRestore(restoreData: RestoreData) {}
+
+    /** Should be called after requesting the repositories to update. */
+    suspend fun postProcessRestore(restoreData: RestoreData) {}
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/AutoAddRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/AutoAddRepository.kt
index 7998dfb..d40f3f4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/AutoAddRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/AutoAddRepository.kt
@@ -20,9 +20,8 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.qs.pipeline.data.model.RestoreData
 import com.android.systemui.qs.pipeline.shared.TileSpec
-import kotlinx.coroutines.flow.Flow
 import javax.inject.Inject
-import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.Flow
 
 /** Repository to track what QS tiles have been auto-added */
 interface AutoAddRepository {
@@ -49,8 +48,9 @@
 @SysUISingleton
 class AutoAddSettingRepository
 @Inject
-constructor(private val userAutoAddRepositoryFactory: UserAutoAddRepository.Factory) :
-    AutoAddRepository {
+constructor(
+    private val userAutoAddRepositoryFactory: UserAutoAddRepository.Factory,
+) : AutoAddRepository {
 
     private val userAutoAddRepositories = SparseArray<UserAutoAddRepository>()
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/QSSettingsRestoredRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/QSSettingsRestoredRepository.kt
index 6cee116..e718eea 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/QSSettingsRestoredRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/QSSettingsRestoredRepository.kt
@@ -10,6 +10,7 @@
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.qs.pipeline.data.model.RestoreData
+import com.android.systemui.qs.pipeline.data.repository.QSSettingsRestoredRepository.Companion.BUFFER_CAPACITY
 import com.android.systemui.qs.pipeline.data.repository.TilesSettingConverter.toTilesList
 import com.android.systemui.qs.pipeline.shared.logging.QSPipelineLogger
 import javax.inject.Inject
@@ -28,6 +29,14 @@
 /** Provides restored data (from Backup and Restore) for Quick Settings pipeline */
 interface QSSettingsRestoredRepository {
     val restoreData: Flow<RestoreData>
+
+    companion object {
+        // This capacity is the number of restore data that we will keep buffered in the shared
+        // flow. It is unlikely that at any given time there would be this many restores being
+        // processed by consumers, but just in case that a couple of users are restored at the
+        // same time and they need to be replayed for the consumers of the flow.
+        const val BUFFER_CAPACITY = 10
+    }
 }
 
 @SysUISingleton
@@ -86,11 +95,6 @@
 
     private companion object {
         private const val TAG = "QSSettingsRestoredBroadcastRepository"
-        // This capacity is the number of restore data that we will keep buffered in the shared
-        // flow. It is unlikely that at any given time there would be this many restores being
-        // processed by consumers, but just in case that a couple of users are restored at the
-        // same time and they need to be replayed for the consumers of the flow.
-        private const val BUFFER_CAPACITY = 10
 
         private val INTENT_FILTER = IntentFilter(Intent.ACTION_SETTING_RESTORED)
         private const val TILES_SETTING = Settings.Secure.QS_TILES
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/restoreprocessors/WorkTileRestoreProcessor.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/restoreprocessors/WorkTileRestoreProcessor.kt
new file mode 100644
index 0000000..7376aa9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/restoreprocessors/WorkTileRestoreProcessor.kt
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.pipeline.data.restoreprocessors
+
+import android.os.UserHandle
+import android.util.SparseIntArray
+import androidx.annotation.GuardedBy
+import androidx.core.util.getOrDefault
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.qs.pipeline.data.model.RestoreData
+import com.android.systemui.qs.pipeline.data.model.RestoreProcessor
+import com.android.systemui.qs.pipeline.data.repository.QSSettingsRestoredRepository
+import com.android.systemui.qs.pipeline.data.repository.TileSpecRepository
+import com.android.systemui.qs.pipeline.shared.TileSpec
+import com.android.systemui.qs.tiles.WorkModeTile
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.map
+
+/**
+ * Processor for restore data for work tile.
+ *
+ * It will indicate when auto-add tracking may be removed for a user. This may be necessary if the
+ * tile will be destroyed due to being not available, but needs to be added once work profile is
+ * enabled (after restore), in the same position as it was in the restored data.
+ */
+@SysUISingleton
+class WorkTileRestoreProcessor @Inject constructor() : RestoreProcessor {
+
+    @GuardedBy("lastRestorePosition") private val lastRestorePosition = SparseIntArray()
+
+    private val _removeTrackingForUser =
+        MutableSharedFlow<Int>(extraBufferCapacity = QSSettingsRestoredRepository.BUFFER_CAPACITY)
+
+    /**
+     * Flow indicating that we may need to remove auto-add tracking for the work tile for a given
+     * user.
+     */
+    fun removeTrackingForUser(userHandle: UserHandle): Flow<Unit> {
+        return _removeTrackingForUser.filter { it == userHandle.identifier }.map {}
+    }
+
+    override suspend fun postProcessRestore(restoreData: RestoreData) {
+        if (TILE_SPEC in restoreData.restoredTiles) {
+            synchronized(lastRestorePosition) {
+                lastRestorePosition.put(
+                    restoreData.userId,
+                    restoreData.restoredTiles.indexOf(TILE_SPEC)
+                )
+            }
+            _removeTrackingForUser.emit(restoreData.userId)
+        }
+    }
+
+    fun pollLastPosition(userId: Int): Int {
+        return synchronized(lastRestorePosition) {
+            lastRestorePosition.getOrDefault(userId, TileSpecRepository.POSITION_AT_END).also {
+                lastRestorePosition.delete(userId)
+            }
+        }
+    }
+
+    companion object {
+        private val TILE_SPEC = TileSpec.create(WorkModeTile.TILE_SPEC)
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/autoaddable/WorkTileAutoAddable.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/autoaddable/WorkTileAutoAddable.kt
index 5e3c348..b221199 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/autoaddable/WorkTileAutoAddable.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/autoaddable/WorkTileAutoAddable.kt
@@ -17,8 +17,10 @@
 package com.android.systemui.qs.pipeline.domain.autoaddable
 
 import android.content.pm.UserInfo
+import android.os.UserHandle
 import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.qs.pipeline.data.restoreprocessors.WorkTileRestoreProcessor
 import com.android.systemui.qs.pipeline.domain.model.AutoAddSignal
 import com.android.systemui.qs.pipeline.domain.model.AutoAddTracking
 import com.android.systemui.qs.pipeline.domain.model.AutoAddable
@@ -28,6 +30,8 @@
 import javax.inject.Inject
 import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.mapNotNull
+import kotlinx.coroutines.flow.merge
 
 /**
  * [AutoAddable] for [WorkModeTile.TILE_SPEC].
@@ -36,17 +40,37 @@
  * signal to remove it if there is not.
  */
 @SysUISingleton
-class WorkTileAutoAddable @Inject constructor(private val userTracker: UserTracker) : AutoAddable {
+class WorkTileAutoAddable
+@Inject
+constructor(
+    private val userTracker: UserTracker,
+    private val workTileRestoreProcessor: WorkTileRestoreProcessor,
+) : AutoAddable {
 
     private val spec = TileSpec.create(WorkModeTile.TILE_SPEC)
 
     override fun autoAddSignal(userId: Int): Flow<AutoAddSignal> {
-        return conflatedCallbackFlow {
+        val removeTrackingDueToRestore: Flow<AutoAddSignal> =
+            workTileRestoreProcessor.removeTrackingForUser(UserHandle.of(userId)).mapNotNull {
+                val profiles = userTracker.userProfiles
+                if (profiles.any { it.id == userId } && !profiles.any { it.isManagedProfile }) {
+                    // Only remove auto-added if there are no managed profiles for this user
+                    AutoAddSignal.RemoveTracking(spec)
+                } else {
+                    null
+                }
+            }
+        val signalsFromCallback = conflatedCallbackFlow {
             fun maybeSend(profiles: List<UserInfo>) {
                 if (profiles.any { it.id == userId }) {
                     // We are looking at the profiles of the correct user.
                     if (profiles.any { it.isManagedProfile }) {
-                        trySend(AutoAddSignal.Add(spec))
+                        trySend(
+                            AutoAddSignal.Add(
+                                spec,
+                                workTileRestoreProcessor.pollLastPosition(userId),
+                            )
+                        )
                     } else {
                         trySend(AutoAddSignal.Remove(spec))
                     }
@@ -65,6 +89,7 @@
 
             awaitClose { userTracker.removeCallback(callback) }
         }
+        return merge(removeTrackingDueToRestore, signalsFromCallback)
     }
 
     override val autoAddTracking = AutoAddTracking.Always
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/AutoAddInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/AutoAddInteractor.kt
index b747393..cde3835 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/AutoAddInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/AutoAddInteractor.kt
@@ -103,6 +103,10 @@
                                     qsPipelineLogger.logTileAutoRemoved(userId, signal.spec)
                                     repository.unmarkTileAdded(userId, signal.spec)
                                 }
+                                is AutoAddSignal.RemoveTracking -> {
+                                    qsPipelineLogger.logTileUnmarked(userId, signal.spec)
+                                    repository.unmarkTileAdded(userId, signal.spec)
+                                }
                             }
                         }
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractor.kt
index 4bda730..5d28c8c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractor.kt
@@ -336,7 +336,7 @@
     private suspend fun createTile(spec: TileSpec): QSTile? {
         val tile =
             withContext(mainDispatcher) {
-                if (featureFlags.pipelineTilesEnabled) {
+                if (featureFlags.tilesEnabled) {
                     newQSTileFactory.get().createTile(spec.spec)
                 } else {
                     null
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/RestoreReconciliationInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/RestoreReconciliationInteractor.kt
index 9844903..a5be14e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/RestoreReconciliationInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/RestoreReconciliationInteractor.kt
@@ -3,14 +3,15 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.qs.pipeline.data.model.RestoreProcessor
 import com.android.systemui.qs.pipeline.data.repository.AutoAddRepository
 import com.android.systemui.qs.pipeline.data.repository.QSSettingsRestoredRepository
 import com.android.systemui.qs.pipeline.data.repository.TileSpecRepository
+import com.android.systemui.qs.pipeline.shared.logging.QSPipelineLogger
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.flow.collect
 import kotlinx.coroutines.flow.flatMapConcat
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.take
@@ -33,6 +34,8 @@
     private val tileSpecRepository: TileSpecRepository,
     private val autoAddRepository: AutoAddRepository,
     private val qsSettingsRestoredRepository: QSSettingsRestoredRepository,
+    private val restoreProcessors: Set<@JvmSuppressWildcards RestoreProcessor>,
+    private val qsPipelineLogger: QSPipelineLogger,
     @Application private val applicationScope: CoroutineScope,
     @Background private val backgroundDispatcher: CoroutineDispatcher,
 ) {
@@ -40,14 +43,30 @@
     @OptIn(ExperimentalCoroutinesApi::class)
     fun start() {
         applicationScope.launch(backgroundDispatcher) {
-            qsSettingsRestoredRepository.restoreData.flatMapConcat { data ->
-                autoAddRepository.autoAddedTiles(data.userId)
-                        .take(1)
-                        .map { tiles -> data to tiles }
-            }.collect { (restoreData, autoAdded) ->
-                tileSpecRepository.reconcileRestore(restoreData, autoAdded)
-                autoAddRepository.reconcileRestore(restoreData)
-            }
+            qsSettingsRestoredRepository.restoreData
+                .flatMapConcat { data ->
+                    autoAddRepository.autoAddedTiles(data.userId).take(1).map { tiles ->
+                        data to tiles
+                    }
+                }
+                .collect { (restoreData, autoAdded) ->
+                    restoreProcessors.forEach {
+                        it.preProcessRestore(restoreData)
+                        qsPipelineLogger.logRestoreProcessorApplied(
+                            it::class.simpleName,
+                            QSPipelineLogger.RestorePreprocessorStep.PREPROCESSING,
+                        )
+                    }
+                    tileSpecRepository.reconcileRestore(restoreData, autoAdded)
+                    autoAddRepository.reconcileRestore(restoreData)
+                    restoreProcessors.forEach {
+                        it.postProcessRestore(restoreData)
+                        qsPipelineLogger.logRestoreProcessorApplied(
+                            it::class.simpleName,
+                            QSPipelineLogger.RestorePreprocessorStep.POSTPROCESSING,
+                        )
+                    }
+                }
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/model/AutoAddSignal.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/model/AutoAddSignal.kt
index ed7b8bd..8263680 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/model/AutoAddSignal.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/model/AutoAddSignal.kt
@@ -34,4 +34,9 @@
     data class Remove(
         override val spec: TileSpec,
     ) : AutoAddSignal
+
+    /** Signal for remove the auto-add marker from the tile, but not remove the tile */
+    data class RemoveTracking(
+        override val spec: TileSpec,
+    ) : AutoAddSignal
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/QSPipelineFlagsRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/QSPipelineFlagsRepository.kt
index 5c7420c..42bee3c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/QSPipelineFlagsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/QSPipelineFlagsRepository.kt
@@ -2,24 +2,18 @@
 
 import com.android.systemui.Flags as AconfigFlags
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.flags.FeatureFlagsClassic
-import com.android.systemui.flags.Flags
 import com.android.systemui.flags.RefactorFlagUtils
 import javax.inject.Inject
 
 /** Encapsulate the different QS pipeline flags and their dependencies */
 @SysUISingleton
-class QSPipelineFlagsRepository
-@Inject
-constructor(
-    private val featureFlags: FeatureFlagsClassic,
-) {
+class QSPipelineFlagsRepository @Inject constructor() {
+
     val pipelineEnabled: Boolean
         get() = AconfigFlags.qsNewPipeline()
 
-    /** @see Flags.QS_PIPELINE_NEW_TILES */
-    val pipelineTilesEnabled: Boolean
-        get() = featureFlags.isEnabled(Flags.QS_PIPELINE_NEW_TILES)
+    val tilesEnabled: Boolean
+        get() = AconfigFlags.qsNewTiles()
 
     companion object Utils {
         fun assertInLegacyMode() =
@@ -27,5 +21,11 @@
                 AconfigFlags.qsNewPipeline(),
                 AconfigFlags.FLAG_QS_NEW_PIPELINE
             )
+
+        fun assertNewTiles() =
+            RefactorFlagUtils.assertInNewMode(
+                AconfigFlags.qsNewTiles(),
+                AconfigFlags.FLAG_QS_NEW_TILES
+            )
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/logging/QSPipelineLogger.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/logging/QSPipelineLogger.kt
index bca86c9..7d2c6c8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/logging/QSPipelineLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/logging/QSPipelineLogger.kt
@@ -209,6 +209,18 @@
         )
     }
 
+    fun logTileUnmarked(userId: Int, spec: TileSpec) {
+        tileAutoAddLogBuffer.log(
+            AUTO_ADD_TAG,
+            LogLevel.DEBUG,
+            {
+                int1 = userId
+                str1 = spec.toString()
+            },
+            { "Tile $str1 unmarked as auto-added for user $int1" }
+        )
+    }
+
     fun logSettingsRestored(restoreData: RestoreData) {
         restoreLogBuffer.log(
             RESTORE_TAG,
@@ -226,6 +238,21 @@
         )
     }
 
+    fun logRestoreProcessorApplied(
+        restoreProcessorClassName: String?,
+        step: RestorePreprocessorStep,
+    ) {
+        restoreLogBuffer.log(
+            RESTORE_TAG,
+            LogLevel.DEBUG,
+            {
+                str1 = restoreProcessorClassName
+                str2 = step.name
+            },
+            { "Restore $str2 processed by $str1" }
+        )
+    }
+
     /** Reasons for destroying an existing tile. */
     enum class TileDestroyedReason(val readable: String) {
         TILE_REMOVED("Tile removed from  current set"),
@@ -234,4 +261,9 @@
         EXISTING_TILE_NOT_AVAILABLE("Existing tile not available"),
         TILE_NOT_PRESENT_IN_NEW_USER("Tile not present in new user"),
     }
+
+    enum class RestorePreprocessorStep {
+        PREPROCESSING,
+        POSTPROCESSING
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
index 38bbce4..17e6375 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
@@ -19,6 +19,7 @@
 
 import androidx.annotation.Nullable;
 
+import com.android.systemui.accessibility.qs.QSAccessibilityModule;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.plugins.qs.QSFactory;
 import com.android.systemui.plugins.qs.QSTile;
@@ -41,7 +42,7 @@
  * com.android.systemui.qs.tiles.DreamTile#TILE_SPEC})
  *
  * After, create or find an existing Module class to house the tile's binding method (e.g. {@link
- * com.android.systemui.accessibility.AccessibilityModule}). If creating a new module, add your
+ * QSAccessibilityModule}). If creating a new module, add your
  * module to the SystemUI dagger graph by including it in an appropriate module.
  */
 @SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RecordIssueTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/RecordIssueTile.kt
new file mode 100644
index 0000000..66da8bd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RecordIssueTile.kt
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles
+
+import android.app.AlertDialog
+import android.content.Intent
+import android.os.Handler
+import android.os.Looper
+import android.service.quicksettings.Tile
+import android.text.TextUtils
+import android.view.View
+import android.widget.Switch
+import androidx.annotation.VisibleForTesting
+import com.android.internal.jank.InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN
+import com.android.internal.logging.MetricsLogger
+import com.android.systemui.Flags.recordIssueQsTile
+import com.android.systemui.animation.DialogCuj
+import com.android.systemui.animation.DialogLaunchAnimator
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.plugins.qs.QSTile
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.qs.QSHost
+import com.android.systemui.qs.QsEventLogger
+import com.android.systemui.qs.logging.QSLogger
+import com.android.systemui.qs.tileimpl.QSTileImpl
+import com.android.systemui.recordissue.RecordIssueDialogDelegate
+import com.android.systemui.res.R
+import com.android.systemui.settings.UserContextProvider
+import com.android.systemui.statusbar.phone.KeyguardDismissUtil
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import javax.inject.Inject
+
+class RecordIssueTile
+@Inject
+constructor(
+    host: QSHost,
+    uiEventLogger: QsEventLogger,
+    @Background backgroundLooper: Looper,
+    @Main mainHandler: Handler,
+    falsingManager: FalsingManager,
+    metricsLogger: MetricsLogger,
+    statusBarStateController: StatusBarStateController,
+    activityStarter: ActivityStarter,
+    qsLogger: QSLogger,
+    private val keyguardDismissUtil: KeyguardDismissUtil,
+    private val keyguardStateController: KeyguardStateController,
+    private val dialogLaunchAnimator: DialogLaunchAnimator,
+    private val sysuiDialogFactory: SystemUIDialog.Factory,
+    private val userContextProvider: UserContextProvider,
+) :
+    QSTileImpl<QSTile.BooleanState>(
+        host,
+        uiEventLogger,
+        backgroundLooper,
+        mainHandler,
+        falsingManager,
+        metricsLogger,
+        statusBarStateController,
+        activityStarter,
+        qsLogger
+    ) {
+
+    @VisibleForTesting var isRecording: Boolean = false
+
+    override fun getTileLabel(): CharSequence = mContext.getString(R.string.qs_record_issue_label)
+
+    override fun isAvailable(): Boolean = recordIssueQsTile()
+
+    override fun newTileState(): QSTile.BooleanState =
+        QSTile.BooleanState().apply {
+            label = tileLabel
+            handlesLongClick = false
+        }
+
+    @VisibleForTesting
+    public override fun handleClick(view: View?) {
+        if (isRecording) {
+            isRecording = false
+        } else {
+            mUiHandler.post { showPrompt(view) }
+        }
+        refreshState()
+    }
+
+    private fun showPrompt(view: View?) {
+        val dialog: AlertDialog =
+            RecordIssueDialogDelegate(sysuiDialogFactory, userContextProvider) {
+                    isRecording = true
+                    refreshState()
+                }
+                .createDialog()
+        val dismissAction =
+            ActivityStarter.OnDismissAction {
+                // We animate from the touched view only if we are not on the keyguard, given
+                // that if we are we will dismiss it which will also collapse the shade.
+                if (view != null && !keyguardStateController.isShowing) {
+                    dialogLaunchAnimator.showFromView(
+                        dialog,
+                        view,
+                        DialogCuj(CUJ_SHADE_DIALOG_OPEN, TILE_SPEC)
+                    )
+                } else {
+                    dialog.show()
+                }
+                false
+            }
+        keyguardDismissUtil.executeWhenUnlocked(dismissAction, false, true)
+    }
+
+    override fun getLongClickIntent(): Intent? = null
+
+    @VisibleForTesting
+    public override fun handleUpdateState(qsTileState: QSTile.BooleanState, arg: Any?) {
+        qsTileState.apply {
+            if (isRecording) {
+                value = true
+                state = Tile.STATE_ACTIVE
+                forceExpandIcon = false
+                secondaryLabel = mContext.getString(R.string.qs_record_issue_stop)
+                icon = ResourceIcon.get(R.drawable.qs_record_issue_icon_on)
+            } else {
+                value = false
+                state = Tile.STATE_INACTIVE
+                forceExpandIcon = true
+                secondaryLabel = mContext.getString(R.string.qs_record_issue_start)
+                icon = ResourceIcon.get(R.drawable.qs_record_issue_icon_off)
+            }
+            label = tileLabel
+            contentDescription =
+                if (TextUtils.isEmpty(secondaryLabel)) label else "$label, $secondaryLabel"
+            expandedAccessibilityClassName = Switch::class.java.name
+        }
+    }
+
+    companion object {
+        const val TILE_SPEC = "record_issue"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/QSTileUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/QSTileUserActionInteractor.kt
index 09d7a1f..17b78eb 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/QSTileUserActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/interactor/QSTileUserActionInteractor.kt
@@ -24,7 +24,7 @@
      * [QSTileInput.data]. It's guaranteed that [QSTileInput.userId] is the same as the id passed to
      * [QSTileDataInteractor] to get [QSTileInput.data].
      *
-     * It's safe to run long running computations inside this function in this.
+     * It's safe to run long running computations inside this function.
      */
     @WorkerThread suspend fun handleInput(input: QSTileInput<DATA_TYPE>)
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileCoroutineScopeFactory.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileCoroutineScopeFactory.kt
new file mode 100644
index 0000000..d0437a7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileCoroutineScopeFactory.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.base.viewmodel
+
+import com.android.systemui.dagger.qualifiers.Application
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.SupervisorJob
+
+/** Creates a [CoroutineScope] for the [QSTileViewModelImpl]. */
+class QSTileCoroutineScopeFactory
+@Inject
+constructor(@Application private val applicationScope: CoroutineScope) {
+
+    fun create(): CoroutineScope =
+        CoroutineScope(applicationScope.coroutineContext + SupervisorJob())
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelFactory.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelFactory.kt
index ae554d9..ffa3b54 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelFactory.kt
@@ -82,6 +82,7 @@
                 qsTileLogger,
                 systemClock,
                 backgroundDispatcher,
+                component.coroutineScope(),
             )
         }
     }
@@ -101,6 +102,7 @@
         private val qsTileConfigProvider: QSTileConfigProvider,
         private val systemClock: SystemClock,
         @Background private val backgroundDispatcher: CoroutineDispatcher,
+        private val coroutineScopeFactory: QSTileCoroutineScopeFactory,
     ) : QSTileViewModelFactory<T> {
 
         /**
@@ -130,6 +132,7 @@
                 qsTileLogger,
                 systemClock,
                 backgroundDispatcher,
+                coroutineScopeFactory.create(),
             )
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImpl.kt
index 9fe316f..45c6fff 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImpl.kt
@@ -39,7 +39,6 @@
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.SupervisorJob
 import kotlinx.coroutines.cancel
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableSharedFlow
@@ -82,7 +81,7 @@
     private val qsTileLogger: QSTileLogger,
     private val systemClock: SystemClock,
     private val backgroundDispatcher: CoroutineDispatcher,
-    private val tileScope: CoroutineScope = CoroutineScope(SupervisorJob()),
+    private val tileScope: CoroutineScope,
 ) : QSTileViewModel, Dumpable {
 
     private val users: MutableStateFlow<UserHandle> =
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/di/NewQSTileFactory.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/di/NewQSTileFactory.kt
index 27007bb..382cfe2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/di/NewQSTileFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/di/NewQSTileFactory.kt
@@ -19,6 +19,7 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.plugins.qs.QSFactory
 import com.android.systemui.plugins.qs.QSTile
+import com.android.systemui.qs.pipeline.shared.QSPipelineFlagsRepository
 import com.android.systemui.qs.pipeline.shared.TileSpec
 import com.android.systemui.qs.tiles.base.viewmodel.QSTileViewModelFactory
 import com.android.systemui.qs.tiles.impl.custom.di.CustomTileComponent
@@ -44,6 +45,7 @@
 ) : QSFactory {
 
     init {
+        QSPipelineFlagsRepository.assertNewTiles()
         for (viewModelTileSpec in tileMap.keys) {
             require(qsTileConfigProvider.hasConfig(viewModelTileSpec)) {
                 "No config for $viewModelTileSpec"
@@ -54,7 +56,7 @@
     override fun createTile(tileSpec: String): QSTile? {
         val viewModel: QSTileViewModel =
             when (val spec = TileSpec.create(tileSpec)) {
-                is TileSpec.CustomTileSpec -> createCustomTileViewModel(spec)
+                is TileSpec.CustomTileSpec -> null
                 is TileSpec.PlatformTileSpec -> tileMap[tileSpec]?.get()
                 is TileSpec.Invalid -> null
             }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/di/QSTilesModule.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/di/QSTilesModule.kt
index 4a34276..b325b4d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/di/QSTilesModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/di/QSTilesModule.kt
@@ -16,6 +16,8 @@
 
 package com.android.systemui.qs.tiles.di
 
+import android.content.Context
+import android.content.res.Resources.Theme
 import com.android.systemui.qs.external.CustomTileStatePersister
 import com.android.systemui.qs.external.CustomTileStatePersisterImpl
 import com.android.systemui.qs.tiles.base.actions.QSTileIntentUserInputHandler
@@ -27,6 +29,7 @@
 import com.android.systemui.qs.tiles.viewmodel.QSTileViewModel
 import dagger.Binds
 import dagger.Module
+import dagger.Provides
 import dagger.multibindings.Multibinds
 
 /** Module listing subcomponents */
@@ -57,4 +60,9 @@
 
     @Binds
     fun bindCustomTileStatePersister(impl: CustomTileStatePersisterImpl): CustomTileStatePersister
+
+    companion object {
+
+        @Provides fun provideTilesTheme(context: Context): Theme = context.theme
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
index 2350b5d..9d214e7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
@@ -59,12 +59,12 @@
 import com.android.internal.logging.UiEventLogger;
 import com.android.settingslib.wifi.WifiEnterpriseRestrictionUtils;
 import com.android.systemui.Prefs;
-import com.android.systemui.res.R;
 import com.android.systemui.accessibility.floatingmenu.AnnotationLinkSpan;
 import com.android.systemui.animation.DialogLaunchAnimator;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.wifitrackerlib.WifiEntry;
@@ -157,14 +157,6 @@
 
     // Wi-Fi scanning progress bar
     protected boolean mIsProgressBarVisible;
-    protected boolean mIsSearchingHidden;
-    protected final Runnable mHideProgressBarRunnable = () -> {
-        setProgressBarVisible(false);
-    };
-    protected Runnable mHideSearchingRunnable = () -> {
-        mIsSearchingHidden = true;
-        mInternetDialogSubTitle.setText(getSubtitleText());
-    };
 
     @Inject
     public InternetDialog(Context context, InternetDialogFactory internetDialogFactory,
@@ -285,8 +277,6 @@
         if (DEBUG) {
             Log.d(TAG, "onStop");
         }
-        mHandler.removeCallbacks(mHideProgressBarRunnable);
-        mHandler.removeCallbacks(mHideSearchingRunnable);
         mMobileNetworkLayout.setOnClickListener(null);
         mConnectedWifListLayout.setOnClickListener(null);
         if (mSecondaryMobileNetworkLayout != null) {
@@ -335,7 +325,6 @@
             return;
         }
 
-        showProgressBar();
         final boolean isDeviceLocked = mInternetDialogController.isDeviceLocked();
         final boolean isWifiEnabled = mInternetDialogController.isWifiEnabled();
         final boolean isWifiScanEnabled = mInternetDialogController.isWifiScanEnabled();
@@ -641,8 +630,7 @@
 
     @Nullable
     CharSequence getSubtitleText() {
-        return mInternetDialogController.getSubtitleText(
-                mIsProgressBarVisible && !mIsSearchingHidden);
+        return mInternetDialogController.getSubtitleText(mIsProgressBarVisible);
     }
 
     private Drawable getSignalStrengthDrawable(int subId) {
@@ -657,20 +645,6 @@
         return mInternetDialogController.getMobileNetworkSummary(subId);
     }
 
-    protected void showProgressBar() {
-        if (!mInternetDialogController.isWifiEnabled()
-                || mInternetDialogController.isDeviceLocked()) {
-            setProgressBarVisible(false);
-            return;
-        }
-        setProgressBarVisible(true);
-        if (mConnectedWifiEntry != null || mWifiEntriesCount > 0) {
-            mHandler.postDelayed(mHideProgressBarRunnable, PROGRESS_DELAY_MS);
-        } else if (!mIsSearchingHidden) {
-            mHandler.postDelayed(mHideSearchingRunnable, PROGRESS_DELAY_MS);
-        }
-    }
-
     private void setProgressBarVisible(boolean visible) {
         if (mIsProgressBarVisible == visible) {
             return;
@@ -823,6 +797,11 @@
     }
 
     @Override
+    public void onWifiScan(boolean isScan) {
+        setProgressBarVisible(isScan);
+    }
+
+    @Override
     public void onWindowFocusChanged(boolean hasFocus) {
         super.onWindowFocusChanged(hasFocus);
         if (mAlertDialog != null && !mAlertDialog.isShowing()) {
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 f516f55..592cb3b 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
@@ -75,7 +75,6 @@
 import com.android.settingslib.net.SignalStrengthUtil;
 import com.android.settingslib.wifi.WifiUtils;
 import com.android.settingslib.wifi.dpp.WifiDppIntentHelper;
-import com.android.systemui.res.R;
 import com.android.systemui.animation.ActivityLaunchAnimator;
 import com.android.systemui.animation.DialogLaunchAnimator;
 import com.android.systemui.broadcast.BroadcastDispatcher;
@@ -84,6 +83,7 @@
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.flags.Flags;
 import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.connectivity.AccessPointController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.statusbar.policy.LocationController;
@@ -1129,6 +1129,15 @@
     public void onSettingsActivityTriggered(Intent settingsIntent) {
     }
 
+    @Override
+    public void onWifiScan(boolean isScan) {
+        if (!isWifiEnabled() || isDeviceLocked()) {
+            mCallback.onWifiScan(false);
+            return;
+        }
+        mCallback.onWifiScan(isScan);
+    }
+
     private class InternetTelephonyCallback extends TelephonyCallback implements
             TelephonyCallback.DataConnectionStateListener,
             TelephonyCallback.DisplayInfoListener,
@@ -1372,6 +1381,8 @@
 
         void onAccessPointsChanged(@Nullable List<WifiEntry> wifiEntries,
                 @Nullable WifiEntry connectedEntry, boolean hasMoreWifiEntries);
+
+        void onWifiScan(boolean isScan);
     }
 
     void makeOverlayToast(int stringId) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialog.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialog.kt
index db3cf0f..1805eb1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialog.kt
@@ -24,6 +24,7 @@
 import android.view.View.GONE
 import android.view.View.VISIBLE
 import android.view.ViewGroup
+import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
 import android.view.accessibility.AccessibilityNodeInfo
 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction
 import android.widget.ImageView
@@ -54,6 +55,7 @@
 constructor(
     private val bluetoothToggleInitialValue: Boolean,
     private val subtitleResIdInitialValue: Int,
+    private val cachedContentHeight: Int,
     private val bluetoothTileDialogCallback: BluetoothTileDialogCallback,
     @Main private val mainDispatcher: CoroutineDispatcher,
     private val systemClock: SystemClock,
@@ -72,6 +74,11 @@
     internal val deviceItemClick
         get() = mutableDeviceItemClick.asSharedFlow()
 
+    private val mutableContentHeight: MutableSharedFlow<Int> =
+        MutableSharedFlow(extraBufferCapacity = 1)
+    internal val contentHeight
+        get() = mutableContentHeight.asSharedFlow()
+
     private val deviceItemAdapter: Adapter = Adapter(bluetoothTileDialogCallback)
 
     private var lastUiUpdateMs: Long = -1
@@ -84,6 +91,7 @@
     private lateinit var seeAllButton: View
     private lateinit var pairNewDeviceButton: View
     private lateinit var deviceListView: RecyclerView
+    private lateinit var scrollViewContent: View
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
@@ -110,12 +118,23 @@
         pairNewDeviceButton.setOnClickListener {
             bluetoothTileDialogCallback.onPairNewDeviceClicked(it)
         }
+        requireViewById<View>(R.id.scroll_view).apply {
+            scrollViewContent = this
+            layoutParams.height = cachedContentHeight
+        }
     }
 
     override fun start() {
         lastUiUpdateMs = systemClock.elapsedRealtime()
     }
 
+    override fun dismiss() {
+        if (::scrollViewContent.isInitialized) {
+            mutableContentHeight.tryEmit(scrollViewContent.measuredHeight)
+        }
+        super.dismiss()
+    }
+
     internal suspend fun onDeviceItemUpdated(
         deviceItem: List<DeviceItem>,
         showSeeAll: Boolean,
@@ -124,14 +143,16 @@
         withContext(mainDispatcher) {
             val start = systemClock.elapsedRealtime()
             val itemRow = deviceItem.size + showSeeAll.toInt() + showPairNewDevice.toInt()
-            // Add a slight delay for smoother dialog height change
-            if (itemRow != lastItemRow) {
+            // If not the first load, add a slight delay for smoother dialog height change
+            if (itemRow != lastItemRow && lastItemRow != -1) {
                 delay(MIN_HEIGHT_CHANGE_INTERVAL_MS - (start - lastUiUpdateMs))
             }
             if (isActive) {
                 deviceItemAdapter.refreshDeviceItemList(deviceItem) {
                     seeAllButton.visibility = if (showSeeAll) VISIBLE else GONE
                     pairNewDeviceButton.visibility = if (showPairNewDevice) VISIBLE else GONE
+                    // Update the height after data is updated
+                    scrollViewContent.layoutParams.height = WRAP_CONTENT
                     lastUiUpdateMs = systemClock.elapsedRealtime()
                     lastItemRow = itemRow
                     logger.logDeviceUiUpdate(lastUiUpdateMs - start)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogViewModel.kt
index 5d5e747..6d08f59 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogViewModel.kt
@@ -18,14 +18,18 @@
 
 import android.content.Context
 import android.content.Intent
+import android.content.SharedPreferences
 import android.os.Bundle
 import android.view.View
+import android.view.ViewGroup
 import com.android.internal.jank.InteractionJankMonitor
 import com.android.internal.logging.UiEventLogger
+import com.android.systemui.Prefs
 import com.android.systemui.animation.DialogCuj
 import com.android.systemui.animation.DialogLaunchAnimator
 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.plugins.ActivityStarter
 import com.android.systemui.qs.tiles.dialog.bluetooth.BluetoothTileDialog.Companion.ACTION_BLUETOOTH_DEVICE_DETAILS
@@ -45,6 +49,7 @@
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
 
 /** ViewModel for Bluetooth Dialog after clicking on the Bluetooth QS tile. */
 @SysUISingleton
@@ -60,6 +65,8 @@
     private val logger: BluetoothTileDialogLogger,
     @Application private val coroutineScope: CoroutineScope,
     @Main private val mainDispatcher: CoroutineDispatcher,
+    @Background private val backgroundDispatcher: CoroutineDispatcher,
+    @Main private val sharedPreferences: SharedPreferences,
 ) : BluetoothTileDialogCallback {
 
     private var job: Job? = null
@@ -145,14 +152,31 @@
                     .onEach { deviceItemInteractor.updateDeviceItemOnClick(it) }
                     .launchIn(this)
 
+                dialog.contentHeight
+                    .onEach {
+                        withContext(backgroundDispatcher) {
+                            sharedPreferences.edit().putInt(CONTENT_HEIGHT_PREF_KEY, it).apply()
+                        }
+                    }
+                    .launchIn(this)
+
                 produce<Unit> { awaitClose { dialog.cancel() } }
             }
     }
 
-    private fun createBluetoothTileDialog(context: Context): BluetoothTileDialog {
+    private suspend fun createBluetoothTileDialog(context: Context): BluetoothTileDialog {
+        val cachedContentHeight =
+            withContext(backgroundDispatcher) {
+                sharedPreferences.getInt(
+                    CONTENT_HEIGHT_PREF_KEY,
+                    ViewGroup.LayoutParams.WRAP_CONTENT
+                )
+            }
+
         return BluetoothTileDialog(
                 bluetoothStateInteractor.isBluetoothEnabled,
                 getSubtitleResId(bluetoothStateInteractor.isBluetoothEnabled),
+                cachedContentHeight,
                 this@BluetoothTileDialogViewModel,
                 mainDispatcher,
                 systemClock,
@@ -205,6 +229,7 @@
 
     companion object {
         private const val INTERACTION_JANK_TAG = "bluetooth_tile_dialog"
+        private const val CONTENT_HEIGHT_PREF_KEY = Prefs.Key.BLUETOOTH_TILE_DIALOG_CONTENT_HEIGHT
         private fun getSubtitleResId(isBluetoothEnabled: Boolean) =
             if (isBluetoothEnabled) R.string.quick_settings_bluetooth_tile_subtitle
             else R.string.bt_is_off
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 cfb5442..9b8dba1 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
@@ -17,6 +17,7 @@
 package com.android.systemui.qs.tiles.impl.airplane.domain
 
 import android.content.res.Resources
+import android.content.res.Resources.Theme
 import com.android.systemui.common.shared.model.Icon
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
@@ -27,18 +28,25 @@
 import javax.inject.Inject
 
 /** Maps [AirplaneModeTileModel] to [QSTileState]. */
-class AirplaneModeMapper @Inject constructor(@Main private val resources: Resources) :
-    QSTileDataToStateMapper<AirplaneModeTileModel> {
+class AirplaneModeMapper
+@Inject
+constructor(
+    @Main private val resources: Resources,
+    val theme: Theme,
+) : QSTileDataToStateMapper<AirplaneModeTileModel> {
 
     override fun map(config: QSTileConfig, data: AirplaneModeTileModel): QSTileState =
-        QSTileState.build(resources, config.uiConfig) {
+        QSTileState.build(resources, theme, config.uiConfig) {
             val icon =
-                Icon.Resource(
-                    if (data.isEnabled) {
-                        R.drawable.qs_airplane_icon_on
-                    } else {
-                        R.drawable.qs_airplane_icon_off
-                    },
+                Icon.Loaded(
+                    resources.getDrawable(
+                        if (data.isEnabled) {
+                            R.drawable.qs_airplane_icon_on
+                        } else {
+                            R.drawable.qs_airplane_icon_off
+                        },
+                        theme,
+                    ),
                     contentDescription = null
                 )
             this.icon = { icon }
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 6386577..e075e76 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
@@ -17,6 +17,7 @@
 package com.android.systemui.qs.tiles.impl.alarm.domain
 
 import android.content.res.Resources
+import android.content.res.Resources.Theme
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
 import com.android.systemui.qs.tiles.impl.alarm.domain.model.AlarmTileModel
@@ -30,14 +31,18 @@
 import javax.inject.Inject
 
 /** Maps [AlarmTileModel] to [QSTileState]. */
-class AlarmTileMapper @Inject constructor(@Main private val resources: Resources) :
-    QSTileDataToStateMapper<AlarmTileModel> {
+class AlarmTileMapper
+@Inject
+constructor(
+    @Main private val resources: Resources,
+    private val theme: Theme,
+) : QSTileDataToStateMapper<AlarmTileModel> {
     companion object {
         val formatter12Hour: DateTimeFormatter = DateTimeFormatter.ofPattern("E hh:mm a")
         val formatter24Hour: DateTimeFormatter = DateTimeFormatter.ofPattern("E HH:mm")
     }
     override fun map(config: QSTileConfig, data: AlarmTileModel): QSTileState =
-        QSTileState.build(resources, config.uiConfig) {
+        QSTileState.build(resources, theme, config.uiConfig) {
             when (data) {
                 is AlarmTileModel.NextAlarmSet -> {
                     activationState = QSTileState.ActivationState.ACTIVE
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
new file mode 100644
index 0000000..1efbfd7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/ColorCorrectionTileMapper.kt
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.colorcorrection.domain
+
+import android.content.res.Resources
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
+import com.android.systemui.qs.tiles.impl.colorcorrection.domain.model.ColorCorrectionTileModel
+import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
+import com.android.systemui.qs.tiles.viewmodel.QSTileState
+import com.android.systemui.res.R
+import javax.inject.Inject
+
+/** Maps [ColorCorrectionTileModel] to [QSTileState]. */
+class ColorCorrectionTileMapper
+@Inject
+constructor(
+    @Main private val resources: Resources,
+    private val theme: Resources.Theme,
+) : QSTileDataToStateMapper<ColorCorrectionTileModel> {
+
+    override fun map(config: QSTileConfig, data: ColorCorrectionTileModel): QSTileState =
+        QSTileState.build(resources, theme, config.uiConfig) {
+            val subtitleArray = resources.getStringArray(R.array.tile_states_color_correction)
+
+            if (data.isEnabled) {
+                activationState = QSTileState.ActivationState.ACTIVE
+                secondaryLabel = subtitleArray[2]
+            } else {
+                activationState = QSTileState.ActivationState.INACTIVE
+                secondaryLabel = subtitleArray[1]
+            }
+            contentDescription = label
+            supportedActions =
+                setOf(QSTileState.UserAction.CLICK, QSTileState.UserAction.LONG_CLICK)
+        }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/interactor/ColorCorrectionTileDataInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/interactor/ColorCorrectionTileDataInteractor.kt
new file mode 100644
index 0000000..cd33d45
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/interactor/ColorCorrectionTileDataInteractor.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.colorcorrection.domain.interactor
+
+import android.os.UserHandle
+import com.android.systemui.accessibility.data.repository.ColorCorrectionRepository
+import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
+import com.android.systemui.qs.tiles.base.interactor.QSTileDataInteractor
+import com.android.systemui.qs.tiles.impl.colorcorrection.domain.model.ColorCorrectionTileModel
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.map
+
+/** Observes color correction state changes providing the [ColorCorrectionTileModel]. */
+class ColorCorrectionTileDataInteractor
+@Inject
+constructor(
+    private val colorCorrectionRepository: ColorCorrectionRepository,
+) : QSTileDataInteractor<ColorCorrectionTileModel> {
+
+    override fun tileData(
+        user: UserHandle,
+        triggers: Flow<DataUpdateTrigger>
+    ): Flow<ColorCorrectionTileModel> {
+        return colorCorrectionRepository.isEnabled(user).map { ColorCorrectionTileModel(it) }
+    }
+    override fun availability(user: UserHandle): Flow<Boolean> = flowOf(true)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/interactor/ColorCorrectionUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/interactor/ColorCorrectionUserActionInteractor.kt
new file mode 100644
index 0000000..d183802
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/interactor/ColorCorrectionUserActionInteractor.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.colorcorrection.domain.interactor
+
+import android.content.Intent
+import android.provider.Settings
+import com.android.systemui.accessibility.data.repository.ColorCorrectionRepository
+import com.android.systemui.qs.tiles.base.actions.QSTileIntentUserInputHandler
+import com.android.systemui.qs.tiles.base.interactor.QSTileInput
+import com.android.systemui.qs.tiles.base.interactor.QSTileUserActionInteractor
+import com.android.systemui.qs.tiles.impl.colorcorrection.domain.model.ColorCorrectionTileModel
+import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
+import javax.inject.Inject
+
+/** Handles color correction tile clicks. */
+class ColorCorrectionUserActionInteractor
+@Inject
+constructor(
+    private val colorCorrectionRepository: ColorCorrectionRepository,
+    private val qsTileIntentUserActionHandler: QSTileIntentUserInputHandler,
+) : QSTileUserActionInteractor<ColorCorrectionTileModel> {
+
+    override suspend fun handleInput(input: QSTileInput<ColorCorrectionTileModel>): Unit =
+        with(input) {
+            when (action) {
+                is QSTileUserAction.Click -> {
+                    colorCorrectionRepository.setIsEnabled(
+                        !data.isEnabled,
+                        user,
+                    )
+                }
+                is QSTileUserAction.LongClick -> {
+                    qsTileIntentUserActionHandler.handle(
+                        action.view,
+                        Intent(Settings.ACTION_COLOR_CORRECTION_SETTINGS)
+                    )
+                }
+            }
+        }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsLottieViewWrapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/model/ColorCorrectionTileModel.kt
similarity index 66%
copy from packages/SystemUI/src/com/android/systemui/biometrics/SideFpsLottieViewWrapper.kt
copy to packages/SystemUI/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/model/ColorCorrectionTileModel.kt
index e98f6db..66487e1 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsLottieViewWrapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/model/ColorCorrectionTileModel.kt
@@ -13,12 +13,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.systemui.biometrics
 
-import android.content.Context
-import android.util.AttributeSet
-import com.android.systemui.util.wrapper.LottieViewWrapper
+package com.android.systemui.qs.tiles.impl.colorcorrection.domain.model
 
-class SideFpsLottieViewWrapper
-@JvmOverloads
-constructor(context: Context, attrs: AttributeSet? = null) : LottieViewWrapper(context, attrs)
+/**
+ * Color correction tile model.
+ *
+ * @param isEnabled is true when the color correction is enabled;
+ */
+@JvmInline value class ColorCorrectionTileModel(val isEnabled: Boolean)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTilePackageUpdatesRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTilePackageUpdatesRepository.kt
index 6d7d88f..92b0f3a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTilePackageUpdatesRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTilePackageUpdatesRepository.kt
@@ -16,46 +16,103 @@
 
 package com.android.systemui.qs.tiles.impl.custom.data.repository
 
+import android.annotation.SuppressLint
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
 import android.os.UserHandle
+import androidx.annotation.GuardedBy
 import com.android.systemui.common.coroutine.ConflatedCallbackFlow
-import com.android.systemui.qs.external.TileServiceManager
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.qs.pipeline.shared.TileSpec
-import com.android.systemui.qs.tiles.impl.custom.di.bound.CustomTileBoundScope
-import com.android.systemui.qs.tiles.impl.custom.di.bound.CustomTileUser
+import com.android.systemui.qs.tiles.impl.di.QSTileScope
 import javax.inject.Inject
+import kotlin.coroutines.CoroutineContext
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.SharingStarted
-import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onCompletion
 import kotlinx.coroutines.flow.shareIn
+import kotlinx.coroutines.launch
 
 interface CustomTilePackageUpdatesRepository {
 
-    val packageChanges: Flow<Unit>
+    fun getPackageChangesForUser(user: UserHandle): Flow<Unit>
 }
 
-@CustomTileBoundScope
+@QSTileScope
 class CustomTilePackageUpdatesRepositoryImpl
 @Inject
 constructor(
-    tileSpec: TileSpec.CustomTileSpec,
-    @CustomTileUser user: UserHandle,
-    serviceManager: TileServiceManager,
-    defaultsRepository: CustomTileDefaultsRepository,
-    @CustomTileBoundScope boundScope: CoroutineScope,
+    private val tileSpec: TileSpec.CustomTileSpec,
+    @Application private val context: Context,
+    @QSTileScope private val tileScope: CoroutineScope,
+    @Background private val backgroundCoroutineContext: CoroutineContext,
 ) : CustomTilePackageUpdatesRepository {
 
-    override val packageChanges: Flow<Unit> =
-        ConflatedCallbackFlow.conflatedCallbackFlow {
-                serviceManager.setTileChangeListener { changedComponentName ->
-                    if (changedComponentName == tileSpec.componentName) {
-                        trySend(Unit)
-                    }
-                }
+    @GuardedBy("perUserCache")
+    private val perUserCache: MutableMap<UserHandle, Flow<Unit>> = mutableMapOf()
 
-                awaitClose { serviceManager.setTileChangeListener(null) }
+    override fun getPackageChangesForUser(user: UserHandle): Flow<Unit> =
+        synchronized(perUserCache) {
+            perUserCache.getOrPut(user) {
+                createPackageChangesFlowForUser(user)
+                    .onCompletion {
+                        // clear cache when nobody listens
+                        synchronized(perUserCache) { perUserCache.remove(user) }
+                    }
+                    .flowOn(backgroundCoroutineContext)
+                    .shareIn(tileScope, SharingStarted.WhileSubscribed())
             }
-            .onEach { defaultsRepository.requestNewDefaults(user, tileSpec.componentName, true) }
-            .shareIn(boundScope, SharingStarted.WhileSubscribed())
+        }
+
+    @SuppressLint(
+        "MissingPermission", // android.permission.INTERACT_ACROSS_USERS_FULL
+        "UnspecifiedRegisterReceiverFlag",
+        "RegisterReceiverViaContext",
+    )
+    private fun createPackageChangesFlowForUser(user: UserHandle): Flow<Unit> =
+        ConflatedCallbackFlow.conflatedCallbackFlow {
+                val receiver =
+                    object : BroadcastReceiver() {
+                        override fun onReceive(context: Context?, intent: Intent?) {
+                            launch { send(intent) }
+                        }
+                    }
+                context.registerReceiverAsUser(
+                    receiver,
+                    user,
+                    INTENT_FILTER,
+                    /* broadcastPermission = */ null,
+                    /* scheduler = */ null,
+                )
+
+                awaitClose { context.unregisterReceiver(receiver) }
+            }
+            .filter { intent ->
+                intent ?: return@filter false
+                if (intent.action?.let(INTENT_FILTER::matchAction) != true) {
+                    return@filter false
+                }
+                val changedComponentNames =
+                    intent.getStringArrayExtra(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST)
+                changedComponentNames?.contains(tileSpec.componentName.packageName) == true
+            }
+            .map {}
+
+    private companion object {
+
+        val INTENT_FILTER =
+            IntentFilter().apply {
+                addDataScheme(IntentFilter.SCHEME_PACKAGE)
+
+                addAction(Intent.ACTION_PACKAGE_CHANGED)
+            }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/di/CustomTileModule.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/di/CustomTileModule.kt
index d956fde..ba8b23a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/di/CustomTileModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/di/CustomTileModule.kt
@@ -19,6 +19,7 @@
 import com.android.systemui.qs.tiles.base.interactor.QSTileDataInteractor
 import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
 import com.android.systemui.qs.tiles.base.interactor.QSTileUserActionInteractor
+import com.android.systemui.qs.tiles.base.viewmodel.QSTileCoroutineScopeFactory
 import com.android.systemui.qs.tiles.impl.custom.CustomTileInteractor
 import com.android.systemui.qs.tiles.impl.custom.CustomTileMapper
 import com.android.systemui.qs.tiles.impl.custom.CustomTileUserActionInteractor
@@ -26,13 +27,15 @@
 import com.android.systemui.qs.tiles.impl.custom.data.repository.CustomTileDefaultsRepositoryImpl
 import com.android.systemui.qs.tiles.impl.custom.data.repository.CustomTileRepository
 import com.android.systemui.qs.tiles.impl.custom.data.repository.CustomTileRepositoryImpl
-import com.android.systemui.qs.tiles.impl.custom.di.bound.CustomTileBoundComponent
 import com.android.systemui.qs.tiles.impl.custom.domain.entity.CustomTileDataModel
+import com.android.systemui.qs.tiles.impl.di.QSTileScope
 import dagger.Binds
 import dagger.Module
+import dagger.Provides
+import kotlinx.coroutines.CoroutineScope
 
 /** Provides bindings for QSTile interfaces */
-@Module(subcomponents = [CustomTileBoundComponent::class])
+@Module
 interface CustomTileModule {
 
     @Binds
@@ -54,4 +57,13 @@
     ): CustomTileDefaultsRepository
 
     @Binds fun bindCustomTileRepository(impl: CustomTileRepositoryImpl): CustomTileRepository
+
+    companion object {
+
+        @Provides
+        @QSTileScope
+        fun provideCustomTileCoroutineScope(
+            scopeFactory: QSTileCoroutineScopeFactory
+        ): CoroutineScope = scopeFactory.create()
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/di/QSTileComponent.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/di/QSTileComponent.kt
index b3d916a..0ed46e7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/di/QSTileComponent.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/di/QSTileComponent.kt
@@ -19,6 +19,7 @@
 import com.android.systemui.qs.tiles.base.interactor.QSTileDataInteractor
 import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
 import com.android.systemui.qs.tiles.base.interactor.QSTileUserActionInteractor
+import kotlinx.coroutines.CoroutineScope
 
 /**
  * Base QS tile component. It should be used with [QSTileScope] to create a custom tile scoped
@@ -32,4 +33,12 @@
     fun userActionInteractor(): QSTileUserActionInteractor<T>
 
     fun dataToStateMapper(): QSTileDataToStateMapper<T>
+
+    /**
+     * Use [com.android.systemui.qs.tiles.base.viewmodel.QSTileCoroutineScopeFactory] to create a
+     * [CoroutineScope] provided by this method. This enables you to use the same scope the
+     * [com.android.systemui.qs.tiles.viewmodel.QSTileViewModel] uses. This scope is cancelled when
+     * the view model is destroyed.
+     */
+    @QSTileScope fun coroutineScope(): CoroutineScope
 }
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 881a6bd..1b3b584 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
@@ -17,6 +17,7 @@
 package com.android.systemui.qs.tiles.impl.flashlight.domain
 
 import android.content.res.Resources
+import android.content.res.Resources.Theme
 import com.android.systemui.common.shared.model.Icon
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
@@ -27,18 +28,25 @@
 import javax.inject.Inject
 
 /** Maps [FlashlightTileModel] to [QSTileState]. */
-class FlashlightMapper @Inject constructor(@Main private val resources: Resources) :
-    QSTileDataToStateMapper<FlashlightTileModel> {
+class FlashlightMapper
+@Inject
+constructor(
+    @Main private val resources: Resources,
+    private val theme: Theme,
+) : QSTileDataToStateMapper<FlashlightTileModel> {
 
     override fun map(config: QSTileConfig, data: FlashlightTileModel): QSTileState =
-        QSTileState.build(resources, config.uiConfig) {
+        QSTileState.build(resources, theme, config.uiConfig) {
             val icon =
-                Icon.Resource(
-                    if (data.isEnabled) {
-                        R.drawable.qs_flashlight_icon_on
-                    } else {
-                        R.drawable.qs_flashlight_icon_off
-                    },
+                Icon.Loaded(
+                    resources.getDrawable(
+                        if (data.isEnabled) {
+                            R.drawable.qs_flashlight_icon_on
+                        } else {
+                            R.drawable.qs_flashlight_icon_off
+                        },
+                        theme,
+                    ),
                     contentDescription = null
                 )
             this.icon = { icon }
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 7e7034d..fe5445d 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
@@ -17,6 +17,7 @@
 package com.android.systemui.qs.tiles.impl.location.domain
 
 import android.content.res.Resources
+import android.content.res.Resources.Theme
 import com.android.systemui.common.shared.model.Icon
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
@@ -27,18 +28,25 @@
 import javax.inject.Inject
 
 /** Maps [LocationTileModel] to [QSTileState]. */
-class LocationTileMapper @Inject constructor(@Main private val resources: Resources) :
-    QSTileDataToStateMapper<LocationTileModel> {
+class LocationTileMapper
+@Inject
+constructor(
+    @Main private val resources: Resources,
+    private val theme: Theme,
+) : QSTileDataToStateMapper<LocationTileModel> {
 
     override fun map(config: QSTileConfig, data: LocationTileModel): QSTileState =
-        QSTileState.build(resources, config.uiConfig) {
+        QSTileState.build(resources, theme, config.uiConfig) {
             val icon =
-                Icon.Resource(
-                    if (data.isEnabled) {
-                        R.drawable.qs_location_icon_on
-                    } else {
-                        R.drawable.qs_location_icon_off
-                    },
+                Icon.Loaded(
+                    resources.getDrawable(
+                        if (data.isEnabled) {
+                            R.drawable.qs_location_icon_on
+                        } else {
+                            R.drawable.qs_location_icon_off
+                        },
+                        theme,
+                    ),
                     contentDescription = null
                 )
             this.icon = { icon }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/DataSaverDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/DataSaverDialogDelegate.kt
new file mode 100644
index 0000000..fc42ba4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/DataSaverDialogDelegate.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.saver.domain
+
+import android.content.Context
+import android.content.DialogInterface
+import android.content.SharedPreferences
+import android.os.Bundle
+import com.android.internal.R
+import com.android.systemui.qs.tiles.impl.saver.domain.interactor.DataSaverTileUserActionInteractor
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import com.android.systemui.statusbar.policy.DataSaverController
+import kotlin.coroutines.CoroutineContext
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
+
+class DataSaverDialogDelegate(
+    private val sysuiDialogFactory: SystemUIDialog.Factory,
+    private val context: Context,
+    private val backgroundContext: CoroutineContext,
+    private val dataSaverController: DataSaverController,
+    private val sharedPreferences: SharedPreferences,
+) : SystemUIDialog.Delegate {
+    override fun createDialog(): SystemUIDialog {
+        return sysuiDialogFactory.create(this, context)
+    }
+
+    override fun onCreate(dialog: SystemUIDialog, savedInstanceState: Bundle?) {
+        with(dialog) {
+            setTitle(R.string.data_saver_enable_title)
+            setMessage(R.string.data_saver_description)
+            setPositiveButton(R.string.data_saver_enable_button) { _: DialogInterface?, _ ->
+                CoroutineScope(backgroundContext).launch {
+                    dataSaverController.setDataSaverEnabled(true)
+                }
+
+                sharedPreferences
+                    .edit()
+                    .putBoolean(DataSaverTileUserActionInteractor.DIALOG_SHOWN, true)
+                    .apply()
+            }
+            setNeutralButton(R.string.cancel, null)
+            setShowForAllUsers(true)
+        }
+    }
+}
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
new file mode 100644
index 0000000..df25600
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/DataSaverTileMapper.kt
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.saver.domain
+
+import android.content.res.Resources
+import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper
+import com.android.systemui.qs.tiles.impl.saver.domain.model.DataSaverTileModel
+import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
+import com.android.systemui.qs.tiles.viewmodel.QSTileState
+import com.android.systemui.res.R
+import javax.inject.Inject
+
+/** Maps [DataSaverTileModel] to [QSTileState]. */
+class DataSaverTileMapper
+@Inject
+constructor(
+    @Main private val resources: Resources,
+    private val theme: Resources.Theme,
+) : QSTileDataToStateMapper<DataSaverTileModel> {
+    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
+                    secondaryLabel = resources.getStringArray(R.array.tile_states_saver)[2]
+                } else {
+                    activationState = QSTileState.ActivationState.INACTIVE
+                    iconRes = R.drawable.qs_data_saver_icon_off
+                    secondaryLabel = resources.getStringArray(R.array.tile_states_saver)[1]
+                }
+                val loadedIcon =
+                    Icon.Loaded(resources.getDrawable(iconRes, theme), contentDescription = null)
+                icon = { loadedIcon }
+                contentDescription = label
+                supportedActions =
+                    setOf(QSTileState.UserAction.CLICK, QSTileState.UserAction.LONG_CLICK)
+            }
+        }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/interactor/DataSaverTileDataInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/interactor/DataSaverTileDataInteractor.kt
new file mode 100644
index 0000000..91e049b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/interactor/DataSaverTileDataInteractor.kt
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.saver.domain.interactor
+
+import android.os.UserHandle
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow
+import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
+import com.android.systemui.qs.tiles.base.interactor.QSTileDataInteractor
+import com.android.systemui.qs.tiles.impl.saver.domain.model.DataSaverTileModel
+import com.android.systemui.statusbar.policy.DataSaverController
+import javax.inject.Inject
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flowOf
+
+/** Observes data saver state changes providing the [DataSaverTileModel]. */
+class DataSaverTileDataInteractor
+@Inject
+constructor(
+    private val dataSaverController: DataSaverController,
+) : QSTileDataInteractor<DataSaverTileModel> {
+
+    override fun tileData(
+        user: UserHandle,
+        triggers: Flow<DataUpdateTrigger>
+    ): Flow<DataSaverTileModel> =
+        ConflatedCallbackFlow.conflatedCallbackFlow {
+            val initialValue = dataSaverController.isDataSaverEnabled
+            trySend(DataSaverTileModel(initialValue))
+
+            val callback = DataSaverController.Listener { trySend(DataSaverTileModel(it)) }
+
+            dataSaverController.addCallback(callback)
+            awaitClose { dataSaverController.removeCallback(callback) }
+        }
+
+    override fun availability(user: UserHandle): Flow<Boolean> = flowOf(true)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/interactor/DataSaverTileUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/interactor/DataSaverTileUserActionInteractor.kt
new file mode 100644
index 0000000..af74409
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/interactor/DataSaverTileUserActionInteractor.kt
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.saver.domain.interactor
+
+import android.content.Context
+import android.content.Intent
+import android.provider.Settings
+import com.android.internal.jank.InteractionJankMonitor
+import com.android.systemui.animation.DialogCuj
+import com.android.systemui.animation.DialogLaunchAnimator
+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.qs.tiles.base.actions.QSTileIntentUserInputHandler
+import com.android.systemui.qs.tiles.base.interactor.QSTileInput
+import com.android.systemui.qs.tiles.base.interactor.QSTileUserActionInteractor
+import com.android.systemui.qs.tiles.impl.saver.domain.DataSaverDialogDelegate
+import com.android.systemui.qs.tiles.impl.saver.domain.model.DataSaverTileModel
+import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
+import com.android.systemui.settings.UserFileManager
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import com.android.systemui.statusbar.policy.DataSaverController
+import javax.inject.Inject
+import kotlin.coroutines.CoroutineContext
+import kotlinx.coroutines.withContext
+
+/** Handles data saver tile clicks. */
+class DataSaverTileUserActionInteractor
+@Inject
+constructor(
+    @Application private val context: Context,
+    @Main private val coroutineContext: CoroutineContext,
+    @Background private val backgroundContext: CoroutineContext,
+    private val dataSaverController: DataSaverController,
+    private val qsTileIntentUserActionHandler: QSTileIntentUserInputHandler,
+    private val dialogLaunchAnimator: DialogLaunchAnimator,
+    private val systemUIDialogFactory: SystemUIDialog.Factory,
+    userFileManager: UserFileManager,
+) : QSTileUserActionInteractor<DataSaverTileModel> {
+    companion object {
+        private const val INTERACTION_JANK_TAG = "start_data_saver"
+        const val PREFS = "data_saver"
+        const val DIALOG_SHOWN = "data_saver_dialog_shown"
+    }
+
+    val sharedPreferences =
+        userFileManager.getSharedPreferences(PREFS, Context.MODE_PRIVATE, context.userId)
+
+    override suspend fun handleInput(input: QSTileInput<DataSaverTileModel>): Unit =
+        with(input) {
+            when (action) {
+                is QSTileUserAction.Click -> {
+                    val wasEnabled: Boolean = data.isEnabled
+                    if (wasEnabled || sharedPreferences.getBoolean(DIALOG_SHOWN, false)) {
+                        withContext(backgroundContext) {
+                            dataSaverController.setDataSaverEnabled(!wasEnabled)
+                        }
+                        return@with
+                    }
+                    // Show a dialog to confirm first. Dialogs shown by the DialogLaunchAnimator
+                    // must be created and shown on the main thread, so we post it to the UI
+                    // handler
+                    withContext(coroutineContext) {
+                        val dialogContext = action.view?.context ?: context
+                        val dialogDelegate =
+                            DataSaverDialogDelegate(
+                                systemUIDialogFactory,
+                                dialogContext,
+                                backgroundContext,
+                                dataSaverController,
+                                sharedPreferences
+                            )
+                        val dialog = systemUIDialogFactory.create(dialogDelegate, dialogContext)
+
+                        if (action.view != null) {
+                            dialogLaunchAnimator.showFromView(
+                                dialog,
+                                action.view!!,
+                                DialogCuj(
+                                    InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN,
+                                    INTERACTION_JANK_TAG
+                                )
+                            )
+                        } else {
+                            dialog.show()
+                        }
+                    }
+                }
+                is QSTileUserAction.LongClick -> {
+                    qsTileIntentUserActionHandler.handle(
+                        action.view,
+                        Intent(Settings.ACTION_DATA_SAVER_SETTINGS)
+                    )
+                }
+            }
+        }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsLottieViewWrapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/model/DataSaverTileModel.kt
similarity index 66%
copy from packages/SystemUI/src/com/android/systemui/biometrics/SideFpsLottieViewWrapper.kt
copy to packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/model/DataSaverTileModel.kt
index e98f6db..040c7bf 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsLottieViewWrapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/model/DataSaverTileModel.kt
@@ -13,12 +13,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.systemui.biometrics
 
-import android.content.Context
-import android.util.AttributeSet
-import com.android.systemui.util.wrapper.LottieViewWrapper
+package com.android.systemui.qs.tiles.impl.saver.domain.model
 
-class SideFpsLottieViewWrapper
-@JvmOverloads
-constructor(context: Context, attrs: AttributeSet? = null) : LottieViewWrapper(context, attrs)
+/**
+ * data saver tile model.
+ *
+ * @param isEnabled is true when the data saver is enabled;
+ */
+@JvmInline value class DataSaverTileModel(val isEnabled: Boolean)
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 3f30c75..ffef2b6 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
@@ -18,6 +18,7 @@
 
 import android.app.UiModeManager
 import android.content.res.Resources
+import android.content.res.Resources.Theme
 import android.text.TextUtils
 import com.android.systemui.common.shared.model.Icon
 import com.android.systemui.dagger.qualifiers.Main
@@ -31,15 +32,19 @@
 import javax.inject.Inject
 
 /** Maps [UiModeNightTileModel] to [QSTileState]. */
-class UiModeNightTileMapper @Inject constructor(@Main private val resources: Resources) :
-    QSTileDataToStateMapper<UiModeNightTileModel> {
+class UiModeNightTileMapper
+@Inject
+constructor(
+    @Main private val resources: Resources,
+    private val theme: Theme,
+) : QSTileDataToStateMapper<UiModeNightTileModel> {
     companion object {
         val formatter12Hour: DateTimeFormatter = DateTimeFormatter.ofPattern("hh:mm a")
         val formatter24Hour: DateTimeFormatter = DateTimeFormatter.ofPattern("HH:mm")
     }
     override fun map(config: QSTileConfig, data: UiModeNightTileModel): QSTileState =
         with(data) {
-            QSTileState.build(resources, config.uiConfig) {
+            QSTileState.build(resources, theme, config.uiConfig) {
                 var shouldSetSecondaryLabel = false
 
                 if (isPowerSave) {
@@ -116,8 +121,9 @@
                     if (activationState == QSTileState.ActivationState.ACTIVE)
                         R.drawable.qs_light_dark_theme_icon_on
                     else R.drawable.qs_light_dark_theme_icon_off
-                val iconResource = Icon.Resource(iconRes, null)
-                icon = { iconResource }
+                val loadedIcon =
+                    Icon.Loaded(resources.getDrawable(iconRes, theme), contentDescription = null)
+                icon = { loadedIcon }
 
                 supportedActions =
                     if (activationState == QSTileState.ActivationState.UNAVAILABLE)
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 23e0cb6..be1b740 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
@@ -17,6 +17,7 @@
 package com.android.systemui.qs.tiles.viewmodel
 
 import android.content.res.Resources
+import android.content.res.Resources.Theme
 import android.service.quicksettings.Tile
 import android.view.View
 import android.widget.Switch
@@ -47,14 +48,17 @@
 
         fun build(
             resources: Resources,
+            theme: Theme,
             config: QSTileUIConfig,
             build: Builder.() -> Unit
-        ): QSTileState =
-            build(
-                { Icon.Resource(config.iconRes, null) },
+        ): QSTileState {
+            val iconDrawable = resources.getDrawable(config.iconRes, theme)
+            return build(
+                { Icon.Loaded(iconDrawable, null) },
                 resources.getString(config.labelRes),
                 build,
             )
+        }
 
         fun build(icon: () -> Icon, label: CharSequence, build: Builder.() -> Unit): QSTileState =
             Builder(icon, label).apply(build).build()
diff --git a/packages/SystemUI/src/com/android/systemui/recordissue/RecordIssueDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/recordissue/RecordIssueDialogDelegate.kt
new file mode 100644
index 0000000..5bf44fa
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recordissue/RecordIssueDialogDelegate.kt
@@ -0,0 +1,113 @@
+/*
+ * 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.recordissue
+
+import android.annotation.SuppressLint
+import android.app.Activity
+import android.app.BroadcastOptions
+import android.app.PendingIntent
+import android.content.Context
+import android.content.res.ColorStateList
+import android.graphics.Color
+import android.os.Bundle
+import android.view.Gravity
+import android.view.LayoutInflater
+import android.view.WindowManager
+import android.widget.Button
+import android.widget.PopupMenu
+import android.widget.Switch
+import com.android.systemui.res.R
+import com.android.systemui.screenrecord.RecordingService
+import com.android.systemui.screenrecord.ScreenRecordingAudioSource
+import com.android.systemui.settings.UserContextProvider
+import com.android.systemui.statusbar.phone.SystemUIDialog
+
+class RecordIssueDialogDelegate(
+    private val factory: SystemUIDialog.Factory,
+    private val userContextProvider: UserContextProvider,
+    private val onStarted: Runnable
+) : SystemUIDialog.Delegate {
+
+    @SuppressLint("UseSwitchCompatOrMaterialCode") private lateinit var screenRecordSwitch: Switch
+    private lateinit var issueTypeButton: Button
+
+    override fun beforeCreate(dialog: SystemUIDialog, savedInstanceState: Bundle?) {
+        dialog.apply {
+            setView(LayoutInflater.from(context).inflate(R.layout.record_issue_dialog, null))
+            setTitle(context.getString(R.string.qs_record_issue_label))
+            setIcon(R.drawable.qs_record_issue_icon_off)
+            setNegativeButton(R.string.cancel) { _, _ -> dismiss() }
+            setPositiveButton(R.string.qs_record_issue_start) { _, _ ->
+                onStarted.run()
+                if (screenRecordSwitch.isChecked) {
+                    requestScreenCapture()
+                }
+                dismiss()
+            }
+        }
+    }
+
+    override fun createDialog(): SystemUIDialog = factory.create(this)
+
+    override fun onCreate(dialog: SystemUIDialog, savedInstanceState: Bundle?) {
+        dialog.apply {
+            window?.addPrivateFlags(WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS)
+            window?.setGravity(Gravity.CENTER)
+
+            screenRecordSwitch = requireViewById(R.id.screenrecord_switch)
+            issueTypeButton = requireViewById(R.id.issue_type_button)
+            issueTypeButton.setOnClickListener { onIssueTypeClicked(context) }
+        }
+    }
+
+    private fun onIssueTypeClicked(context: Context) {
+        val selectedCategory = issueTypeButton.text.toString()
+        val popupMenu = PopupMenu(context, issueTypeButton)
+
+        context.resources.getStringArray(R.array.qs_record_issue_types).forEachIndexed { i, cat ->
+            popupMenu.menu.add(0, 0, i, cat).apply {
+                setIcon(R.drawable.arrow_pointing_down)
+                if (selectedCategory != cat) {
+                    iconTintList = ColorStateList.valueOf(Color.TRANSPARENT)
+                }
+            }
+        }
+        popupMenu.apply {
+            setOnMenuItemClickListener {
+                issueTypeButton.text = it.title
+                true
+            }
+            setForceShowIcon(true)
+            show()
+        }
+    }
+
+    private fun requestScreenCapture() =
+        PendingIntent.getForegroundService(
+                userContextProvider.userContext,
+                RecordingService.REQUEST_CODE,
+                RecordingService.getStartIntent(
+                    userContextProvider.userContext,
+                    Activity.RESULT_OK,
+                    ScreenRecordingAudioSource.NONE.ordinal,
+                    false,
+                    null
+                ),
+                PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
+            )
+            .send(BroadcastOptions.makeBasic().apply { isInteractive = true }.toBundle())
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recordissue/RecordIssueModule.kt b/packages/SystemUI/src/com/android/systemui/recordissue/RecordIssueModule.kt
new file mode 100644
index 0000000..d67cf4d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recordissue/RecordIssueModule.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recordissue
+
+import com.android.systemui.qs.tileimpl.QSTileImpl
+import com.android.systemui.qs.tiles.RecordIssueTile
+import dagger.Binds
+import dagger.Module
+import dagger.multibindings.IntoMap
+import dagger.multibindings.StringKey
+
+@Module
+interface RecordIssueModule {
+    /** Inject RecordIssueTile into tileMap in QSModule */
+    @Binds
+    @IntoMap
+    @StringKey(RecordIssueTile.TILE_SPEC)
+    fun bindRecordIssueTile(recordIssueTile: RecordIssueTile): QSTileImpl<*>
+}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
index d42fde6..47518bb 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
@@ -44,6 +44,11 @@
 import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE
 import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED
 import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING
+import com.android.systemui.statusbar.notification.stack.shared.flexiNotifsEnabled
+import com.android.systemui.util.asIndenting
+import com.android.systemui.util.printSection
+import com.android.systemui.util.println
+import java.io.PrintWriter
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -94,6 +99,15 @@
         }
     }
 
+    override fun dump(pw: PrintWriter, args: Array<out String>) =
+        pw.asIndenting().run {
+            printSection("SceneContainerFlags") {
+                println("isEnabled", flags.isEnabled())
+                printSection("requirementDescription") { println(flags.requirementDescription()) }
+                println("flexiNotifsEnabled", flags.flexiNotifsEnabled())
+            }
+        }
+
     /** Updates the visibility of the scene container. */
     private fun hydrateVisibility() {
         applicationScope.launch {
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt
index dbb58a3..1156250 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt
@@ -31,6 +31,7 @@
 import com.android.systemui.flags.ResourceBooleanFlag
 import com.android.systemui.flags.UnreleasedFlag
 import com.android.systemui.keyguard.shared.KeyguardShadeMigrationNssl
+import com.android.systemui.media.controls.util.MediaInSceneContainerFlag
 import com.android.systemui.res.R
 import dagger.Module
 import dagger.Provides
@@ -82,6 +83,10 @@
                 flagName = KeyguardShadeMigrationNssl.FLAG_NAME,
                 flagValue = KeyguardShadeMigrationNssl.isEnabled,
             ),
+            AconfigFlagMustBeEnabled(
+                flagName = MediaInSceneContainerFlag.FLAG_NAME,
+                flagValue = MediaInSceneContainerFlag.isEnabled,
+            ),
         ) +
             classicFlagTokens.map { flagToken -> FlagMustBeEnabled(flagToken) } +
             listOf(
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
index c885492..c43d20c 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
@@ -35,6 +35,8 @@
 import com.android.systemui.Gefingerpoken;
 import com.android.systemui.res.R;
 
+import java.util.Collections;
+
 /**
  * {@code FrameLayout} used to show and manipulate a {@link ToggleSeekBar}.
  *
@@ -48,6 +50,7 @@
     @Nullable
     private Drawable mProgressDrawable;
     private float mScale = 1f;
+    private final Rect mSystemGestureExclusionRect = new Rect();
 
     public BrightnessSliderView(Context context) {
         this(context, null);
@@ -176,6 +179,11 @@
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
         applySliderScale();
+        int horizontalMargin =
+                getResources().getDimensionPixelSize(R.dimen.notification_side_paddings);
+        mSystemGestureExclusionRect.set(-horizontalMargin, 0, right - left + horizontalMargin,
+                bottom - top);
+        setSystemGestureExclusionRects(Collections.singletonList(mSystemGestureExclusionRect));
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
index e9779cd..5fbb60d 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
@@ -59,6 +59,7 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.res.R;
+import com.android.systemui.scene.shared.flag.SceneContainerFlags;
 import com.android.systemui.scene.ui.view.WindowRootViewComponent;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.shade.domain.interactor.ShadeInteractor;
@@ -116,6 +117,7 @@
     private final AuthController mAuthController;
     private final Lazy<SelectedUserInteractor> mUserInteractor;
     private final Lazy<ShadeInteractor> mShadeInteractorLazy;
+    private final SceneContainerFlags mSceneContainerFlags;
     private ViewGroup mWindowRootView;
     private LayoutParams mLp;
     private boolean mHasTopUi;
@@ -162,7 +164,8 @@
             Lazy<ShadeInteractor> shadeInteractorLazy,
             ShadeWindowLogger logger,
             Lazy<SelectedUserInteractor> userInteractor,
-            UserTracker userTracker) {
+            UserTracker userTracker,
+            SceneContainerFlags sceneContainerFlags) {
         mContext = context;
         mWindowRootViewComponentFactory = windowRootViewComponentFactory;
         mWindowManager = windowManager;
@@ -180,6 +183,7 @@
         dumpManager.registerDumpable(this);
         mAuthController = authController;
         mUserInteractor = userInteractor;
+        mSceneContainerFlags = sceneContainerFlags;
         mLastKeyguardRotationAllowed = mKeyguardStateController.isKeyguardScreenRotationAllowed();
         mLockScreenDisplayTimeout = context.getResources()
                 .getInteger(R.integer.config_lockScreenDisplayTimeout);
@@ -287,6 +291,15 @@
         mLp.privateFlags |= PRIVATE_FLAG_BEHAVIOR_CONTROLLED;
         mLp.insetsFlags.behavior = BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
 
+        if (mSceneContainerFlags.isEnabled()) {
+            // This prevents the appearance and disappearance of the software keyboard (also known
+            // as the "IME") from scrolling/panning the window to make room for the keyboard.
+            //
+            // The scene container logic does its own adjustment and animation when the IME appears
+            // or disappears.
+            mLp.softInputMode = LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
+        }
+
         mWindowManager.addView(mWindowRootView, mLp);
 
         mLpChanged.copyFrom(mLp);
diff --git a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
index dd194eaa..8397caa 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
@@ -794,13 +794,6 @@
 
     /** update Qs height state */
     public void setExpansionHeight(float height) {
-        // TODO(b/277909752): remove below log when bug is fixed
-        if (mSplitShadeEnabled && mShadeExpandedFraction == 1.0f && height == 0
-                && mBarState == SHADE) {
-            Log.wtf(TAG,
-                    "setting QS height to 0 in split shade while shade is open(ing). "
-                            + "Value of isExpandImmediate() = " + isExpandImmediate());
-        }
         int maxHeight = getMaxExpansionHeight();
         height = Math.min(Math.max(
                 height, getMinExpansionHeight()), maxHeight);
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt
index 8a93ef6..d3459b1 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt
@@ -32,6 +32,7 @@
  * TODO(b/200063118): Make this class the one source of truth for the state of panel expansion.
  */
 @SysUISingleton
+@Deprecated("Use ShadeInteractor instead")
 class ShadeExpansionStateManager @Inject constructor() {
 
     private val expansionListeners = CopyOnWriteArrayList<ShadeExpansionListener>()
@@ -49,6 +50,7 @@
      *
      * @see #addExpansionListener
      */
+    @Deprecated("Use ShadeInteractor instead")
     fun addExpansionListener(listener: ShadeExpansionListener): ShadeExpansionChangeEvent {
         expansionListeners.add(listener)
         return ShadeExpansionChangeEvent(fraction, expanded, tracking, dragDownPxAmount)
@@ -60,6 +62,7 @@
     }
 
     /** Adds a listener that will be notified when the panel state has changed. */
+    @Deprecated("Use ShadeInteractor instead")
     fun addStateListener(listener: ShadeStateListener) {
         stateListeners.add(listener)
     }
diff --git a/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt b/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt
index e94a3eb..2445bdb 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt
@@ -15,25 +15,14 @@
  */
 package com.android.systemui.shade.data.repository
 
-import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
-import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.shade.ShadeExpansionChangeEvent
-import com.android.systemui.shade.ShadeExpansionListener
-import com.android.systemui.shade.ShadeExpansionStateManager
-import com.android.systemui.shade.domain.model.ShadeModel
 import javax.inject.Inject
-import kotlinx.coroutines.channels.awaitClose
-import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.asStateFlow
-import kotlinx.coroutines.flow.distinctUntilChanged
 
+/** Data for the shade, mostly related to expansion of the shade and quick settings. */
 interface ShadeRepository {
-    /** ShadeModel information regarding shade expansion events */
-    val shadeModel: Flow<ShadeModel>
-
     /**
      * Amount qs has expanded, [0-1]. 0 means fully collapsed, 1 means fully expanded. Quick
      * Settings can be expanded without the full shade expansion.
@@ -167,34 +156,7 @@
 
 /** Business logic for shade interactions */
 @SysUISingleton
-class ShadeRepositoryImpl
-@Inject
-constructor(shadeExpansionStateManager: ShadeExpansionStateManager) : ShadeRepository {
-    override val shadeModel: Flow<ShadeModel> =
-        conflatedCallbackFlow {
-                val callback =
-                    object : ShadeExpansionListener {
-                        override fun onPanelExpansionChanged(event: ShadeExpansionChangeEvent) {
-                            // Don't propagate ShadeExpansionChangeEvent.dragDownPxAmount field.
-                            // It is too noisy and produces extra events that consumers won't care
-                            // about
-                            val info =
-                                ShadeModel(
-                                    expansionAmount = event.fraction,
-                                    isExpanded = event.expanded,
-                                    isUserDragging = event.tracking
-                                )
-                            trySendWithFailureLogging(info, TAG, "updated shade expansion info")
-                        }
-                    }
-
-                val currentState = shadeExpansionStateManager.addExpansionListener(callback)
-                callback.onPanelExpansionChanged(currentState)
-
-                awaitClose { shadeExpansionStateManager.removeExpansionListener(callback) }
-            }
-            .distinctUntilChanged()
-
+class ShadeRepositoryImpl @Inject constructor() : ShadeRepository {
     private val _qsExpansion = MutableStateFlow(0f)
     override val qsExpansion: StateFlow<Float> = _qsExpansion.asStateFlow()
 
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/model/ShadeModel.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/model/ShadeModel.kt
deleted file mode 100644
index ce0f4283..0000000
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/model/ShadeModel.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-package com.android.systemui.shade.domain.model
-
-import android.annotation.FloatRange
-
-/** Information about shade (NotificationPanel) expansion */
-data class ShadeModel(
-    /** 0 when collapsed, 1 when fully expanded. */
-    @FloatRange(from = 0.0, to = 1.0) val expansionAmount: Float = 0f,
-    /** Whether the panel should be considered expanded */
-    val isExpanded: Boolean = false,
-    /** Whether the user is actively dragging the panel. */
-    val isUserDragging: Boolean = false,
-)
diff --git a/packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceModule.kt b/packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceModule.kt
index c59ef26..d26fded1 100644
--- a/packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceModule.kt
@@ -59,6 +59,11 @@
          * The BcSmartspaceDataPlugin for the standalone weather.
          */
         const val WEATHER_SMARTSPACE_DATA_PLUGIN = "weather_smartspace_data_plugin"
+
+        /**
+         * The BcSmartspaceDataProvider for the glanceable hub.
+         */
+        const val GLANCEABLE_HUB_SMARTSPACE_DATA_PLUGIN = "glanceable_hub_smartspace_data_plugin"
     }
 
     @BindsOptionalOf
@@ -78,4 +83,8 @@
     abstract fun bindSmartspacePrecondition(
         lockscreenPrecondition: LockscreenPrecondition?
     ): SmartspacePrecondition?
+
+    @BindsOptionalOf
+    @Named(GLANCEABLE_HUB_SMARTSPACE_DATA_PLUGIN)
+    abstract fun optionalBcSmartspaceDataPlugin(): BcSmartspaceDataPlugin?
 }
diff --git a/packages/SystemUI/src/com/android/systemui/smartspace/data/repository/SmartspaceRepository.kt b/packages/SystemUI/src/com/android/systemui/smartspace/data/repository/SmartspaceRepository.kt
index 2fc0ec2..095d30e 100644
--- a/packages/SystemUI/src/com/android/systemui/smartspace/data/repository/SmartspaceRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/smartspace/data/repository/SmartspaceRepository.kt
@@ -19,9 +19,9 @@
 import android.app.smartspace.SmartspaceTarget
 import android.os.Parcelable
 import android.widget.RemoteViews
+import com.android.systemui.communal.smartspace.CommunalSmartspaceController
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.plugins.BcSmartspaceDataPlugin
-import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController
 import javax.inject.Inject
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
@@ -32,37 +32,37 @@
     /** Whether [RemoteViews] are passed through smartspace targets. */
     val isSmartspaceRemoteViewsEnabled: Boolean
 
-    /** Smartspace targets for the lockscreen surface. */
-    val lockscreenSmartspaceTargets: Flow<List<SmartspaceTarget>>
+    /** Smartspace targets for the communal surface. */
+    val communalSmartspaceTargets: Flow<List<SmartspaceTarget>>
 }
 
 @SysUISingleton
 class SmartspaceRepositoryImpl
 @Inject
 constructor(
-    private val lockscreenSmartspaceController: LockscreenSmartspaceController,
+    private val communalSmartspaceController: CommunalSmartspaceController,
 ) : SmartspaceRepository, BcSmartspaceDataPlugin.SmartspaceTargetListener {
 
     override val isSmartspaceRemoteViewsEnabled: Boolean
         get() = android.app.smartspace.flags.Flags.remoteViews()
 
-    private val _lockscreenSmartspaceTargets: MutableStateFlow<List<SmartspaceTarget>> =
+    private val _communalSmartspaceTargets: MutableStateFlow<List<SmartspaceTarget>> =
         MutableStateFlow(emptyList())
-    override val lockscreenSmartspaceTargets: Flow<List<SmartspaceTarget>> =
-        _lockscreenSmartspaceTargets
+    override val communalSmartspaceTargets: Flow<List<SmartspaceTarget>> =
+        _communalSmartspaceTargets
             .onStart {
-                lockscreenSmartspaceController.addListener(listener = this@SmartspaceRepositoryImpl)
+                communalSmartspaceController.addListener(listener = this@SmartspaceRepositoryImpl)
             }
             .onCompletion {
-                lockscreenSmartspaceController.removeListener(
+                communalSmartspaceController.removeListener(
                     listener = this@SmartspaceRepositoryImpl
                 )
             }
 
     override fun onSmartspaceTargetsUpdated(targetsNullable: MutableList<out Parcelable>?) {
         targetsNullable?.let { targets ->
-            _lockscreenSmartspaceTargets.value = targets.filterIsInstance<SmartspaceTarget>()
+            _communalSmartspaceTargets.value = targets.filterIsInstance<SmartspaceTarget>()
         }
-            ?: run { _lockscreenSmartspaceTargets.value = emptyList() }
+            ?: run { _communalSmartspaceTargets.value = emptyList() }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
index faffb3e..cfbd015 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
@@ -18,17 +18,17 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.os.Handler;
-import android.os.SystemClock;
 import android.util.ArrayMap;
 import android.util.ArraySet;
+import android.util.Log;
 import android.view.accessibility.AccessibilityEvent;
 
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
 import com.android.systemui.statusbar.policy.HeadsUpManagerLogger;
+import com.android.systemui.util.concurrency.DelayableExecutor;
+import com.android.systemui.util.time.SystemClock;
 
 import java.util.stream.Stream;
 
@@ -39,20 +39,21 @@
  */
 public abstract class AlertingNotificationManager {
     private static final String TAG = "AlertNotifManager";
-    protected final Clock mClock = new Clock();
+    protected final SystemClock mSystemClock;
     protected final ArrayMap<String, AlertEntry> mAlertEntries = new ArrayMap<>();
     protected final HeadsUpManagerLogger mLogger;
 
-    public AlertingNotificationManager(HeadsUpManagerLogger logger, @Main Handler handler) {
-        mLogger = logger;
-        mHandler = handler;
-    }
-
     protected int mMinimumDisplayTime;
-    protected int mStickyDisplayTime;
-    protected int mAutoDismissNotificationDecay;
-    @VisibleForTesting
-    public Handler mHandler;
+    protected int mStickyForSomeTimeAutoDismissTime;
+    protected int mAutoDismissTime;
+    private DelayableExecutor mExecutor;
+
+    public AlertingNotificationManager(HeadsUpManagerLogger logger,
+            SystemClock systemClock, @Main DelayableExecutor executor) {
+        mLogger = logger;
+        mExecutor = executor;
+        mSystemClock = systemClock;
+    }
 
     /**
      * Called when posting a new notification that should alert the user and appear on screen.
@@ -251,7 +252,7 @@
     public long getEarliestRemovalTime(String key) {
         AlertEntry alerting = mAlertEntries.get(key);
         if (alerting != null) {
-            return Math.max(0, alerting.mEarliestRemovaltime - mClock.currentTimeMillis());
+            return Math.max(0, alerting.mEarliestRemovalTime - mSystemClock.elapsedRealtime());
         }
         return 0;
     }
@@ -259,9 +260,10 @@
     protected class AlertEntry implements Comparable<AlertEntry> {
         @Nullable public NotificationEntry mEntry;
         public long mPostTime;
-        public long mEarliestRemovaltime;
+        public long mEarliestRemovalTime;
 
         @Nullable protected Runnable mRemoveAlertRunnable;
+        @Nullable private Runnable mCancelRemoveAlertRunnable;
 
         public void setEntry(@NonNull final NotificationEntry entry) {
             setEntry(entry, () -> removeAlertEntry(entry.getKey()));
@@ -283,19 +285,21 @@
         public void updateEntry(boolean updatePostTime, @Nullable String reason) {
             mLogger.logUpdateEntry(mEntry, updatePostTime, reason);
 
-            final long now = mClock.currentTimeMillis();
-            mEarliestRemovaltime = now + mMinimumDisplayTime;
+            final long now = mSystemClock.elapsedRealtime();
+            mEarliestRemovalTime = now + mMinimumDisplayTime;
 
             if (updatePostTime) {
                 mPostTime = Math.max(mPostTime, now);
             }
-            removeAutoRemovalCallbacks("updateEntry (will be rescheduled)");
 
-            if (!isSticky()) {
-                final long finishTime = calculateFinishTime();
-                final long timeLeft = Math.max(finishTime - now, mMinimumDisplayTime);
-                mHandler.postDelayed(mRemoveAlertRunnable, timeLeft);
+            if (isSticky()) {
+                removeAutoRemovalCallbacks("updateEntry (sticky)");
+                return;
             }
+
+            final long finishTime = calculateFinishTime();
+            final long timeLeft = Math.max(finishTime - now, mMinimumDisplayTime);
+            scheduleAutoRemovalCallback(timeLeft, "updateEntry (not sticky)");
         }
 
         /**
@@ -318,7 +322,7 @@
          * @return true if the notification has been on screen long enough
          */
         public boolean wasShownLongEnough() {
-            return mEarliestRemovaltime < mClock.currentTimeMillis();
+            return mEarliestRemovalTime < mSystemClock.elapsedRealtime();
         }
 
         @Override
@@ -338,21 +342,50 @@
          * Clear any pending removal runnables.
          */
         public void removeAutoRemovalCallbacks(@Nullable String reason) {
-            if (mRemoveAlertRunnable != null) {
+            final boolean removed = removeAutoRemovalCallbackInternal();
+
+            if (removed) {
                 mLogger.logAutoRemoveCanceled(mEntry, reason);
-                mHandler.removeCallbacks(mRemoveAlertRunnable);
             }
         }
 
+        private void scheduleAutoRemovalCallback(long delayMillis, @NonNull String reason) {
+            if (mRemoveAlertRunnable == null) {
+                Log.wtf(TAG, "scheduleAutoRemovalCallback with no callback set");
+                return;
+            }
+
+            final boolean removed = removeAutoRemovalCallbackInternal();
+
+            if (removed) {
+                mLogger.logAutoRemoveRescheduled(mEntry, delayMillis, reason);
+            } else {
+                mLogger.logAutoRemoveScheduled(mEntry, delayMillis, reason);
+            }
+
+
+            mCancelRemoveAlertRunnable = mExecutor.executeDelayed(mRemoveAlertRunnable,
+                    delayMillis);
+        }
+
+        private boolean removeAutoRemovalCallbackInternal() {
+            final boolean scheduled = (mCancelRemoveAlertRunnable != null);
+
+            if (scheduled) {
+                mCancelRemoveAlertRunnable.run();
+                mCancelRemoveAlertRunnable = null;
+            }
+
+            return scheduled;
+        }
+
         /**
          * Remove the alert at the earliest allowed removal time.
          */
         public void removeAsSoonAsPossible() {
             if (mRemoveAlertRunnable != null) {
-                removeAutoRemovalCallbacks("removeAsSoonAsPossible (will be rescheduled)");
-
-                final long timeLeft = mEarliestRemovaltime - mClock.currentTimeMillis();
-                mHandler.postDelayed(mRemoveAlertRunnable, timeLeft);
+                final long timeLeft = mEarliestRemovalTime - mSystemClock.elapsedRealtime();
+                scheduleAutoRemovalCallback(timeLeft, "removeAsSoonAsPossible");
             }
         }
 
@@ -361,22 +394,16 @@
          * @return the post time
          */
         protected long calculatePostTime() {
-            return mClock.currentTimeMillis();
+            return mSystemClock.elapsedRealtime();
         }
 
         /**
          * @return When the notification should auto-dismiss itself, based on
-         * {@link SystemClock#elapsedRealTime()}
+         * {@link SystemClock#elapsedRealtime()}
          */
         protected long calculateFinishTime() {
             // Overridden by HeadsUpManager HeadsUpEntry #calculateFinishTime
             return 0;
         }
     }
-
-    protected final static class Clock {
-        public long currentTimeMillis() {
-            return SystemClock.elapsedRealtime();
-        }
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index e486457..05c3839 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -18,6 +18,7 @@
 import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
 import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS;
 import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS;
+import static android.os.UserHandle.USER_ALL;
 import static android.os.UserHandle.USER_NULL;
 import static android.provider.Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS;
 import static android.provider.Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS;
@@ -46,6 +47,7 @@
 import android.os.UserManager;
 import android.provider.Settings;
 import android.util.Log;
+import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
 
@@ -155,8 +157,22 @@
 
             if (ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) {
                 if (mFeatureFlags.isEnabled(Flags.NOTIF_LS_BACKGROUND_THREAD)) {
-                    boolean changed = updateDpcSettings(getSendingUserId());
-                    if (mCurrentUserId == getSendingUserId()) {
+                    boolean changed = false;
+                    int sendingUserId = getSendingUserId();
+                    if (sendingUserId == USER_ALL) {
+                        // When a Device Owner triggers changes it's sent as USER_ALL. Normalize
+                        // the user before calling into DPM
+                        sendingUserId = mCurrentUserId;
+                        @SuppressLint("MissingPermission")
+                        List<UserInfo> users = mUserManager.getUsers();
+                        for (int i = users.size() - 1; i >= 0; i--) {
+                            changed |= updateDpcSettings(users.get(i).id);
+                        }
+                    } else {
+                        changed |= updateDpcSettings(sendingUserId);
+                    }
+
+                    if (mCurrentUserId == sendingUserId) {
                         changed |= updateLockscreenNotificationSetting();
                     }
                     if (changed) {
@@ -374,13 +390,13 @@
         mContext.getContentResolver().registerContentObserver(
                 SHOW_LOCKSCREEN, false,
                 mLockscreenSettingsObserver,
-                UserHandle.USER_ALL);
+                USER_ALL);
 
         mContext.getContentResolver().registerContentObserver(
                 SHOW_PRIVATE_LOCKSCREEN,
                 true,
                 mLockscreenSettingsObserver,
-                UserHandle.USER_ALL);
+                USER_ALL);
 
         if (!mFeatureFlags.isEnabled(Flags.NOTIF_LS_BACKGROUND_THREAD)) {
             mContext.getContentResolver().registerContentObserver(
@@ -441,7 +457,7 @@
 
     public boolean isCurrentProfile(int userId) {
         synchronized (mLock) {
-            return userId == UserHandle.USER_ALL || mCurrentProfiles.get(userId) != null;
+            return userId == USER_ALL || mCurrentProfiles.get(userId) != null;
         }
     }
 
@@ -526,7 +542,7 @@
      */
     public boolean userAllowsPrivateNotificationsInPublic(int userHandle) {
         if (mFeatureFlags.isEnabled(Flags.NOTIF_LS_BACKGROUND_THREAD)) {
-            if (userHandle == UserHandle.USER_ALL) {
+            if (userHandle == USER_ALL) {
                 userHandle = mCurrentUserId;
             }
             if (mUsersUsersAllowingPrivateNotifications.indexOfKey(userHandle) < 0) {
@@ -540,7 +556,7 @@
             return mUsersUsersAllowingPrivateNotifications.get(userHandle)
                     && mUsersDpcAllowingPrivateNotifications.get(userHandle);
         } else {
-            if (userHandle == UserHandle.USER_ALL) {
+            if (userHandle == USER_ALL) {
                 return true;
             }
 
@@ -574,7 +590,7 @@
     }
 
     private boolean adminAllowsKeyguardFeature(int userHandle, int feature) {
-        if (userHandle == UserHandle.USER_ALL) {
+        if (userHandle == USER_ALL) {
             return true;
         }
         final int dpmFlags =
@@ -591,7 +607,7 @@
     }
 
     public boolean isLockscreenPublicMode(int userId) {
-        if (userId == UserHandle.USER_ALL) {
+        if (userId == USER_ALL) {
             return mLockscreenPublicMode.get(mCurrentUserId, false);
         }
         return mLockscreenPublicMode.get(userId, false);
@@ -610,7 +626,7 @@
         if (mFeatureFlags.isEnabled(Flags.NOTIF_LS_BACKGROUND_THREAD)) {
             // Unlike 'show private', settings does not show a copy of this setting for each
             // profile, so it inherits from the parent user.
-            if (userHandle == UserHandle.USER_ALL || mCurrentManagedProfiles.contains(userHandle)) {
+            if (userHandle == USER_ALL || mCurrentManagedProfiles.contains(userHandle)) {
                 userHandle = mCurrentUserId;
             }
             if (mUsersUsersAllowingNotifications.indexOfKey(userHandle) < 0) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/AccessPointController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/AccessPointController.kt
index 490994d..fc474d2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/AccessPointController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/AccessPointController.kt
@@ -89,5 +89,12 @@
          * "wifi_start_connect_ssid" set as an extra
          */
         fun onSettingsActivityTriggered(settingsIntent: Intent?)
+
+        /**
+         * Called whenever a Wi-Fi scan is triggered.
+         *
+         * @param isScan Whether Wi-Fi scan is triggered or not.
+         */
+        fun onWifiScan(isScan: Boolean)
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImpl.java
index 91ca148..3a31851 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImpl.java
@@ -213,6 +213,12 @@
         }
     }
 
+    private void fireWifiScanCallback(boolean isScan) {
+        for (AccessPointCallback callback : mCallbacks) {
+            callback.onWifiScan(isScan);
+        }
+    }
+
     void dump(PrintWriter pw) {
         IndentingPrintWriter ipw = new IndentingPrintWriter(pw);
         ipw.println("AccessPointControllerImpl:");
@@ -240,6 +246,14 @@
     }
 
     @Override
+    public void onWifiEntriesChanged(@WifiPickerTracker.WifiEntriesChangedReason int reason) {
+        onWifiEntriesChanged();
+        if (reason == WifiPickerTracker.WIFI_ENTRIES_CHANGED_REASON_SCAN_RESULTS) {
+            fireWifiScanCallback(false /* isScan */);
+        }
+    }
+
+    @Override
     public void onNumSavedNetworksChanged() {
         // Do nothing
     }
@@ -249,6 +263,11 @@
         // Do nothing
     }
 
+    @Override
+    public void onScanRequested() {
+        fireWifiScanCallback(true /* isScan */);
+    }
+
     private final WifiEntry.ConnectCallback mConnectCallback = new WifiEntry.ConnectCallback() {
         @Override
         public void onConnectResult(int status) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ConnectivityModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ConnectivityModule.kt
index a3adea0..642eacc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ConnectivityModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ConnectivityModule.kt
@@ -35,6 +35,10 @@
 import com.android.systemui.qs.tiles.impl.airplane.domain.interactor.AirplaneModeTileDataInteractor
 import com.android.systemui.qs.tiles.impl.airplane.domain.interactor.AirplaneModeTileUserActionInteractor
 import com.android.systemui.qs.tiles.impl.airplane.domain.model.AirplaneModeTileModel
+import com.android.systemui.qs.tiles.impl.saver.domain.DataSaverTileMapper
+import com.android.systemui.qs.tiles.impl.saver.domain.interactor.DataSaverTileDataInteractor
+import com.android.systemui.qs.tiles.impl.saver.domain.interactor.DataSaverTileUserActionInteractor
+import com.android.systemui.qs.tiles.impl.saver.domain.model.DataSaverTileModel
 import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
 import com.android.systemui.qs.tiles.viewmodel.QSTilePolicy
 import com.android.systemui.qs.tiles.viewmodel.QSTileUIConfig
@@ -85,6 +89,7 @@
     companion object {
 
         const val AIRPLANE_MODE_TILE_SPEC = "airplane"
+        const val DATA_SAVER_TILE_SPEC = "saver"
 
         /** Inject InternetTile or InternetTileNewImpl into tileMap in QSModule */
         @Provides
@@ -132,5 +137,36 @@
                 stateInteractor,
                 mapper,
             )
+
+        @Provides
+        @IntoMap
+        @StringKey(DATA_SAVER_TILE_SPEC)
+        fun provideDataSaverTileConfig(uiEventLogger: QsEventLogger): QSTileConfig =
+            QSTileConfig(
+                tileSpec = TileSpec.create(DATA_SAVER_TILE_SPEC),
+                uiConfig =
+                    QSTileUIConfig.Resource(
+                        iconRes = R.drawable.qs_data_saver_icon_off,
+                        labelRes = R.string.data_saver,
+                    ),
+                instanceId = uiEventLogger.getNewInstanceId(),
+            )
+
+        /** Inject DataSaverTile into tileViewModelMap in QSModule */
+        @Provides
+        @IntoMap
+        @StringKey(DATA_SAVER_TILE_SPEC)
+        fun provideDataSaverTileViewModel(
+            factory: QSTileViewModelFactory.Static<DataSaverTileModel>,
+            mapper: DataSaverTileMapper,
+            stateInteractor: DataSaverTileDataInteractor,
+            userActionInteractor: DataSaverTileUserActionInteractor
+        ): QSTileViewModel =
+            factory.create(
+                TileSpec.create(DATA_SAVER_TILE_SPEC),
+                userActionInteractor,
+                stateInteractor,
+                mapper,
+            )
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt
index 22912df..85f4c36 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt
@@ -20,6 +20,7 @@
 import com.android.systemui.statusbar.data.StatusBarDataLayerModule
 import com.android.systemui.statusbar.phone.LightBarController
 import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController
+import com.android.systemui.statusbar.ui.SystemBarUtilsProxyImpl
 import dagger.Binds
 import dagger.Module
 import dagger.multibindings.ClassKey
@@ -33,7 +34,7 @@
  *   ([com.android.systemui.statusbar.pipeline.dagger.StatusBarPipelineModule],
  *   [com.android.systemui.statusbar.policy.dagger.StatusBarPolicyModule], etc.).
  */
-@Module(includes = [StatusBarDataLayerModule::class])
+@Module(includes = [StatusBarDataLayerModule::class, SystemBarUtilsProxyImpl.Module::class])
 abstract class StatusBarModule {
     @Binds
     @IntoMap
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt
index ecca973..e1e30e1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt
@@ -17,12 +17,13 @@
 
 import android.graphics.Color
 import android.graphics.Rect
+import android.util.Log
 import android.view.View
+import android.view.ViewGroup
 import android.widget.FrameLayout
 import androidx.annotation.ColorInt
 import androidx.collection.ArrayMap
 import androidx.lifecycle.lifecycleScope
-import com.android.internal.policy.SystemBarUtils
 import com.android.internal.statusbar.StatusBarIcon
 import com.android.internal.util.ContrastColorUtil
 import com.android.systemui.common.ui.ConfigurationState
@@ -39,10 +40,8 @@
 import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconsViewData
 import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconsViewData.LimitType
 import com.android.systemui.statusbar.phone.NotificationIconContainer
-import com.android.systemui.statusbar.policy.ConfigurationController
-import com.android.systemui.statusbar.policy.onConfigChanged
+import com.android.systemui.statusbar.ui.SystemBarUtilsState
 import com.android.systemui.util.kotlin.mapValuesNotNullTo
-import com.android.systemui.util.kotlin.stateFlow
 import com.android.systemui.util.ui.isAnimating
 import com.android.systemui.util.ui.stopAnimating
 import com.android.systemui.util.ui.value
@@ -51,7 +50,6 @@
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.coroutineScope
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.mapNotNull
 import kotlinx.coroutines.launch
@@ -59,20 +57,20 @@
 /** Binds a view-model to a [NotificationIconContainer]. */
 object NotificationIconContainerViewBinder {
     @JvmStatic
-    fun bind(
+    fun bindWhileAttached(
         view: NotificationIconContainer,
         viewModel: NotificationIconContainerShelfViewModel,
         configuration: ConfigurationState,
-        configurationController: ConfigurationController,
+        systemBarUtilsState: SystemBarUtilsState,
         failureTracker: StatusBarIconViewBindingFailureTracker,
-        viewStore: ShelfNotificationIconViewStore,
+        viewStore: IconViewStore,
     ): DisposableHandle {
         return view.repeatWhenAttached {
             lifecycleScope.launch {
                 viewModel.icons.bindIcons(
                     view,
                     configuration,
-                    configurationController,
+                    systemBarUtilsState,
                     notifyBindingFailures = { failureTracker.shelfFailures = it },
                     viewStore,
                 )
@@ -81,68 +79,89 @@
     }
 
     @JvmStatic
-    fun bind(
+    fun bindWhileAttached(
         view: NotificationIconContainer,
         viewModel: NotificationIconContainerStatusBarViewModel,
         configuration: ConfigurationState,
-        configurationController: ConfigurationController,
+        systemBarUtilsState: SystemBarUtilsState,
         failureTracker: StatusBarIconViewBindingFailureTracker,
-        viewStore: StatusBarNotificationIconViewStore,
-    ): DisposableHandle {
-        val contrastColorUtil = ContrastColorUtil.getInstance(view.context)
-        return view.repeatWhenAttached {
-            lifecycleScope.run {
-                launch {
-                    val iconColors: Flow<NotificationIconColors> =
-                        viewModel.iconColors.mapNotNull { it.iconColors(view.viewBounds) }
-                    viewModel.icons.bindIcons(
-                        view,
-                        configuration,
-                        configurationController,
-                        notifyBindingFailures = { failureTracker.statusBarFailures = it },
-                        viewStore,
-                    ) { _, sbiv ->
-                        StatusBarIconViewBinder.bindIconColors(
-                            sbiv,
-                            iconColors,
-                            contrastColorUtil,
-                        )
-                    }
-                }
-                launch { viewModel.bindIsolatedIcon(view, viewStore) }
-                launch { viewModel.animationsEnabled.bindAnimationsEnabled(view) }
+        viewStore: IconViewStore,
+    ): DisposableHandle =
+        view.repeatWhenAttached {
+            lifecycleScope.launch {
+                bind(view, viewModel, configuration, systemBarUtilsState, failureTracker, viewStore)
             }
         }
+
+    suspend fun bind(
+        view: NotificationIconContainer,
+        viewModel: NotificationIconContainerStatusBarViewModel,
+        configuration: ConfigurationState,
+        systemBarUtilsState: SystemBarUtilsState,
+        failureTracker: StatusBarIconViewBindingFailureTracker,
+        viewStore: IconViewStore,
+    ): Unit = coroutineScope {
+        launch {
+            val contrastColorUtil = ContrastColorUtil.getInstance(view.context)
+            val iconColors: Flow<NotificationIconColors> =
+                viewModel.iconColors.mapNotNull { it.iconColors(view.viewBounds) }
+            viewModel.icons.bindIcons(
+                view,
+                configuration,
+                systemBarUtilsState,
+                notifyBindingFailures = { failureTracker.statusBarFailures = it },
+                viewStore,
+            ) { _, sbiv ->
+                StatusBarIconViewBinder.bindIconColors(
+                    sbiv,
+                    iconColors,
+                    contrastColorUtil,
+                )
+            }
+        }
+        launch { viewModel.bindIsolatedIcon(view, viewStore) }
+        launch { viewModel.animationsEnabled.bindAnimationsEnabled(view) }
     }
 
     @JvmStatic
-    fun bind(
+    fun bindWhileAttached(
         view: NotificationIconContainer,
         viewModel: NotificationIconContainerAlwaysOnDisplayViewModel,
         configuration: ConfigurationState,
-        configurationController: ConfigurationController,
+        systemBarUtilsState: SystemBarUtilsState,
         failureTracker: StatusBarIconViewBindingFailureTracker,
         viewStore: IconViewStore,
     ): DisposableHandle {
         return view.repeatWhenAttached {
             lifecycleScope.launch {
-                view.setUseIncreasedIconScale(true)
-                launch {
-                    viewModel.icons.bindIcons(
-                        view,
-                        configuration,
-                        configurationController,
-                        notifyBindingFailures = { failureTracker.aodFailures = it },
-                        viewStore,
-                    ) { _, sbiv ->
-                        viewModel.bindAodStatusBarIconView(sbiv, configuration)
-                    }
-                }
-                launch { viewModel.areContainerChangesAnimated.bindAnimationsEnabled(view) }
+                bind(view, viewModel, configuration, systemBarUtilsState, failureTracker, viewStore)
             }
         }
     }
 
+    suspend fun bind(
+        view: NotificationIconContainer,
+        viewModel: NotificationIconContainerAlwaysOnDisplayViewModel,
+        configuration: ConfigurationState,
+        systemBarUtilsState: SystemBarUtilsState,
+        failureTracker: StatusBarIconViewBindingFailureTracker,
+        viewStore: IconViewStore,
+    ): Unit = coroutineScope {
+        view.setUseIncreasedIconScale(true)
+        launch {
+            viewModel.icons.bindIcons(
+                view,
+                configuration,
+                systemBarUtilsState,
+                notifyBindingFailures = { failureTracker.aodFailures = it },
+                viewStore,
+            ) { _, sbiv ->
+                viewModel.bindAodStatusBarIconView(sbiv, configuration)
+            }
+        }
+        launch { viewModel.areContainerChangesAnimated.bindAnimationsEnabled(view) }
+    }
+
     private suspend fun NotificationIconContainerAlwaysOnDisplayViewModel.bindAodStatusBarIconView(
         sbiv: StatusBarIconView,
         configuration: ConfigurationState,
@@ -199,29 +218,40 @@
     private suspend fun Flow<NotificationIconsViewData>.bindIcons(
         view: NotificationIconContainer,
         configuration: ConfigurationState,
-        configurationController: ConfigurationController,
+        systemBarUtilsState: SystemBarUtilsState,
         notifyBindingFailures: (Collection<String>) -> Unit,
         viewStore: IconViewStore,
         bindIcon: suspend (iconKey: String, view: StatusBarIconView) -> Unit = { _, _ -> },
-    ): Unit = coroutineScope {
+    ) {
         val iconSizeFlow: Flow<Int> =
             configuration.getDimensionPixelSize(
                 com.android.internal.R.dimen.status_bar_icon_size_sp,
             )
         val iconHorizontalPaddingFlow: Flow<Int> =
             configuration.getDimensionPixelSize(R.dimen.status_bar_icon_horizontal_margin)
-        val statusBarHeightFlow: StateFlow<Int> =
-            stateFlow(changedSignals = configurationController.onConfigChanged) {
-                SystemBarUtils.getStatusBarHeight(view.context)
-            }
         val layoutParams: Flow<FrameLayout.LayoutParams> =
-            combine(iconSizeFlow, iconHorizontalPaddingFlow, statusBarHeightFlow) {
+            combine(iconSizeFlow, iconHorizontalPaddingFlow, systemBarUtilsState.statusBarHeight) {
                 iconSize,
                 iconHPadding,
                 statusBarHeight,
                 ->
                 FrameLayout.LayoutParams(iconSize + 2 * iconHPadding, statusBarHeight)
             }
+        try {
+            bindIcons(view, layoutParams, notifyBindingFailures, viewStore, bindIcon)
+        } finally {
+            // Detach everything so that child SBIVs don't hold onto a reference to the container.
+            view.detachAllIcons()
+        }
+    }
+
+    private suspend fun Flow<NotificationIconsViewData>.bindIcons(
+        view: NotificationIconContainer,
+        layoutParams: Flow<FrameLayout.LayoutParams>,
+        notifyBindingFailures: (Collection<String>) -> Unit,
+        viewStore: IconViewStore,
+        bindIcon: suspend (iconKey: String, view: StatusBarIconView) -> Unit,
+    ): Unit = coroutineScope {
         val failedBindings = mutableSetOf<String>()
         val boundViewsByNotifKey = ArrayMap<String, Pair<StatusBarIconView, Job>>()
         var prevIcons = NotificationIconsViewData()
@@ -253,9 +283,17 @@
                         continue
                     }
                     failedBindings.remove(notifKey)
-                    // The view might still be transiently added if it was just removed and added
-                    // again
-                    view.removeTransientView(sbiv)
+                    (sbiv.parent as? ViewGroup)?.run {
+                        if (this !== view) {
+                            Log.wtf(TAG, "StatusBarIconView($notifKey) has an unexpected parent")
+                        }
+                        // If the container was re-inflated and re-bound, then SBIVs might still be
+                        // attached to the prior view.
+                        removeView(sbiv)
+                        // The view might still be transiently added if it was just removed and
+                        // added again.
+                        removeTransientView(sbiv)
+                    }
                     view.addView(sbiv, idx)
                     boundViewsByNotifKey.remove(notifKey)?.second?.cancel()
                     boundViewsByNotifKey[notifKey] =
@@ -338,7 +376,8 @@
         fun iconView(key: String): StatusBarIconView?
     }
 
-    @ColorInt private val DEFAULT_AOD_ICON_COLOR = Color.WHITE
+    @ColorInt private const val DEFAULT_AOD_ICON_COLOR = Color.WHITE
+    private const val TAG =  "NotifIconContainerViewBinder"
 }
 
 /** [IconViewStore] for the [com.android.systemui.statusbar.NotificationShelf] */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderWrapper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderWrapper.kt
index 16bcd43d..bd3a71c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderWrapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderWrapper.kt
@@ -15,6 +15,7 @@
  */
 package com.android.systemui.statusbar.notification.interruption
 
+import com.android.app.tracing.traceSection
 import com.android.internal.annotations.VisibleForTesting
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.flags.RefactorFlagUtils
@@ -82,20 +83,33 @@
     }
 
     override fun makeUnloggedHeadsUpDecision(entry: NotificationEntry): Decision =
-        wrapped.checkHeadsUp(entry, /* log= */ false).let { DecisionImpl.of(it) }
+        traceSection("NotificationInterruptStateProviderWrapper#makeUnloggedHeadsUpDecision") {
+            wrapped.checkHeadsUp(entry, /* log= */ false).let { DecisionImpl.of(it) }
+        }
 
     override fun makeAndLogHeadsUpDecision(entry: NotificationEntry): Decision =
-        wrapped.checkHeadsUp(entry, /* log= */ true).let { DecisionImpl.of(it) }
+        traceSection("NotificationInterruptStateProviderWrapper#makeAndLogHeadsUpDecision") {
+            wrapped.checkHeadsUp(entry, /* log= */ true).let { DecisionImpl.of(it) }
+        }
 
     override fun makeUnloggedFullScreenIntentDecision(entry: NotificationEntry) =
-        wrapped.getFullScreenIntentDecision(entry).let { FullScreenIntentDecisionImpl(entry, it) }
-
-    override fun logFullScreenIntentDecision(decision: FullScreenIntentDecision) {
-        (decision as FullScreenIntentDecisionImpl).let {
-            wrapped.logFullScreenIntentDecision(it.originalEntry, it.originalDecision)
+        traceSection(
+            "NotificationInterruptStateProviderWrapper#makeUnloggedFullScreenIntentDecision"
+        ) {
+            wrapped.getFullScreenIntentDecision(entry).let {
+                FullScreenIntentDecisionImpl(entry, it)
+            }
         }
-    }
+
+    override fun logFullScreenIntentDecision(decision: FullScreenIntentDecision) =
+        traceSection("NotificationInterruptStateProviderWrapper#logFullScreenIntentDecision") {
+            (decision as FullScreenIntentDecisionImpl).let {
+                wrapped.logFullScreenIntentDecision(it.originalEntry, it.originalDecision)
+            }
+        }
 
     override fun makeAndLogBubbleDecision(entry: NotificationEntry): Decision =
-        wrapped.shouldBubbleUp(entry).let { DecisionImpl.of(it) }
+        traceSection("NotificationInterruptStateProviderWrapper#makeAndLogBubbleDecision") {
+            wrapped.shouldBubbleUp(entry).let { DecisionImpl.of(it) }
+        }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImpl.kt
index 73dd5f6..6878a1e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImpl.kt
@@ -19,6 +19,7 @@
 import android.os.Handler
 import android.os.PowerManager
 import android.util.Log
+import com.android.app.tracing.traceSection
 import com.android.internal.annotations.VisibleForTesting
 import com.android.internal.logging.UiEventLogger
 import com.android.internal.logging.UiEventLogger.UiEventEnum
@@ -196,27 +197,29 @@
         filters.remove(filter)
     }
 
-    override fun makeUnloggedHeadsUpDecision(entry: NotificationEntry): Decision {
-        check(started)
+    override fun makeUnloggedHeadsUpDecision(entry: NotificationEntry): Decision =
+        traceSection("VisualInterruptionDecisionProviderImpl#makeUnloggedHeadsUpDecision") {
+            check(started)
 
-        return if (statusBarStateController.isDozing) {
-                makeLoggablePulseDecision(entry)
-            } else {
-                makeLoggablePeekDecision(entry)
-            }
-            .decision
-    }
+            return if (statusBarStateController.isDozing) {
+                    makeLoggablePulseDecision(entry)
+                } else {
+                    makeLoggablePeekDecision(entry)
+                }
+                .decision
+        }
 
-    override fun makeAndLogHeadsUpDecision(entry: NotificationEntry): Decision {
-        check(started)
+    override fun makeAndLogHeadsUpDecision(entry: NotificationEntry): Decision =
+        traceSection("VisualInterruptionDecisionProviderImpl#makeAndLogHeadsUpDecision") {
+            check(started)
 
-        return if (statusBarStateController.isDozing) {
-                makeLoggablePulseDecision(entry).also { logDecision(PULSE, entry, it) }
-            } else {
-                makeLoggablePeekDecision(entry).also { logDecision(PEEK, entry, it) }
-            }
-            .decision
-    }
+            return if (statusBarStateController.isDozing) {
+                    makeLoggablePulseDecision(entry).also { logDecision(PULSE, entry, it) }
+                } else {
+                    makeLoggablePeekDecision(entry).also { logDecision(PEEK, entry, it) }
+                }
+                .decision
+        }
 
     private fun makeLoggablePeekDecision(entry: NotificationEntry): LoggableDecision =
         checkConditions(PEEK)
@@ -229,11 +232,14 @@
             ?: checkFilters(PULSE, entry) ?: checkSuppressInterruptions(entry)
                 ?: LoggableDecision.unsuppressed
 
-    override fun makeAndLogBubbleDecision(entry: NotificationEntry): Decision {
-        check(started)
+    override fun makeAndLogBubbleDecision(entry: NotificationEntry): Decision =
+        traceSection("VisualInterruptionDecisionProviderImpl#makeAndLogBubbleDecision") {
+            check(started)
 
-        return makeLoggableBubbleDecision(entry).also { logDecision(BUBBLE, entry, it) }.decision
-    }
+            return makeLoggableBubbleDecision(entry)
+                .also { logDecision(BUBBLE, entry, it) }
+                .decision
+        }
 
     private fun makeLoggableBubbleDecision(entry: NotificationEntry): LoggableDecision =
         checkConditions(BUBBLE)
@@ -251,38 +257,42 @@
 
     override fun makeUnloggedFullScreenIntentDecision(
         entry: NotificationEntry
-    ): FullScreenIntentDecision {
-        check(started)
+    ): FullScreenIntentDecision =
+        traceSection(
+            "VisualInterruptionDecisionProviderImpl#makeUnloggedFullScreenIntentDecision"
+        ) {
+            check(started)
 
-        val couldHeadsUp = makeUnloggedHeadsUpDecision(entry).shouldInterrupt
-        val fsiDecision =
-            fullScreenIntentDecisionProvider.makeFullScreenIntentDecision(entry, couldHeadsUp)
-        return FullScreenIntentDecisionImpl(entry, fsiDecision)
-    }
-
-    override fun logFullScreenIntentDecision(decision: FullScreenIntentDecision) {
-        check(started)
-
-        if (decision !is FullScreenIntentDecisionImpl) {
-            Log.wtf(TAG, "FSI decision $decision was not created by this class")
-            return
+            val couldHeadsUp = makeUnloggedHeadsUpDecision(entry).shouldInterrupt
+            val fsiDecision =
+                fullScreenIntentDecisionProvider.makeFullScreenIntentDecision(entry, couldHeadsUp)
+            return FullScreenIntentDecisionImpl(entry, fsiDecision)
         }
 
-        if (decision.hasBeenLogged) {
-            Log.wtf(TAG, "FSI decision $decision has already been logged")
-            return
+    override fun logFullScreenIntentDecision(decision: FullScreenIntentDecision) =
+        traceSection("VisualInterruptionDecisionProviderImpl#logFullScreenIntentDecision") {
+            check(started)
+
+            if (decision !is FullScreenIntentDecisionImpl) {
+                Log.wtf(TAG, "FSI decision $decision was not created by this class")
+                return
+            }
+
+            if (decision.hasBeenLogged) {
+                Log.wtf(TAG, "FSI decision $decision has already been logged")
+                return
+            }
+
+            decision.hasBeenLogged = true
+
+            if (!decision.shouldLog) {
+                return
+            }
+
+            logger.logFullScreenIntentDecision(decision.entry, decision, decision.isWarning)
+            logEvents(decision.entry, decision)
         }
 
-        decision.hasBeenLogged = true
-
-        if (!decision.shouldLog) {
-            return
-        }
-
-        logger.logFullScreenIntentDecision(decision.entry, decision, decision.isWarning)
-        logEvents(decision.entry, decision)
-    }
-
     private fun logEvents(entry: NotificationEntry, loggable: Loggable) {
         loggable.uiEventId?.let { uiEventLogger.log(it, entry.sbn.uid, entry.sbn.packageName) }
         loggable.eventLogData?.let {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/ui/viewbinder/NotificationShelfViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/ui/viewbinder/NotificationShelfViewBinder.kt
index 5cdead4..699e140 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/ui/viewbinder/NotificationShelfViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/ui/viewbinder/NotificationShelfViewBinder.kt
@@ -29,7 +29,7 @@
 import com.android.systemui.statusbar.notification.shared.NotificationIconContainerRefactor
 import com.android.systemui.statusbar.notification.shelf.ui.viewmodel.NotificationShelfViewModel
 import com.android.systemui.statusbar.phone.NotificationIconAreaController
-import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.statusbar.ui.SystemBarUtilsState
 import kotlinx.coroutines.awaitCancellation
 import kotlinx.coroutines.launch
 
@@ -39,7 +39,7 @@
         shelf: NotificationShelf,
         viewModel: NotificationShelfViewModel,
         configuration: ConfigurationState,
-        configurationController: ConfigurationController,
+        systemBarUtilsState: SystemBarUtilsState,
         falsingManager: FalsingManager,
         iconViewBindingFailureTracker: StatusBarIconViewBindingFailureTracker,
         notificationIconAreaController: NotificationIconAreaController,
@@ -48,11 +48,11 @@
         ActivatableNotificationViewBinder.bind(viewModel, shelf, falsingManager)
         shelf.apply {
             if (NotificationIconContainerRefactor.isEnabled) {
-                NotificationIconContainerViewBinder.bind(
+                NotificationIconContainerViewBinder.bindWhileAttached(
                     shelfIcons,
                     viewModel.icons,
                     configuration,
-                    configurationController,
+                    systemBarUtilsState,
                     iconViewBindingFailureTracker,
                     shelfIconViewStore,
                 )
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationStackAppearanceRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationStackAppearanceRepository.kt
index abf09ae..e78a694 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationStackAppearanceRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationStackAppearanceRepository.kt
@@ -26,5 +26,8 @@
 @SysUISingleton
 class NotificationStackAppearanceRepository @Inject constructor() {
     /** The bounds of the notification stack in the current scene. */
-    val stackBounds = MutableStateFlow(NotificationContainerBounds(0f, 0f))
+    val stackBounds = MutableStateFlow(NotificationContainerBounds())
+
+    /** The corner radius of the notification stack, in dp. */
+    val cornerRadiusDp = MutableStateFlow(32f)
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractor.kt
index 32e4e89..61a4dfc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractor.kt
@@ -39,4 +39,7 @@
         check(bounds.top <= bounds.bottom) { "Invalid bounds: $bounds" }
         repository.stackBounds.value = bounds
     }
+
+    /** The corner radius of the notification stack, in dp. */
+    val cornerRadiusDp: StateFlow<Float> = repository.cornerRadiusDp.asStateFlow()
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractor.kt
index c2c5eed..625fdc1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractor.kt
@@ -20,6 +20,8 @@
 import android.content.Context
 import com.android.systemui.common.ui.data.repository.ConfigurationRepository
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.res.R
 import com.android.systemui.statusbar.policy.SplitShadeStateController
 import javax.inject.Inject
@@ -28,6 +30,7 @@
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.asSharedFlow
 import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.onStart
@@ -39,7 +42,9 @@
 constructor(
     configurationRepository: ConfigurationRepository,
     private val context: Context,
-    private val splitShadeStateController: SplitShadeStateController
+    private val splitShadeStateController: SplitShadeStateController,
+    keyguardInteractor: KeyguardInteractor,
+    deviceEntryUdfpsInteractor: DeviceEntryUdfpsInteractor,
 ) {
 
     private val _topPosition = MutableStateFlow(0f)
@@ -68,11 +73,26 @@
                         marginTop = getDimensionPixelSize(R.dimen.notification_panel_margin_top),
                         marginTopLargeScreen =
                             getDimensionPixelSize(R.dimen.large_screen_shade_header_height),
+                        keyguardSplitShadeTopMargin =
+                            getDimensionPixelSize(R.dimen.keyguard_split_shade_top_margin),
                     )
                 }
             }
             .distinctUntilChanged()
 
+    /**
+     * The notification shelf can extend over the lock icon area if:
+     * * UDFPS supported. Ambient indication will always appear below
+     * * UDFPS not supported and ambient indication not visible, which will appear above lock icon
+     */
+    val useExtraShelfSpace: Flow<Boolean> =
+        combine(
+            keyguardInteractor.ambientIndicationVisible,
+            deviceEntryUdfpsInteractor.isUdfpsSupported,
+        ) { ambientIndicationVisible, isUdfpsSupported ->
+            isUdfpsSupported || !ambientIndicationVisible
+        }
+
     val isSplitShadeEnabled: Flow<Boolean> =
         configurationBasedDimensions
             .map { dimens: ConfigurationBasedDimensions -> dimens.useSplitShade }
@@ -95,5 +115,6 @@
         val marginBottom: Int,
         val marginTop: Int,
         val marginTopLargeScreen: Int,
+        val keyguardSplitShadeTopMargin: Int,
     )
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationListViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationListViewBinder.kt
index a4e1a9c..9373d49 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationListViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationListViewBinder.kt
@@ -40,7 +40,7 @@
 import com.android.systemui.statusbar.notification.stack.ui.viewbinder.HideNotificationsBinder.bindHideList
 import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationListViewModel
 import com.android.systemui.statusbar.phone.NotificationIconAreaController
-import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.statusbar.ui.SystemBarUtilsState
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.flow.combine
@@ -53,12 +53,12 @@
     private val viewModel: NotificationListViewModel,
     @Background private val backgroundDispatcher: CoroutineDispatcher,
     private val configuration: ConfigurationState,
-    private val configurationController: ConfigurationController,
     private val falsingManager: FalsingManager,
     private val iconAreaController: NotificationIconAreaController,
     private val iconViewBindingFailureTracker: StatusBarIconViewBindingFailureTracker,
     private val metricsLogger: MetricsLogger,
     private val shelfIconViewStore: ShelfNotificationIconViewStore,
+    private val systemBarUtilsState: SystemBarUtilsState,
 ) {
 
     fun bind(
@@ -91,7 +91,7 @@
             shelf,
             viewModel.shelf,
             configuration,
-            configurationController,
+            systemBarUtilsState,
             falsingManager,
             iconViewBindingFailureTracker,
             iconAreaController,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationStackAppearanceViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationStackAppearanceViewBinder.kt
index fa7a8fd..a9b542d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationStackAppearanceViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationStackAppearanceViewBinder.kt
@@ -16,14 +16,16 @@
 
 package com.android.systemui.statusbar.notification.stack.ui.viewbinder
 
+import android.content.Context
+import android.util.TypedValue
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.repeatOnLifecycle
 import com.android.systemui.lifecycle.repeatWhenAttached
-import com.android.systemui.scene.shared.flag.SceneContainerFlags
 import com.android.systemui.statusbar.notification.stack.AmbientState
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
 import com.android.systemui.statusbar.notification.stack.ui.view.SharedNotificationContainer
 import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationStackAppearanceViewModel
+import kotlin.math.roundToInt
 import kotlinx.coroutines.launch
 
 /** Binds the shared notification container to its view-model. */
@@ -31,9 +33,9 @@
 
     @JvmStatic
     fun bind(
+        context: Context,
         view: SharedNotificationContainer,
         viewModel: NotificationStackAppearanceViewModel,
-        sceneContainerFlags: SceneContainerFlags,
         ambientState: AmbientState,
         controller: NotificationStackScrollLayoutController,
     ) {
@@ -45,6 +47,14 @@
                             bounds.top,
                             controller.isAddOrRemoveAnimationPending
                         )
+                        controller.setRoundedClippingBounds(
+                            it.left,
+                            it.top,
+                            it.right,
+                            it.bottom,
+                            viewModel.cornerRadiusDp.value.dpToPx(context),
+                            viewModel.cornerRadiusDp.value.dpToPx(context),
+                        )
                     }
                 }
                 launch {
@@ -56,4 +66,13 @@
             }
         }
     }
+
+    private fun Float.dpToPx(context: Context): Int {
+        return TypedValue.applyDimension(
+                TypedValue.COMPLEX_UNIT_DIP,
+                this,
+                context.resources.displayMetrics
+            )
+            .roundToInt()
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt
index af56a3f..12927b8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt
@@ -101,12 +101,13 @@
 
                     launch {
                         viewModel
-                            .getMaxNotifications { space ->
+                            .getMaxNotifications { space, extraShelfSpace ->
+                                val shelfHeight = controller.getShelfHeight().toFloat()
                                 notificationStackSizeCalculator.computeMaxKeyguardNotifications(
                                     controller.getView(),
                                     space,
-                                    0f, // Vertical space for shelf is already accounted for
-                                    controller.getShelfHeight().toFloat(),
+                                    if (extraShelfSpace) shelfHeight else 0f,
+                                    shelfHeight,
                                 )
                             }
                             .collect { controller.setMaxDisplayedNotifications(it) }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationStackAppearanceViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationStackAppearanceViewModel.kt
index f4c0e92..834d3ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationStackAppearanceViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationStackAppearanceViewModel.kt
@@ -23,6 +23,7 @@
 import com.android.systemui.statusbar.notification.stack.domain.interactor.NotificationStackAppearanceInteractor
 import javax.inject.Inject
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.StateFlow
 
 /** ViewModel which represents the state of the NSSL/Controller in the world of flexiglass */
 @SysUISingleton
@@ -37,4 +38,7 @@
 
     /** The bounds of the notification stack in the current scene. */
     val stackBounds: Flow<NotificationContainerBounds> = stackAppearanceInteractor.stackBounds
+
+    /** The corner radius of the notification stack, in dp. */
+    val cornerRadiusDp: StateFlow<Float> = stackAppearanceInteractor.cornerRadiusDp
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt
index c6fd98e..9f22118 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationsPlaceholderViewModel.kt
@@ -24,6 +24,7 @@
 import com.android.systemui.statusbar.notification.stack.domain.interactor.NotificationStackAppearanceInteractor
 import com.android.systemui.statusbar.notification.stack.shared.flexiNotifsEnabled
 import javax.inject.Inject
+import kotlinx.coroutines.flow.StateFlow
 
 /**
  * ViewModel used by the Notification placeholders inside the scene container to update the
@@ -55,9 +56,14 @@
      *   pixels.
      */
     fun onBoundsChanged(
+        left: Float,
         top: Float,
+        right: Float,
         bottom: Float,
     ) {
-        interactor.setStackBounds(NotificationContainerBounds(top, bottom))
+        interactor.setStackBounds(NotificationContainerBounds(left, top, right, bottom))
     }
+
+    /** The corner radius of the placeholder, in dp. */
+    val cornerRadiusDp: StateFlow<Float> = interactor.cornerRadiusDp
 }
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 b0f1038..eff91e5 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
@@ -83,6 +83,14 @@
                     marginTop =
                         if (it.useLargeScreenHeader) it.marginTopLargeScreen else it.marginTop,
                     useSplitShade = it.useSplitShade,
+                    paddingTop =
+                        if (it.useSplitShade) {
+                            // When in split shade, the margin is applied twice as the legacy shade
+                            // code uses it to calculate padding.
+                            it.keyguardSplitShadeTopMargin - 2 * it.marginTopLargeScreen
+                        } else {
+                            0
+                        }
                 )
             }
             .distinctUntilChanged()
@@ -156,11 +164,7 @@
                 ),
             ) { onLockscreen, bounds, config, (top, isInTransitionToAnyState, qsExpansion) ->
                 if (onLockscreen) {
-                    if (config.useSplitShade) {
-                        bounds.copy(top = 0f)
-                    } else {
-                        bounds
-                    }
+                    bounds.copy(top = bounds.top + config.paddingTop)
                 } else {
                     // When QS expansion > 0, it should directly set the top padding so do not
                     // animate it
@@ -173,8 +177,8 @@
             }
             .stateIn(
                 scope = applicationScope,
-                started = SharingStarted.WhileSubscribed(),
-                initialValue = NotificationContainerBounds(0f, 0f),
+                started = SharingStarted.Lazily,
+                initialValue = NotificationContainerBounds(),
             )
 
     val alpha: Flow<Float> =
@@ -225,7 +229,7 @@
      * When expanding or when the user is interacting with the shade, keep the count stable; do not
      * emit a value.
      */
-    fun getMaxNotifications(calculateSpace: (Float) -> Int): Flow<Int> {
+    fun getMaxNotifications(calculateSpace: (Float, Boolean) -> Int): Flow<Int> {
         val showLimitedNotifications = isOnLockscreenWithoutShade
         val showUnlimitedNotifications =
             combine(
@@ -241,11 +245,17 @@
                 shadeInteractor.isUserInteracting,
                 bounds,
                 interactor.notificationStackChanged.onStart { emit(Unit) },
-            ) { showLimitedNotifications, showUnlimitedNotifications, isUserInteracting, bounds, _
-                ->
+                interactor.useExtraShelfSpace,
+            ) { flows ->
+                val showLimitedNotifications = flows[0] as Boolean
+                val showUnlimitedNotifications = flows[1] as Boolean
+                val isUserInteracting = flows[2] as Boolean
+                val bounds = flows[3] as NotificationContainerBounds
+                val useExtraShelfSpace = flows[5] as Boolean
+
                 if (!isUserInteracting) {
                     if (showLimitedNotifications) {
-                        emit(calculateSpace(bounds.bottom - bounds.top))
+                        emit(calculateSpace(bounds.bottom - bounds.top, useExtraShelfSpace))
                     } else if (showUnlimitedNotifications) {
                         emit(-1)
                     }
@@ -268,5 +278,6 @@
         val marginEnd: Int,
         val marginBottom: Int,
         val useSplitShade: Boolean,
+        val paddingTop: Int,
     )
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index 4e77801..97fc35a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -47,7 +47,6 @@
 import com.android.systemui.biometrics.AuthController;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.deviceentry.domain.interactor.DeviceEntryHapticsInteractor;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
@@ -180,8 +179,6 @@
     private final SystemClock mSystemClock;
     private final boolean mOrderUnlockAndWake;
     private final Lazy<SelectedUserInteractor> mSelectedUserInteractor;
-    private final DeviceEntryHapticsInteractor mHapticsInteractor;
-
     private long mLastFpFailureUptimeMillis;
     private int mNumConsecutiveFpFailures;
 
@@ -288,7 +285,6 @@
             ScreenOffAnimationController screenOffAnimationController,
             VibratorHelper vibrator,
             SystemClock systemClock,
-            DeviceEntryHapticsInteractor hapticsInteractor,
             Lazy<SelectedUserInteractor> selectedUserInteractor,
             BiometricUnlockInteractor biometricUnlockInteractor
     ) {
@@ -320,7 +316,6 @@
         mSystemClock = systemClock;
         mOrderUnlockAndWake = resources.getBoolean(
                 com.android.internal.R.bool.config_orderUnlockAndWake);
-        mHapticsInteractor = hapticsInteractor;
         mSelectedUserInteractor = selectedUserInteractor;
 
         dumpManager.registerDumpable(this);
@@ -442,7 +437,6 @@
         if (mode == MODE_WAKE_AND_UNLOCK
                 || mode == MODE_WAKE_AND_UNLOCK_PULSING || mode == MODE_UNLOCK_COLLAPSING
                 || mode == MODE_WAKE_AND_UNLOCK_FROM_DREAM || mode == MODE_DISMISS_BOUNCER) {
-            mHapticsInteractor.vibrateSuccess();
             onBiometricUnlockedWithKeyguardDismissal(biometricSourceType);
         }
         startWakeAndUnlock(mode);
@@ -726,14 +720,6 @@
             }
         }
 
-        // Suppress all face auth errors if fingerprint can be used to authenticate
-        if ((biometricSourceType == BiometricSourceType.FACE
-                && !mUpdateMonitor.isUnlockWithFingerprintPossible(
-                    mSelectedUserInteractor.get().getSelectedUserId()))
-                || (biometricSourceType == BiometricSourceType.FINGERPRINT)) {
-            mHapticsInteractor.vibrateError();
-        }
-
         cleanup();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
index 3a95e6d..e66d9e8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -48,7 +48,10 @@
 import com.android.systemui.statusbar.policy.HeadsUpManagerLogger;
 import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
 import com.android.systemui.statusbar.policy.OnHeadsUpPhoneListenerChange;
+import com.android.systemui.util.concurrency.DelayableExecutor;
 import com.android.systemui.util.kotlin.JavaAdapter;
+import com.android.systemui.util.settings.GlobalSettings;
+import com.android.systemui.util.time.SystemClock;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -115,11 +118,15 @@
             VisualStabilityProvider visualStabilityProvider,
             ConfigurationController configurationController,
             @Main Handler handler,
+            GlobalSettings globalSettings,
+            SystemClock systemClock,
+            @Main DelayableExecutor executor,
             AccessibilityManagerWrapper accessibilityManagerWrapper,
             UiEventLogger uiEventLogger,
             JavaAdapter javaAdapter,
             ShadeInteractor shadeInteractor) {
-        super(context, logger, handler, accessibilityManagerWrapper, uiEventLogger);
+        super(context, logger, handler, globalSettings, systemClock, executor,
+                accessibilityManagerWrapper, uiEventLogger);
         Resources resources = mContext.getResources();
         mExtensionTime = resources.getInteger(R.integer.ambient_notification_extension_time);
         statusBarStateController.addCallback(mStatusBarStateListener);
@@ -206,7 +213,7 @@
     @Override
     public boolean shouldSwallowClick(@NonNull String key) {
         BaseHeadsUpManager.HeadsUpEntry entry = getHeadsUpEntry(key);
-        return entry != null && mClock.currentTimeMillis() < entry.mPostTime;
+        return entry != null && mSystemClock.elapsedRealtime() < entry.mPostTime;
     }
 
     public void onExpandingFinished() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index 00e78a4..0dabafb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -400,6 +400,21 @@
         }
     }
 
+    /**
+     * Removes all child {@link StatusBarIconView} instances from this container, immediately and
+     * without animation. This should be called when tearing down this container so that external
+     * icon views are not holding onto a reference thru {@link View#getParent()}.
+     */
+    public void detachAllIcons() {
+        boolean animsWereEnabled = mAnimationsEnabled;
+        boolean wasChangingPositions = mChangingViewPositions;
+        mAnimationsEnabled = false;
+        mChangingViewPositions = true;
+        removeAllViews();
+        mChangingViewPositions = wasChangingPositions;
+        mAnimationsEnabled = animsWereEnabled;
+    }
+
     public boolean areIconsOverflowing() {
         return mIsShowingOverflowDot;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt
index 3b96f57..877bd7c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt
@@ -42,6 +42,9 @@
 import com.android.systemui.util.leak.RotationUtils.getExactRotation
 import com.android.systemui.util.leak.RotationUtils.getResourcesForRotation
 import com.android.app.tracing.traceSection
+import com.android.systemui.BottomMarginCommand
+import com.android.systemui.StatusBarInsetsCommand
+import com.android.systemui.statusbar.commandline.CommandRegistry
 import java.io.PrintWriter
 import java.lang.Math.max
 import javax.inject.Inject
@@ -64,7 +67,8 @@
 class StatusBarContentInsetsProvider @Inject constructor(
     val context: Context,
     val configurationController: ConfigurationController,
-    val dumpManager: DumpManager
+    val dumpManager: DumpManager,
+    val commandRegistry: CommandRegistry,
 ) : CallbackController<StatusBarContentInsetsChangedListener>,
         ConfigurationController.ConfigurationListener,
         Dumpable {
@@ -80,6 +84,13 @@
     init {
         configurationController.addCallback(this)
         dumpManager.registerDumpable(TAG, this)
+        commandRegistry.registerCommand(StatusBarInsetsCommand.NAME) {
+            StatusBarInsetsCommand(object : StatusBarInsetsCommand.Callback {
+                override fun onExecute(command: StatusBarInsetsCommand, printWriter: PrintWriter) {
+                    executeCommand(command, printWriter)
+                }
+            })
+        }
     }
 
     override fun addCallback(listener: StatusBarContentInsetsChangedListener) {
@@ -271,8 +282,41 @@
                 statusBarContentHeight)
     }
 
+    private fun executeCommand(command: StatusBarInsetsCommand, printWriter: PrintWriter) {
+        command.bottomMargin?.let { executeBottomMarginCommand(it, printWriter) }
+    }
+
+    private fun executeBottomMarginCommand(command: BottomMarginCommand, printWriter: PrintWriter) {
+        val rotation = command.rotationValue
+        if (rotation == null) {
+            printWriter.println(
+                    "Rotation should be one of ${BottomMarginCommand.ROTATION_DEGREES_OPTIONS}"
+            )
+            return
+        }
+        val marginBottomDp = command.marginBottomDp
+        if (marginBottomDp == null) {
+            printWriter.println("Margin bottom not set.")
+            return
+        }
+        setBottomMarginOverride(rotation, marginBottomDp)
+    }
+
+    private val marginBottomOverrides = mutableMapOf<Int, Int>()
+
+    private fun setBottomMarginOverride(rotation: Int, marginBottomDp: Float) {
+        insetsCache.evictAll()
+        val marginBottomPx = (marginBottomDp * context.resources.displayMetrics.density).toInt()
+        marginBottomOverrides[rotation] = marginBottomPx
+        notifyInsetsChanged()
+    }
+
     @Px
     private fun getBottomAlignedMargin(targetRotation: Int, resources: Resources): Int {
+        val override = marginBottomOverrides[targetRotation]
+        if (override != null) {
+            return override
+        }
         val dimenRes =
                 when (targetRotation) {
                     Surface.ROTATION_0 -> R.dimen.status_bar_bottom_aligned_margin_rotation_0
@@ -294,6 +338,7 @@
             pw.println("$key -> $rect")
         }
         pw.println(insetsCache)
+        pw.println("Bottom margin overrides: $marginBottomOverrides")
     }
 
     private fun getCacheKey(
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 daadedb..4999123 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -36,6 +36,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewRootImpl;
+import android.view.WindowInsetsController;
 import android.window.BackEvent;
 import android.window.OnBackAnimationCallback;
 import android.window.OnBackInvokedDispatcher;
@@ -859,10 +860,19 @@
         }
     }
 
+    private void setRootViewAnimationDisabled(boolean disabled) {
+        ViewGroup windowRootView = mNotificationShadeWindowController.getWindowRootView();
+        if (windowRootView != null) {
+            WindowInsetsController insetsController = windowRootView.getWindowInsetsController();
+            if (insetsController != null) {
+                insetsController.setAnimationsDisabled(disabled);
+            }
+        }
+    }
+
     @Override
     public void onStartedWakingUp() {
-        mNotificationShadeWindowController.getWindowRootView().getWindowInsetsController()
-                .setAnimationsDisabled(false);
+        setRootViewAnimationDisabled(false);
         NavigationBarView navBarView = mCentralSurfaces.getNavigationBarView();
         if (navBarView != null) {
             navBarView.forEachView(view ->
@@ -875,8 +885,7 @@
 
     @Override
     public void onStartedGoingToSleep() {
-        mNotificationShadeWindowController.getWindowRootView().getWindowInsetsController()
-                .setAnimationsDisabled(true);
+        setRootViewAnimationDisabled(true);
         NavigationBarView navBarView = mCentralSurfaces.getNavigationBarView();
         if (navBarView != null) {
             navBarView.forEachView(view ->
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
index 49880d4..cd99934 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
@@ -74,8 +74,8 @@
 import com.android.systemui.statusbar.pipeline.shared.ui.binder.CollapsedStatusBarViewBinder;
 import com.android.systemui.statusbar.pipeline.shared.ui.binder.StatusBarVisibilityChangeListener;
 import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.CollapsedStatusBarViewModel;
-import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.ui.SystemBarUtilsState;
 import com.android.systemui.statusbar.window.StatusBarWindowStateController;
 import com.android.systemui.statusbar.window.StatusBarWindowStateListener;
 import com.android.systemui.util.CarrierConfigTracker;
@@ -83,8 +83,6 @@
 import com.android.systemui.util.CarrierConfigTracker.DefaultDataSubscriptionChangedListener;
 import com.android.systemui.util.settings.SecureSettings;
 
-import kotlin.Unit;
-
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -95,6 +93,8 @@
 
 import javax.inject.Inject;
 
+import kotlin.Unit;
+
 /**
  * Contains the collapsed status bar and handles hiding/showing based on disable flags
  * and keyguard state. Also manages lifecycle to make sure the views it contains are being
@@ -153,7 +153,7 @@
     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     private final NotificationIconContainerStatusBarViewModel mStatusBarIconsViewModel;
     private final ConfigurationState mConfigurationState;
-    private final ConfigurationController mConfigurationController;
+    private final SystemBarUtilsState mSystemBarUtilsState;
     private final StatusBarNotificationIconViewStore mStatusBarIconViewStore;
     private final DemoModeController mDemoModeController;
 
@@ -246,7 +246,7 @@
             KeyguardUpdateMonitor keyguardUpdateMonitor,
             NotificationIconContainerStatusBarViewModel statusBarIconsViewModel,
             ConfigurationState configurationState,
-            ConfigurationController configurationController,
+            SystemBarUtilsState systemBarUtilsState,
             StatusBarNotificationIconViewStore statusBarIconViewStore,
             DemoModeController demoModeController) {
         mStatusBarFragmentComponentFactory = statusBarFragmentComponentFactory;
@@ -275,7 +275,7 @@
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
         mStatusBarIconsViewModel = statusBarIconsViewModel;
         mConfigurationState = configurationState;
-        mConfigurationController = configurationController;
+        mSystemBarUtilsState = systemBarUtilsState;
         mStatusBarIconViewStore = statusBarIconViewStore;
         mDemoModeController = demoModeController;
     }
@@ -466,11 +466,11 @@
                         .inflate(R.layout.notification_icon_area, notificationIconArea, true);
             NotificationIconContainer notificationIcons =
                     notificationIconArea.requireViewById(R.id.notificationIcons);
-            NotificationIconContainerViewBinder.bind(
+            NotificationIconContainerViewBinder.bindWhileAttached(
                     notificationIcons,
                     mStatusBarIconsViewModel,
                     mConfigurationState,
-                    mConfigurationController,
+                    mSystemBarUtilsState,
                     mIconViewBindingFailureTracker,
                     mStatusBarIconViewStore);
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModel.kt
index 99b123f..ae58398 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModel.kt
@@ -161,13 +161,13 @@
             if (it == null) {
                 notConnectedFlow
             } else {
-                val secondary = it.contentDescription.toString()
+                val secondary = it.contentDescription
                 flowOf(
                     InternetTileModel.Active(
-                        secondaryTitle = secondary,
+                        secondaryLabel = secondary?.toText(),
                         iconId = it.res,
                         stateDescription = null,
-                        contentDescription = ContentDescription.Loaded(secondary),
+                        contentDescription = secondary,
                     )
                 )
             }
@@ -241,5 +241,11 @@
                 string.substring(1, length - 1)
             } else string
         }
+
+        private fun ContentDescription.toText(): Text =
+            when (this) {
+                is ContentDescription.Loaded -> Text.Loaded(this.description)
+                is ContentDescription.Resource -> Text.Resource(this.res)
+            }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseHeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseHeadsUpManager.java
index cec76f3..e971128 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseHeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseHeadsUpManager.java
@@ -25,8 +25,6 @@
 import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.os.Handler;
-import android.os.SystemClock;
-import android.provider.Settings;
 import android.util.ArrayMap;
 import android.view.accessibility.AccessibilityManager;
 
@@ -40,6 +38,9 @@
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
 import com.android.systemui.util.ListenerSet;
+import com.android.systemui.util.concurrency.DelayableExecutor;
+import com.android.systemui.util.settings.GlobalSettings;
+import com.android.systemui.util.time.SystemClock;
 
 import java.io.PrintWriter;
 
@@ -85,36 +86,41 @@
     public BaseHeadsUpManager(@NonNull final Context context,
             HeadsUpManagerLogger logger,
             @Main Handler handler,
+            GlobalSettings globalSettings,
+            SystemClock systemClock,
+            @Main DelayableExecutor executor,
             AccessibilityManagerWrapper accessibilityManagerWrapper,
             UiEventLogger uiEventLogger) {
-        super(logger, handler);
+        super(logger, systemClock, executor);
         mContext = context;
         mAccessibilityMgr = accessibilityManagerWrapper;
         mUiEventLogger = uiEventLogger;
         Resources resources = context.getResources();
         mMinimumDisplayTime = resources.getInteger(R.integer.heads_up_notification_minimum_time);
-        mStickyDisplayTime = resources.getInteger(R.integer.sticky_heads_up_notification_time);
-        mAutoDismissNotificationDecay = resources.getInteger(R.integer.heads_up_notification_decay);
+        mStickyForSomeTimeAutoDismissTime = resources.getInteger(
+                R.integer.sticky_heads_up_notification_time);
+        mAutoDismissTime = resources.getInteger(R.integer.heads_up_notification_decay);
         mTouchAcceptanceDelay = resources.getInteger(R.integer.touch_acceptance_delay);
         mSnoozedPackages = new ArrayMap<>();
         int defaultSnoozeLengthMs =
                 resources.getInteger(R.integer.heads_up_default_snooze_length_ms);
 
-        mSnoozeLengthMs = Settings.Global.getInt(context.getContentResolver(),
-                SETTING_HEADS_UP_SNOOZE_LENGTH_MS, defaultSnoozeLengthMs);
+        mSnoozeLengthMs = globalSettings.getInt(SETTING_HEADS_UP_SNOOZE_LENGTH_MS,
+                defaultSnoozeLengthMs);
         ContentObserver settingsObserver = new ContentObserver(handler) {
             @Override
             public void onChange(boolean selfChange) {
-                final int packageSnoozeLengthMs = Settings.Global.getInt(
-                        context.getContentResolver(), SETTING_HEADS_UP_SNOOZE_LENGTH_MS, -1);
+                final int packageSnoozeLengthMs = globalSettings.getInt(
+                        SETTING_HEADS_UP_SNOOZE_LENGTH_MS, -1);
                 if (packageSnoozeLengthMs > -1 && packageSnoozeLengthMs != mSnoozeLengthMs) {
                     mSnoozeLengthMs = packageSnoozeLengthMs;
                     mLogger.logSnoozeLengthChange(packageSnoozeLengthMs);
                 }
             }
         };
-        context.getContentResolver().registerContentObserver(
-                Settings.Global.getUriFor(SETTING_HEADS_UP_SNOOZE_LENGTH_MS), false,
+        globalSettings.registerContentObserver(
+                globalSettings.getUriFor(SETTING_HEADS_UP_SNOOZE_LENGTH_MS),
+                /* notifyForDescendants = */ false,
                 settingsObserver);
     }
 
@@ -231,7 +237,7 @@
         final String key = snoozeKey(packageName, mUser);
         Long snoozedUntil = mSnoozedPackages.get(key);
         if (snoozedUntil != null) {
-            if (snoozedUntil > mClock.currentTimeMillis()) {
+            if (snoozedUntil > mSystemClock.elapsedRealtime()) {
                 mLogger.logIsSnoozedReturned(key);
                 return true;
             }
@@ -250,7 +256,7 @@
             String packageName = entry.mEntry.getSbn().getPackageName();
             String snoozeKey = snoozeKey(packageName, mUser);
             mLogger.logPackageSnoozed(snoozeKey);
-            mSnoozedPackages.put(snoozeKey, mClock.currentTimeMillis() + mSnoozeLengthMs);
+            mSnoozedPackages.put(snoozeKey, mSystemClock.elapsedRealtime() + mSnoozeLengthMs);
         }
     }
 
@@ -308,7 +314,7 @@
     protected void dumpInternal(@NonNull PrintWriter pw, @NonNull String[] args) {
         pw.print("  mTouchAcceptanceDelay="); pw.println(mTouchAcceptanceDelay);
         pw.print("  mSnoozeLengthMs="); pw.println(mSnoozeLengthMs);
-        pw.print("  now="); pw.println(mClock.currentTimeMillis());
+        pw.print("  now="); pw.println(mSystemClock.elapsedRealtime());
         pw.print("  mUser="); pw.println(mUser);
         for (AlertEntry entry: mAlertEntries.values()) {
             pw.print("  HeadsUpEntry="); pw.println(entry.mEntry);
@@ -519,12 +525,12 @@
 
         /**
          * @return When the notification should auto-dismiss itself, based on
-         * {@link SystemClock#elapsedRealTime()}
+         * {@link SystemClock#elapsedRealtime()}
          */
         @Override
         protected long calculateFinishTime() {
             final long duration = getRecommendedHeadsUpTimeoutMs(
-                    isStickyForSomeTime() ? mStickyDisplayTime : mAutoDismissNotificationDecay);
+                    isStickyForSomeTime() ? mStickyForSomeTimeAutoDismissTime : mAutoDismissTime);
 
             return mPostTime + duration;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt
index ef07eed..f6154afe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt
@@ -66,6 +66,26 @@
         })
     }
 
+    fun logAutoRemoveScheduled(entry: NotificationEntry, delayMillis: Long, reason: String) {
+        buffer.log(TAG, INFO, {
+            str1 = entry.logKey
+            long1 = delayMillis
+            str2 = reason
+        }, {
+            "schedule auto remove of $str1 in $long1 ms reason: $str2"
+        })
+    }
+
+    fun logAutoRemoveRescheduled(entry: NotificationEntry, delayMillis: Long, reason: String) {
+        buffer.log(TAG, INFO, {
+            str1 = entry.logKey
+            long1 = delayMillis
+            str2 = reason
+        }, {
+            "reschedule auto remove of $str1 in $long1 ms reason: $str2"
+        })
+    }
+
     fun logAutoRemoveCanceled(entry: NotificationEntry, reason: String?) {
         buffer.log(TAG, INFO, {
             str1 = entry.logKey
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
index 80c6802..0c5472f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
@@ -41,6 +41,7 @@
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
+import com.android.systemui.log.core.LogLevel;
 import com.android.systemui.res.R;
 import com.android.systemui.user.domain.interactor.SelectedUserInteractor;
 
@@ -49,6 +50,7 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Objects;
+import java.util.function.Consumer;
 
 import javax.inject.Inject;
 
@@ -210,23 +212,33 @@
     private void notifyKeyguardChanged() {
         Trace.beginSection("KeyguardStateController#notifyKeyguardChanged");
         // Copy the list to allow removal during callback.
-        new ArrayList<>(mCallbacks).forEach(Callback::onKeyguardShowingChanged);
+        invokeForEachCallback(Callback::onKeyguardShowingChanged);
         Trace.endSection();
     }
 
     private void notifyKeyguardFaceAuthEnabledChanged() {
+        invokeForEachCallback(Callback::onFaceEnrolledChanged);
+    }
+
+    private void invokeForEachCallback(Consumer<Callback> consumer) {
         // Copy the list to allow removal during callback.
-        new ArrayList<>(mCallbacks).forEach(callback -> {
+        ArrayList<Callback> copyOfCallbacks = new ArrayList<>(mCallbacks);
+        for (int i = 0; i < copyOfCallbacks.size(); i++) {
+            Callback callback = copyOfCallbacks.get(i);
+            // Temporary fix for b/315731775, callback is null even though only non-null callbacks
+            // are added to the list by addCallback
             if (callback != null) {
-                callback.onFaceEnrolledChanged();
+                consumer.accept(callback);
+            } else {
+                mLogger.log("KeyguardStateController callback is null", LogLevel.DEBUG);
             }
-        });
+        }
     }
 
     private void notifyUnlockedChanged() {
         Trace.beginSection("KeyguardStateController#notifyUnlockedChanged");
         // Copy the list to allow removal during callback.
-        new ArrayList<>(mCallbacks).forEach(Callback::onUnlockedChanged);
+        invokeForEachCallback(Callback::onUnlockedChanged);
         Trace.endSection();
     }
 
@@ -242,10 +254,7 @@
             Trace.traceCounter(Trace.TRACE_TAG_APP, "keyguardFadingAway",
                     keyguardFadingAway ? 1 : 0);
             mKeyguardFadingAway = keyguardFadingAway;
-            ArrayList<Callback> callbacks = new ArrayList<>(mCallbacks);
-            for (int i = 0; i < callbacks.size(); i++) {
-                callbacks.get(i).onKeyguardFadingAwayChanged();
-            }
+            invokeForEachCallback(Callback::onKeyguardFadingAwayChanged);
         }
     }
 
@@ -359,7 +368,7 @@
             Trace.traceCounter(Trace.TRACE_TAG_APP, "keyguardGoingAway",
                     keyguardGoingAway ? 1 : 0);
             mKeyguardGoingAway = keyguardGoingAway;
-            new ArrayList<>(mCallbacks).forEach(Callback::onKeyguardGoingAwayChanged);
+            invokeForEachCallback(Callback::onKeyguardGoingAwayChanged);
         }
     }
 
@@ -368,7 +377,7 @@
         if (mPrimaryBouncerShowing != showing) {
             mPrimaryBouncerShowing = showing;
 
-            new ArrayList<>(mCallbacks).forEach(Callback::onPrimaryBouncerShowingChanged);
+            invokeForEachCallback(Callback::onPrimaryBouncerShowingChanged);
         }
     }
 
@@ -392,13 +401,13 @@
             boolean dismissingFromTouch) {
         mDismissAmount = dismissAmount;
         mDismissingFromTouch = dismissingFromTouch;
-        new ArrayList<>(mCallbacks).forEach(Callback::onKeyguardDismissAmountChanged);
+        invokeForEachCallback(Callback::onKeyguardDismissAmountChanged);
     }
 
     @Override
     public void setLaunchTransitionFadingAway(boolean fadingAway) {
         mLaunchTransitionFadingAway = fadingAway;
-        new ArrayList<>(mCallbacks).forEach(Callback::onLaunchTransitionFadingAwayChanged);
+        invokeForEachCallback(Callback::onLaunchTransitionFadingAwayChanged);
     }
 
     @Override
@@ -484,7 +493,12 @@
         }
 
         @Override
-        public void onBiometricsCleared() {
+        public void onFingerprintsCleared() {
+            update(false /* alwaysUpdate */);
+        }
+
+        @Override
+        public void onFacesCleared() {
             update(false /* alwaysUpdate */);
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ui/SystemBarUtilsProxy.kt b/packages/SystemUI/src/com/android/systemui/statusbar/ui/SystemBarUtilsProxy.kt
new file mode 100644
index 0000000..2b3fb70
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ui/SystemBarUtilsProxy.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.ui
+
+import android.content.Context
+import com.android.internal.policy.SystemBarUtils
+import com.android.systemui.dagger.qualifiers.Application
+import dagger.Binds
+import javax.inject.Inject
+
+/**
+ * Proxy interface to [SystemBarUtils], allowing injection of different logic for testing.
+ *
+ * Developers should almost always prefer [SystemBarUtilsState] instead.
+ */
+interface SystemBarUtilsProxy {
+    fun getStatusBarHeight(): Int
+}
+
+class SystemBarUtilsProxyImpl
+@Inject
+constructor(
+    @Application private val context: Context,
+) : SystemBarUtilsProxy {
+    override fun getStatusBarHeight(): Int = SystemBarUtils.getStatusBarHeight(context)
+
+    @dagger.Module
+    interface Module {
+        @Binds fun bindImpl(impl: SystemBarUtilsProxyImpl): SystemBarUtilsProxy
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ui/SystemBarUtilsState.kt b/packages/SystemUI/src/com/android/systemui/statusbar/ui/SystemBarUtilsState.kt
new file mode 100644
index 0000000..ce811e2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ui/SystemBarUtilsState.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.ui
+
+import com.android.internal.policy.SystemBarUtils
+import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.statusbar.policy.onConfigChanged
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onStart
+
+/**
+ * Tracks state from [SystemBarUtils]. Using this is both more efficient and more testable than
+ * using [SystemBarUtils] directly.
+ */
+class SystemBarUtilsState
+@Inject
+constructor(
+    configurationController: ConfigurationController,
+    proxy: SystemBarUtilsProxy,
+) {
+    /** @see SystemBarUtils.getStatusBarHeight */
+    val statusBarHeight: Flow<Int> =
+        configurationController.onConfigChanged
+            .onStart<Any> { emit(Unit) }
+            .map { proxy.getStatusBarHeight() }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
index 886fa70..2b9ad50 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
@@ -18,8 +18,8 @@
 
 import static android.util.TypedValue.TYPE_INT_COLOR_ARGB8;
 
-import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP;
 import static com.android.systemui.Flags.themeOverlayControllerWakefulnessDeprecation;
+import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP;
 import static com.android.systemui.theme.ThemeOverlayApplier.COLOR_SOURCE_HOME;
 import static com.android.systemui.theme.ThemeOverlayApplier.COLOR_SOURCE_LOCK;
 import static com.android.systemui.theme.ThemeOverlayApplier.COLOR_SOURCE_PRESET;
@@ -364,15 +364,23 @@
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            boolean newWorkProfile = Intent.ACTION_MANAGED_PROFILE_ADDED.equals(intent.getAction());
-            boolean isManagedProfile = mUserManager.isManagedProfile(
-                    intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
-            if (newWorkProfile) {
-                if (!mDeviceProvisionedController.isCurrentUserSetup() && isManagedProfile) {
+            boolean newProfile = Intent.ACTION_PROFILE_ADDED.equals(intent.getAction());
+            if (newProfile) {
+                UserHandle newUserHandle = intent.getParcelableExtra(Intent.EXTRA_USER,
+                        android.os.UserHandle.class);
+                boolean isManagedProfile =
+                        mUserManager.isManagedProfile(newUserHandle.getIdentifier());
+                if (!mDeviceProvisionedController.isUserSetup(newUserHandle.getIdentifier())
+                        && isManagedProfile) {
                     Log.i(TAG, "User setup not finished when " + intent.getAction()
                             + " was received. Deferring... Managed profile? " + isManagedProfile);
                     return;
                 }
+                if (android.os.Flags.allowPrivateProfile() && isPrivateProfile(newUserHandle)) {
+                    mDeferredThemeEvaluation = true;
+                    Log.i(TAG, "Deferring theme for private profile till user setup is complete");
+                    return;
+                }
                 if (DEBUG) Log.d(TAG, "Updating overlays for user switch / profile added.");
                 reevaluateSystemTheme(true /* forceReload */);
             } else if (Intent.ACTION_WALLPAPER_CHANGED.equals(intent.getAction())) {
@@ -432,7 +440,7 @@
     public void start() {
         if (DEBUG) Log.d(TAG, "Start");
         final IntentFilter filter = new IntentFilter();
-        filter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
+        filter.addAction(Intent.ACTION_PROFILE_ADDED);
         filter.addAction(Intent.ACTION_WALLPAPER_CHANGED);
         mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, filter, mMainExecutor,
                 UserHandle.ALL);
@@ -608,6 +616,15 @@
         return new FabricatedOverlay.Builder("com.android.systemui", name, "android").build();
     }
 
+    @VisibleForTesting
+    protected boolean isPrivateProfile(UserHandle userHandle) {
+        Context usercontext = mContext.createContextAsUser(userHandle,0);
+        if (usercontext.getSystemService(UserManager.class).isPrivateProfile()) {
+            return true;
+        }
+        return false;
+    }
+
     private void createOverlays(int color) {
         boolean nightMode = isNightMode();
         mColorScheme = new ColorScheme(color, nightMode, mThemeStyle);
@@ -784,7 +801,7 @@
 
         Set<UserHandle> managedProfiles = new HashSet<>();
         for (UserInfo userInfo : mUserManager.getEnabledProfiles(currentUser)) {
-            if (userInfo.isManagedProfile()) {
+            if (userInfo.isProfile()) {
                 managedProfiles.add(userInfo.getUserHandle());
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt
index 9689811..50515da 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt
@@ -68,6 +68,7 @@
 
     @Provides
     @UnfoldBgProgressFlag
+    @Singleton
     fun unfoldBgProgressFlag() = Flags.unfoldAnimationBackgroundProgress()
 
     /** A globally available FoldStateListener that allows one to query the fold state. */
diff --git a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/SelectedUserInteractor.kt b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/SelectedUserInteractor.kt
index 3ed05aa..0fb4b43 100644
--- a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/SelectedUserInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/SelectedUserInteractor.kt
@@ -2,9 +2,8 @@
 
 import android.annotation.UserIdInt
 import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.systemui.Flags.refactorGetCurrentUser
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.flags.FeatureFlagsClassic
-import com.android.systemui.flags.Flags.REFACTOR_GETCURRENTUSER
 import com.android.systemui.user.data.repository.UserRepository
 import javax.inject.Inject
 import kotlinx.coroutines.flow.distinctUntilChanged
@@ -12,12 +11,7 @@
 
 /** Encapsulates business logic to interact the selected user */
 @SysUISingleton
-class SelectedUserInteractor
-@Inject
-constructor(
-    private val repository: UserRepository,
-    private val flags: FeatureFlagsClassic,
-) {
+class SelectedUserInteractor @Inject constructor(private val repository: UserRepository) {
 
     /** Flow providing the ID of the currently selected user. */
     val selectedUser = repository.selectedUserInfo.map { it.id }.distinctUntilChanged()
@@ -34,7 +28,7 @@
     @UserIdInt
     @JvmOverloads
     fun getSelectedUserId(bypassFlag: Boolean = false): Int {
-        return if (bypassFlag || flags.isEnabled(REFACTOR_GETCURRENTUSER)) {
+        return if (bypassFlag || refactorGetCurrentUser()) {
             repository.getSelectedUserInfo().id
         } else {
             KeyguardUpdateMonitor.getCurrentUser()
diff --git a/packages/SystemUI/src/com/android/systemui/util/DumpUtils.kt b/packages/SystemUI/src/com/android/systemui/util/DumpUtils.kt
index 5b0943a..a89fdda 100644
--- a/packages/SystemUI/src/com/android/systemui/util/DumpUtils.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/DumpUtils.kt
@@ -60,6 +60,12 @@
 fun IndentingPrintWriter.println(label: String, value: Any?) =
     append(label).append('=').println(value)
 
+/** Print a section with a header using the given name and an indented body */
+inline fun IndentingPrintWriter.printSection(sectionName: String, block: () -> Unit) {
+    append(sectionName).println(":")
+    withIncreasedIndent(block)
+}
+
 @JvmOverloads
 inline fun <T> IndentingPrintWriter.printCollection(
     label: String,
diff --git a/packages/SystemUI/src/com/android/systemui/util/Utils.java b/packages/SystemUI/src/com/android/systemui/util/Utils.java
index f5edb7b..fa6d055 100644
--- a/packages/SystemUI/src/com/android/systemui/util/Utils.java
+++ b/packages/SystemUI/src/com/android/systemui/util/Utils.java
@@ -83,17 +83,19 @@
 
     /**
      * Allow the media player to be shown in the QS area, controlled by 2 flags.
-     * Off by default, but can be disabled by setting to 0
+     * On by default, but can be disabled by setting either flag to 0/false.
      */
     public static boolean useQsMediaPlayer(Context context) {
-        // TODO(b/192412820): Replace SHOW_MEDIA_ON_QUICK_SETTINGS with compile-time value
         // Settings.Global.SHOW_MEDIA_ON_QUICK_SETTINGS can't be toggled at runtime, so simply
         // cache the first result we fetch and use that going forward. Do this to avoid unnecessary
         // binder calls which may happen on the critical path.
         if (sUseQsMediaPlayer == null) {
-            int flag = Settings.Global.getInt(context.getContentResolver(),
+            // TODO(b/192412820): Consolidate SHOW_MEDIA_ON_QUICK_SETTINGS into compile-time value.
+            final int settingsFlag = Settings.Global.getInt(context.getContentResolver(),
                     Settings.Global.SHOW_MEDIA_ON_QUICK_SETTINGS, 1);
-            sUseQsMediaPlayer = flag > 0;
+            final boolean configFlag = context.getResources()
+                    .getBoolean(com.android.internal.R.bool.config_quickSettingsShowMediaPlayer);
+            sUseQsMediaPlayer = settingsFlag > 0 && configFlag;
         }
         return sUseQsMediaPlayer;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/util/kotlin/Log.kt b/packages/SystemUI/src/com/android/systemui/util/kotlin/Log.kt
new file mode 100644
index 0000000..2f6c450
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/kotlin/Log.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.util.kotlin
+
+import android.util.Log
+
+/** Logs message at [Log.DEBUG] level. Won't call the lambda if [DEBUG] is not loggable. */
+inline fun logD(tag: String, messageLambda: () -> String) {
+    if (Log.isLoggable(tag, Log.DEBUG)) {
+        Log.d(tag, messageLambda.invoke())
+    }
+}
+
+/** Logs message at [Log.VERBOSE] level. Won't call the lambda if [VERBOSE] is not loggable. */
+inline fun logV(tag: String, messageLambda: () -> String) {
+    if (Log.isLoggable(tag, Log.VERBOSE)) {
+        Log.v(tag, messageLambda.invoke())
+    }
+}
+
+/** Logs message at [Log.INFO] level. Won't call the lambda if [INFO] is not loggable. */
+inline fun logI(tag: String, messageLambda: () -> String) {
+    if (Log.isLoggable(tag, Log.INFO)) {
+        Log.i(tag, messageLambda.invoke())
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerBaseTest.java
index 24917b3..88f63ad 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerBaseTest.java
@@ -63,7 +63,7 @@
 import com.android.systemui.statusbar.phone.NotificationIconAreaController;
 import com.android.systemui.statusbar.phone.NotificationIconContainer;
 import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
-import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.ui.SystemBarUtilsState;
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.settings.SecureSettings;
 import com.android.systemui.util.time.FakeSystemClock;
@@ -185,7 +185,7 @@
                 mKeyguardSliceViewController,
                 mNotificationIconAreaController,
                 mSmartspaceController,
-                mock(ConfigurationController.class),
+                mock(SystemBarUtilsState.class),
                 mock(ScreenOffAnimationController.class),
                 mock(StatusBarIconViewBindingFailureTracker.class),
                 mKeyguardUnlockAnimationController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/IMagnificationConnectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/IMagnificationConnectionTest.java
index 235aa21..f8856c9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/IMagnificationConnectionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/IMagnificationConnectionTest.java
@@ -34,8 +34,8 @@
 import android.view.Display;
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.IMagnificationConnection;
+import android.view.accessibility.IMagnificationConnectionCallback;
 import android.view.accessibility.IRemoteMagnificationAnimationCallback;
-import android.view.accessibility.IWindowMagnificationConnectionCallback;
 
 import androidx.test.filters.SmallTest;
 
@@ -67,7 +67,7 @@
     @Mock
     private CommandQueue mCommandQueue;
     @Mock
-    private IWindowMagnificationConnectionCallback mConnectionCallback;
+    private IMagnificationConnectionCallback mConnectionCallback;
     @Mock
     private WindowMagnificationController mWindowMagnificationController;
     @Mock
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationTest.java
index 39c8f5d..d0e1678 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationTest.java
@@ -44,7 +44,7 @@
 import android.view.Display;
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.IMagnificationConnection;
-import android.view.accessibility.IWindowMagnificationConnectionCallback;
+import android.view.accessibility.IMagnificationConnectionCallback;
 
 import androidx.test.filters.SmallTest;
 
@@ -75,7 +75,7 @@
     @Mock
     private SysUiState mSysUiState;
     @Mock
-    private IWindowMagnificationConnectionCallback mConnectionCallback;
+    private IMagnificationConnectionCallback mConnectionCallback;
     @Mock
     private OverviewProxyService mOverviewProxyService;
     @Mock
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java
index 95e21cf..92b06ba 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java
@@ -20,6 +20,7 @@
 import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL;
 import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
 import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW;
+import static android.view.WindowInsets.Type.systemBars;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -42,6 +43,7 @@
 import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.database.ContentObserver;
+import android.graphics.Insets;
 import android.graphics.Rect;
 import android.os.UserHandle;
 import android.provider.Settings;
@@ -49,6 +51,7 @@
 import android.testing.TestableLooper;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.WindowInsets;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityManager;
 import android.widget.Button;
@@ -59,10 +62,10 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.common.ui.view.SeekBarWithIconButtonsView;
 import com.android.systemui.common.ui.view.SeekBarWithIconButtonsView.OnSeekBarWithIconButtonsChangeListener;
+import com.android.systemui.res.R;
 import com.android.systemui.util.settings.SecureSettings;
 
 import org.junit.After;
@@ -314,6 +317,42 @@
     }
 
     @Test
+    public void onWindowBoundsChanged_updateDraggableWindowBounds() {
+        setupMagnificationCapabilityAndMode(
+                /* capability= */ ACCESSIBILITY_MAGNIFICATION_MODE_ALL,
+                /* mode= */ ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
+        mWindowMagnificationSettings.showSettingPanel();
+
+        // get the measured panel view frame size
+        final int panelWidth = mSettingView.getMeasuredWidth();
+        final int panelHeight = mSettingView.getMeasuredHeight();
+
+        final Rect testWindowBounds = new Rect(10, 20, 1010, 2020);
+        final WindowInsets testWindowInsets = new WindowInsets.Builder()
+                .setInsetsIgnoringVisibility(systemBars(), Insets.of(100, 200, 100, 200))
+                .build();
+        mWindowManager.setWindowBounds(testWindowBounds);
+        mWindowManager.setWindowInsets(testWindowInsets);
+
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+            mWindowMagnificationSettings.onConfigurationChanged(ActivityInfo.CONFIG_SCREEN_SIZE);
+        });
+
+        // the draggable window bounds left/top should be only related to the insets,
+        // and the bounds right/bottom should consider the panel frame size
+        // inset left (100) = 100
+        int expectedLeft = 100;
+        // inset top (200) = 200
+        int expectedTop = 200;
+        // window width (1010 - 10) - inset right (100) - panel width
+        int expectedRight = 900 - panelWidth;
+        // window height (2020 - 20) - inset bottom (200) - panel height
+        int expectedBottom = 1800 - panelHeight;
+        Rect expectedBounds = new Rect(expectedLeft, expectedTop, expectedRight, expectedBottom);
+        assertThat(mWindowMagnificationSettings.mDraggableWindowBounds).isEqualTo(expectedBounds);
+    }
+
+    @Test
     public void onScreenSizeChanged_resetPositionToRightBottomCorner() {
         setupMagnificationCapabilityAndMode(
                 /* capability= */ ACCESSIBILITY_MAGNIFICATION_MODE_ALL,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuAnimationControllerTest.java
index 2a1cfd1..215f93d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuAnimationControllerTest.java
@@ -17,7 +17,6 @@
 package com.android.systemui.accessibility.floatingmenu;
 
 import static com.google.common.truth.Truth.assertThat;
-
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
@@ -26,9 +25,7 @@
 import static org.mockito.Mockito.verifyZeroInteractions;
 
 import android.graphics.PointF;
-import android.platform.test.annotations.RequiresFlagsEnabled;
-import android.platform.test.flag.junit.CheckFlagsRule;
-import android.platform.test.flag.junit.DeviceFlagsValueProvider;
+import android.platform.test.annotations.EnableFlags;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.view.View;
@@ -74,10 +71,6 @@
     @Rule
     public MockitoRule mockito = MockitoJUnit.rule();
 
-    @Rule
-    public final CheckFlagsRule mCheckFlagsRule =
-            DeviceFlagsValueProvider.createCheckFlagsRule();
-
     @Mock
     private AccessibilityManager mAccessibilityManager;
 
@@ -233,7 +226,7 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_FLOATING_MENU_ANIMATED_TUCK)
+    @EnableFlags(Flags.FLAG_FLOATING_MENU_ANIMATED_TUCK)
     public void tuck_animates() {
         mMenuAnimationController.cancelAnimations();
         mMenuAnimationController.moveToEdgeAndHide();
@@ -242,7 +235,7 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_FLOATING_MENU_ANIMATED_TUCK)
+    @EnableFlags(Flags.FLAG_FLOATING_MENU_ANIMATED_TUCK)
     public void untuck_animates() {
         mMenuAnimationController.cancelAnimations();
         mMenuAnimationController.moveOutEdgeAndShow();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java
index 0f1364d..be6f3ff 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java
@@ -21,11 +21,8 @@
 import static android.view.WindowInsets.Type.displayCutout;
 import static android.view.WindowInsets.Type.ime;
 import static android.view.WindowInsets.Type.systemBars;
-
 import static com.android.systemui.accessibility.floatingmenu.MenuViewLayer.LayerIndex;
-
 import static com.google.common.truth.Truth.assertThat;
-
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
@@ -41,10 +38,8 @@
 import android.graphics.Rect;
 import android.os.Build;
 import android.os.UserHandle;
-import android.platform.test.annotations.RequiresFlagsDisabled;
-import android.platform.test.annotations.RequiresFlagsEnabled;
-import android.platform.test.flag.junit.CheckFlagsRule;
-import android.platform.test.flag.junit.DeviceFlagsValueProvider;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
 import android.provider.Settings;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -103,10 +98,6 @@
     @Rule
     public MockitoRule mockito = MockitoJUnit.rule();
 
-    @Rule
-    public final CheckFlagsRule mCheckFlagsRule =
-            DeviceFlagsValueProvider.createCheckFlagsRule();
-
     @Mock
     private IAccessibilityFloatingMenu mFloatingMenu;
 
@@ -230,7 +221,7 @@
     }
 
     @Test
-    @RequiresFlagsDisabled(Flags.FLAG_FLOATING_MENU_IME_DISPLACEMENT_ANIMATION)
+    @DisableFlags(Flags.FLAG_FLOATING_MENU_IME_DISPLACEMENT_ANIMATION)
     public void showingImeInsetsChange_overlapOnIme_menuShownAboveIme_old() {
         mMenuAnimationController.moveAndPersistPosition(new PointF(0, IME_TOP + 100));
         final PointF beforePosition = mMenuView.getMenuPosition();
@@ -243,7 +234,7 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_FLOATING_MENU_IME_DISPLACEMENT_ANIMATION)
+    @EnableFlags(Flags.FLAG_FLOATING_MENU_IME_DISPLACEMENT_ANIMATION)
     public void showingImeInsetsChange_overlapOnIme_menuShownAboveIme() {
         mMenuAnimationController.moveAndPersistPosition(new PointF(0, IME_TOP + 100));
         final PointF beforePosition = mMenuView.getMenuPosition();
@@ -259,7 +250,7 @@
     }
 
     @Test
-    @RequiresFlagsDisabled(Flags.FLAG_FLOATING_MENU_IME_DISPLACEMENT_ANIMATION)
+    @DisableFlags(Flags.FLAG_FLOATING_MENU_IME_DISPLACEMENT_ANIMATION)
     public void hidingImeInsetsChange_overlapOnIme_menuBackToOriginalPosition_old() {
         mMenuAnimationController.moveAndPersistPosition(new PointF(0, IME_TOP + 200));
         final PointF beforePosition = mMenuView.getMenuPosition();
@@ -271,7 +262,7 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_FLOATING_MENU_IME_DISPLACEMENT_ANIMATION)
+    @EnableFlags(Flags.FLAG_FLOATING_MENU_IME_DISPLACEMENT_ANIMATION)
     public void hidingImeInsetsChange_overlapOnIme_menuBackToOriginalPosition() {
         mMenuAnimationController.moveAndPersistPosition(new PointF(0, IME_TOP + 200));
         final PointF beforePosition = mMenuView.getMenuPosition();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewTest.java
index 8f0a97c..8da6cf9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewTest.java
@@ -17,9 +17,7 @@
 package com.android.systemui.accessibility.floatingmenu;
 
 import static android.app.UiModeManager.MODE_NIGHT_YES;
-
 import static com.google.common.truth.Truth.assertThat;
-
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
@@ -27,9 +25,7 @@
 import android.app.UiModeManager;
 import android.graphics.Rect;
 import android.graphics.drawable.GradientDrawable;
-import android.platform.test.annotations.RequiresFlagsEnabled;
-import android.platform.test.flag.junit.CheckFlagsRule;
-import android.platform.test.flag.junit.DeviceFlagsValueProvider;
+import android.platform.test.annotations.EnableFlags;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.view.WindowManager;
@@ -66,10 +62,6 @@
     @Rule
     public MockitoRule mockito = MockitoJUnit.rule();
 
-    @Rule
-    public final CheckFlagsRule mCheckFlagsRule =
-            DeviceFlagsValueProvider.createCheckFlagsRule();
-
     @Mock
     private AccessibilityManager mAccessibilityManager;
 
@@ -147,7 +139,7 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_FLOATING_MENU_RADII_ANIMATION)
+    @EnableFlags(Flags.FLAG_FLOATING_MENU_RADII_ANIMATION)
     public void onEdgeChanged_startsRadiiAnimation() {
         final RadiiAnimator radiiAnimator = getRadiiAnimator();
         mMenuView.onEdgeChanged();
@@ -155,7 +147,7 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_FLOATING_MENU_RADII_ANIMATION)
+    @EnableFlags(Flags.FLAG_FLOATING_MENU_RADII_ANIMATION)
     public void onDraggingStart_startsRadiiAnimation() {
         final RadiiAnimator radiiAnimator = getRadiiAnimator();
         mMenuView.onDraggingStart();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
index ea20d29..91219f0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
@@ -47,12 +47,14 @@
 import com.android.systemui.biometrics.domain.interactor.FakeCredentialInteractor
 import com.android.systemui.biometrics.domain.interactor.PromptCredentialInteractor
 import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractorImpl
+import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor
 import com.android.systemui.biometrics.ui.viewmodel.CredentialViewModel
 import com.android.systemui.biometrics.ui.viewmodel.PromptViewModel
 import com.android.systemui.display.data.repository.FakeDisplayRepository
 import com.android.systemui.keyguard.WakefulnessLifecycle
 import com.android.systemui.statusbar.VibratorHelper
 import com.android.systemui.statusbar.events.ANIMATING_OUT
+import com.android.systemui.user.domain.interactor.SelectedUserInteractor
 import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
@@ -101,6 +103,12 @@
     lateinit var interactionJankMonitor: InteractionJankMonitor
     @Mock
     lateinit var vibrator: VibratorHelper
+    @Mock
+    lateinit var udfpsUtils: UdfpsUtils
+    @Mock
+    lateinit var authController: AuthController
+    @Mock
+    lateinit var selectedUserInteractor: SelectedUserInteractor
 
     private val testScope = TestScope(StandardTestDispatcher())
     private val fakeExecutor = FakeExecutor(FakeSystemClock())
@@ -123,6 +131,7 @@
 
     private lateinit var displayRepository: FakeDisplayRepository
     private lateinit var displayStateInteractor: DisplayStateInteractor
+    private lateinit var udfpsOverlayInteractor: UdfpsOverlayInteractor
 
     private val credentialViewModel = CredentialViewModel(mContext, bpCredentialInteractor)
 
@@ -140,6 +149,12 @@
                     displayStateRepository,
                     displayRepository,
             )
+        udfpsOverlayInteractor =
+                UdfpsOverlayInteractor(
+                        authController,
+                        selectedUserInteractor,
+                        testScope.backgroundScope,
+                )
     }
 
     @After
@@ -532,6 +547,8 @@
             displayStateInteractor,
             promptSelectorInteractor,
             context,
+            udfpsOverlayInteractor,
+            udfpsUtils
         ),
         { credentialViewModel },
         Handler(TestableLooper.get(this).looper),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
index 8e54eb7..4c510ee 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
@@ -27,6 +27,7 @@
 import com.android.keyguard.KeyguardUpdateMonitor
 import com.android.keyguard.KeyguardUpdateMonitorCallback
 import com.android.keyguard.logging.KeyguardLogger
+import com.android.systemui.Flags.FLAG_LIGHT_REVEAL_MIGRATION
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.dump.logcatLogBuffer
 import com.android.systemui.flags.FeatureFlags
@@ -40,6 +41,7 @@
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.util.leak.RotationUtils
 import com.android.systemui.util.mockito.any
+import javax.inject.Provider
 import org.junit.After
 import org.junit.Assert.assertFalse
 import org.junit.Assert.assertTrue
@@ -51,14 +53,14 @@
 import org.mockito.ArgumentMatchers.eq
 import org.mockito.Captor
 import org.mockito.Mock
-import org.mockito.Mockito.`when`
 import org.mockito.Mockito.never
 import org.mockito.Mockito.reset
 import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
 import org.mockito.MockitoAnnotations
 import org.mockito.MockitoSession
 import org.mockito.quality.Strictness
-import javax.inject.Provider
+
 
 @SmallTest
 @RunWith(AndroidTestingRunner::class)
@@ -246,6 +248,7 @@
     @Test
     @RunWithLooper(setAsMainLooper = true)
     fun testAnimatorRunWhenWakeAndUnlock_fingerprint() {
+        mSetFlagsRule.disableFlags(FLAG_LIGHT_REVEAL_MIGRATION)
         val fpsLocation = Point(5, 5)
         `when`(authController.fingerprintSensorLocation).thenReturn(fpsLocation)
         controller.onViewAttached()
@@ -266,6 +269,7 @@
     @Test
     @RunWithLooper(setAsMainLooper = true)
     fun testAnimatorRunWhenWakeAndUnlock_faceUdfpsFingerDown() {
+        mSetFlagsRule.disableFlags(FLAG_LIGHT_REVEAL_MIGRATION)
         val faceLocation = Point(5, 5)
         `when`(authController.faceSensorLocation).thenReturn(faceLocation)
         controller.onViewAttached()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/BiometricStatusRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/BiometricStatusRepositoryTest.kt
new file mode 100644
index 0000000..27d93eb
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/BiometricStatusRepositoryTest.kt
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.biometrics.data.repository
+
+import android.hardware.biometrics.AuthenticationStateListener
+import android.hardware.biometrics.BiometricManager
+import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_BP
+import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_KEYGUARD
+import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_OTHER
+import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_SETTINGS
+import android.hardware.biometrics.BiometricRequestConstants.REASON_ENROLL_ENROLLING
+import android.hardware.biometrics.BiometricRequestConstants.REASON_ENROLL_FIND_SENSOR
+import android.platform.test.annotations.RequiresFlagsEnabled
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.biometrics.shared.model.AuthenticationReason
+import com.android.systemui.biometrics.shared.model.AuthenticationReason.SettingsOperations
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
+import com.android.systemui.util.mockito.withArgCaptor
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+
+@RequiresFlagsEnabled(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class BiometricStatusRepositoryTest : SysuiTestCase() {
+    @JvmField @Rule var mockitoRule: MockitoRule = MockitoJUnit.rule()
+    @Mock private lateinit var biometricManager: BiometricManager
+
+    private lateinit var underTest: BiometricStatusRepository
+
+    private val testScope = TestScope(StandardTestDispatcher())
+
+    @Before
+    fun setUp() {
+        underTest = BiometricStatusRepositoryImpl(testScope.backgroundScope, biometricManager)
+    }
+
+    @Test
+    fun updatesFingerprintAuthenticationReason_whenBiometricPromptAuthenticationStarted() =
+        testScope.runTest {
+            val fingerprintAuthenticationReason by
+                collectLastValue(underTest.fingerprintAuthenticationReason)
+            runCurrent()
+
+            val listener = biometricManager.captureListener()
+
+            assertThat(fingerprintAuthenticationReason).isEqualTo(AuthenticationReason.NotRunning)
+
+            listener.onAuthenticationStarted(REASON_AUTH_BP)
+            assertThat(fingerprintAuthenticationReason)
+                .isEqualTo(AuthenticationReason.BiometricPromptAuthentication)
+        }
+
+    @Test
+    fun updatesFingerprintAuthenticationReason_whenDeviceEntryAuthenticationStarted() =
+        testScope.runTest {
+            val fingerprintAuthenticationReason by
+                collectLastValue(underTest.fingerprintAuthenticationReason)
+            runCurrent()
+
+            val listener = biometricManager.captureListener()
+
+            assertThat(fingerprintAuthenticationReason).isEqualTo(AuthenticationReason.NotRunning)
+
+            listener.onAuthenticationStarted(REASON_AUTH_KEYGUARD)
+            assertThat(fingerprintAuthenticationReason)
+                .isEqualTo(AuthenticationReason.DeviceEntryAuthentication)
+        }
+
+    @Test
+    fun updatesFingerprintAuthenticationReason_whenOtherAuthenticationStarted() =
+        testScope.runTest {
+            val fingerprintAuthenticationReason by
+                collectLastValue(underTest.fingerprintAuthenticationReason)
+            runCurrent()
+
+            val listener = biometricManager.captureListener()
+
+            assertThat(fingerprintAuthenticationReason).isEqualTo(AuthenticationReason.NotRunning)
+
+            listener.onAuthenticationStarted(REASON_AUTH_OTHER)
+            assertThat(fingerprintAuthenticationReason)
+                .isEqualTo(AuthenticationReason.OtherAuthentication)
+        }
+
+    @Test
+    fun updatesFingerprintAuthenticationReason_whenSettingsAuthenticationStarted() =
+        testScope.runTest {
+            val fingerprintAuthenticationReason by
+                collectLastValue(underTest.fingerprintAuthenticationReason)
+            runCurrent()
+
+            val listener = biometricManager.captureListener()
+
+            assertThat(fingerprintAuthenticationReason).isEqualTo(AuthenticationReason.NotRunning)
+
+            listener.onAuthenticationStarted(REASON_AUTH_SETTINGS)
+            assertThat(fingerprintAuthenticationReason)
+                .isEqualTo(AuthenticationReason.SettingsAuthentication(SettingsOperations.OTHER))
+        }
+
+    @Test
+    fun updatesFingerprintAuthenticationReason_whenEnrollmentAuthenticationStarted() =
+        testScope.runTest {
+            val fingerprintAuthenticationReason by
+                collectLastValue(underTest.fingerprintAuthenticationReason)
+            runCurrent()
+
+            val listener = biometricManager.captureListener()
+
+            assertThat(fingerprintAuthenticationReason).isEqualTo(AuthenticationReason.NotRunning)
+
+            listener.onAuthenticationStarted(REASON_ENROLL_FIND_SENSOR)
+            assertThat(fingerprintAuthenticationReason)
+                .isEqualTo(
+                    AuthenticationReason.SettingsAuthentication(
+                        SettingsOperations.ENROLL_FIND_SENSOR
+                    )
+                )
+
+            listener.onAuthenticationStarted(REASON_ENROLL_ENROLLING)
+            assertThat(fingerprintAuthenticationReason)
+                .isEqualTo(
+                    AuthenticationReason.SettingsAuthentication(SettingsOperations.ENROLL_ENROLLING)
+                )
+        }
+
+    @Test
+    fun updatesFingerprintAuthenticationReason_whenAuthenticationStopped() =
+        testScope.runTest {
+            val fingerprintAuthenticationReason by
+                collectLastValue(underTest.fingerprintAuthenticationReason)
+            runCurrent()
+
+            val listener = biometricManager.captureListener()
+
+            listener.onAuthenticationStarted(REASON_AUTH_BP)
+            listener.onAuthenticationStopped()
+            assertThat(fingerprintAuthenticationReason).isEqualTo(AuthenticationReason.NotRunning)
+        }
+}
+
+private fun BiometricManager.captureListener() =
+    withArgCaptor<AuthenticationStateListener> {
+        verify(this@captureListener).registerAuthenticationStateListener(capture())
+    }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/BiometricStatusInteractorImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/BiometricStatusInteractorImplTest.kt
new file mode 100644
index 0000000..6978923
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/BiometricStatusInteractorImplTest.kt
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.biometrics.domain.interactor
+
+import android.app.ActivityManager
+import android.app.ActivityTaskManager
+import android.content.ComponentName
+import android.platform.test.annotations.RequiresFlagsEnabled
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.biometrics.data.repository.FakeBiometricStatusRepository
+import com.android.systemui.biometrics.shared.model.AuthenticationReason
+import com.android.systemui.biometrics.shared.model.AuthenticationReason.SettingsOperations
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.Mockito.`when`
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+
+@RequiresFlagsEnabled(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class BiometricStatusInteractorImplTest : SysuiTestCase() {
+    @JvmField @Rule var mockitoRule: MockitoRule = MockitoJUnit.rule()
+    @Mock private lateinit var activityTaskManager: ActivityTaskManager
+
+    private lateinit var biometricStatusRepository: FakeBiometricStatusRepository
+    private lateinit var underTest: BiometricStatusInteractorImpl
+
+    private val testScope = TestScope(StandardTestDispatcher())
+
+    @Before
+    fun setup() {
+        biometricStatusRepository = FakeBiometricStatusRepository()
+        underTest = BiometricStatusInteractorImpl(activityTaskManager, biometricStatusRepository)
+    }
+
+    @Test
+    fun updatesSfpsAuthenticationReason_whenBiometricPromptAuthenticationStarted() =
+        testScope.runTest {
+            val sfpsAuthenticationReason by collectLastValue(underTest.sfpsAuthenticationReason)
+            runCurrent()
+
+            assertThat(sfpsAuthenticationReason).isEqualTo(AuthenticationReason.NotRunning)
+
+            biometricStatusRepository.setFingerprintAuthenticationReason(
+                AuthenticationReason.BiometricPromptAuthentication
+            )
+            assertThat(sfpsAuthenticationReason)
+                .isEqualTo(AuthenticationReason.BiometricPromptAuthentication)
+        }
+
+    @Test
+    fun doesNotUpdateSfpsAuthenticationReason_whenDeviceEntryAuthenticationStarted() =
+        testScope.runTest {
+            val sfpsAuthenticationReason by collectLastValue(underTest.sfpsAuthenticationReason)
+            runCurrent()
+
+            assertThat(sfpsAuthenticationReason).isEqualTo(AuthenticationReason.NotRunning)
+
+            biometricStatusRepository.setFingerprintAuthenticationReason(
+                AuthenticationReason.DeviceEntryAuthentication
+            )
+            assertThat(sfpsAuthenticationReason).isEqualTo(AuthenticationReason.NotRunning)
+        }
+
+    @Test
+    fun updatesSfpsAuthenticationReason_whenOtherAuthenticationStarted() =
+        testScope.runTest {
+            val sfpsAuthenticationReason by collectLastValue(underTest.sfpsAuthenticationReason)
+            runCurrent()
+
+            assertThat(sfpsAuthenticationReason).isEqualTo(AuthenticationReason.NotRunning)
+
+            biometricStatusRepository.setFingerprintAuthenticationReason(
+                AuthenticationReason.OtherAuthentication
+            )
+            assertThat(sfpsAuthenticationReason).isEqualTo(AuthenticationReason.OtherAuthentication)
+        }
+
+    @Test
+    fun doesNotUpdateSfpsAuthenticationReason_whenOtherSettingsAuthenticationStarted() =
+        testScope.runTest {
+            val sfpsAuthenticationReason by collectLastValue(underTest.sfpsAuthenticationReason)
+            runCurrent()
+
+            assertThat(sfpsAuthenticationReason).isEqualTo(AuthenticationReason.NotRunning)
+
+            `when`(activityTaskManager.getTasks(Mockito.anyInt()))
+                .thenReturn(listOf(fpSettingsTask()))
+            biometricStatusRepository.setFingerprintAuthenticationReason(
+                AuthenticationReason.SettingsAuthentication(SettingsOperations.OTHER)
+            )
+            assertThat(sfpsAuthenticationReason).isEqualTo(AuthenticationReason.NotRunning)
+        }
+
+    @Test
+    fun updatesSfpsAuthenticationReason_whenEnrollmentAuthenticationStarted() =
+        testScope.runTest {
+            val sfpsAuthenticationReason by collectLastValue(underTest.sfpsAuthenticationReason)
+            runCurrent()
+
+            assertThat(sfpsAuthenticationReason).isEqualTo(AuthenticationReason.NotRunning)
+
+            biometricStatusRepository.setFingerprintAuthenticationReason(
+                AuthenticationReason.SettingsAuthentication(SettingsOperations.ENROLL_FIND_SENSOR)
+            )
+            assertThat(sfpsAuthenticationReason)
+                .isEqualTo(
+                    AuthenticationReason.SettingsAuthentication(
+                        SettingsOperations.ENROLL_FIND_SENSOR
+                    )
+                )
+
+            biometricStatusRepository.setFingerprintAuthenticationReason(
+                AuthenticationReason.SettingsAuthentication(SettingsOperations.ENROLL_ENROLLING)
+            )
+            assertThat(sfpsAuthenticationReason)
+                .isEqualTo(
+                    AuthenticationReason.SettingsAuthentication(SettingsOperations.ENROLL_ENROLLING)
+                )
+        }
+
+    @Test
+    fun updatesFingerprintAuthenticationReason_whenAuthenticationStopped() =
+        testScope.runTest {
+            val sfpsAuthenticationReason by collectLastValue(underTest.sfpsAuthenticationReason)
+            runCurrent()
+
+            biometricStatusRepository.setFingerprintAuthenticationReason(
+                AuthenticationReason.BiometricPromptAuthentication
+            )
+            biometricStatusRepository.setFingerprintAuthenticationReason(
+                AuthenticationReason.NotRunning
+            )
+            assertThat(sfpsAuthenticationReason).isEqualTo(AuthenticationReason.NotRunning)
+        }
+}
+
+private fun fpSettingsTask() = settingsTask(".biometrics.fingerprint.FingerprintSettings")
+
+private fun settingsTask(cls: String) =
+    ActivityManager.RunningTaskInfo().apply {
+        topActivity = ComponentName.createRelative("com.android.settings", cls)
+    }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/shared/model/BiometricModalitiesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/shared/model/BiometricModalitiesTest.kt
index 22e3e7f..74c4313 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/shared/model/BiometricModalitiesTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/shared/model/BiometricModalitiesTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.biometrics.shared.model
 
+import android.hardware.fingerprint.FingerprintSensorProperties
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.biometrics.faceSensorPropertiesInternal
@@ -35,6 +36,46 @@
     }
 
     @Test
+    fun hasUdfps() {
+        with(
+            BiometricModalities(
+                fingerprintProperties = fingerprintSensorPropertiesInternal(
+                    sensorType = FingerprintSensorProperties.TYPE_UDFPS_OPTICAL
+                ).first(),
+            )
+        ) {
+            assertThat(isEmpty).isFalse()
+            assertThat(hasUdfps).isTrue()
+            assertThat(hasSfps).isFalse()
+            assertThat(hasFace).isFalse()
+            assertThat(hasFaceOnly).isFalse()
+            assertThat(hasFingerprint).isTrue()
+            assertThat(hasFingerprintOnly).isTrue()
+            assertThat(hasFaceAndFingerprint).isFalse()
+        }
+    }
+
+    @Test
+    fun hasSfps() {
+        with(
+            BiometricModalities(
+                fingerprintProperties = fingerprintSensorPropertiesInternal(
+                    sensorType = FingerprintSensorProperties.TYPE_POWER_BUTTON
+                ).first(),
+            )
+        ) {
+            assertThat(isEmpty).isFalse()
+            assertThat(hasUdfps).isFalse()
+            assertThat(hasSfps).isTrue()
+            assertThat(hasFace).isFalse()
+            assertThat(hasFaceOnly).isFalse()
+            assertThat(hasFingerprint).isTrue()
+            assertThat(hasFingerprintOnly).isTrue()
+            assertThat(hasFaceAndFingerprint).isFalse()
+        }
+    }
+
+    @Test
     fun fingerprintOnly() {
         with(
             BiometricModalities(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt
new file mode 100644
index 0000000..b4ae00d
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt
@@ -0,0 +1,484 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.biometrics.ui.binder
+
+import android.animation.Animator
+import android.app.ActivityTaskManager
+import android.graphics.Rect
+import android.hardware.biometrics.SensorLocationInternal
+import android.hardware.display.DisplayManager
+import android.hardware.display.DisplayManagerGlobal
+import android.os.Handler
+import android.testing.TestableLooper
+import android.view.Display
+import android.view.DisplayInfo
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewPropertyAnimator
+import android.view.WindowInsets
+import android.view.WindowManager
+import android.view.WindowMetrics
+import androidx.test.filters.SmallTest
+import com.airbnb.lottie.LottieAnimationView
+import com.android.keyguard.KeyguardSecurityModel
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.biometrics.FingerprintInteractiveToAuthProvider
+import com.android.systemui.biometrics.FpsUnlockTracker
+import com.android.systemui.biometrics.data.repository.FakeBiometricStatusRepository
+import com.android.systemui.biometrics.data.repository.FakeDisplayStateRepository
+import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository
+import com.android.systemui.biometrics.domain.interactor.BiometricStatusInteractor
+import com.android.systemui.biometrics.domain.interactor.BiometricStatusInteractorImpl
+import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractorImpl
+import com.android.systemui.biometrics.domain.interactor.SideFpsSensorInteractor
+import com.android.systemui.biometrics.shared.model.AuthenticationReason
+import com.android.systemui.biometrics.shared.model.DisplayRotation
+import com.android.systemui.biometrics.shared.model.FingerprintSensorType
+import com.android.systemui.biometrics.shared.model.SensorStrength
+import com.android.systemui.biometrics.ui.viewmodel.SideFpsOverlayViewModel
+import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
+import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
+import com.android.systemui.bouncer.ui.BouncerView
+import com.android.systemui.classifier.FalsingCollector
+import com.android.systemui.display.data.repository.FakeDisplayRepository
+import com.android.systemui.dump.logcatLogBuffer
+import com.android.systemui.keyguard.DismissCallbackRegistry
+import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
+import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
+import com.android.systemui.keyguard.data.repository.FakeTrustRepository
+import com.android.systemui.keyguard.domain.interactor.DeviceEntrySideFpsOverlayInteractor
+import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor
+import com.android.systemui.keyguard.ui.viewmodel.SideFpsProgressBarViewModel
+import com.android.systemui.log.SideFpsLogger
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.res.R
+import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.unfold.compat.ScreenSizeFoldProvider
+import com.android.systemui.user.domain.interactor.SelectedUserInteractor
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.time.FakeSystemClock
+import java.util.Optional
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.Mockito.any
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.spy
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+class SideFpsOverlayViewBinderTest : SysuiTestCase() {
+    @JvmField @Rule var mockitoRule: MockitoRule = MockitoJUnit.rule()
+    @Mock private lateinit var activityTaskManager: ActivityTaskManager
+    @Mock private lateinit var displayManager: DisplayManager
+    @Mock private lateinit var faceAuthInteractor: KeyguardFaceAuthInteractor
+    @Mock
+    private lateinit var fingerprintInteractiveToAuthProvider: FingerprintInteractiveToAuthProvider
+    @Mock private lateinit var fpsUnlockTracker: FpsUnlockTracker
+    @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
+    @Mock private lateinit var layoutInflater: LayoutInflater
+    @Mock private lateinit var screenSizeFoldProvider: ScreenSizeFoldProvider
+    @Mock private lateinit var selectedUserInteractor: SelectedUserInteractor
+    @Mock private lateinit var sideFpsView: View
+    @Mock private lateinit var windowManager: WindowManager
+
+    private val contextDisplayInfo = DisplayInfo()
+
+    private val bouncerRepository = FakeKeyguardBouncerRepository()
+    private val biometricSettingsRepository = FakeBiometricSettingsRepository()
+    private val biometricStatusRepository = FakeBiometricStatusRepository()
+    private val deviceEntryFingerprintAuthRepository = FakeDeviceEntryFingerprintAuthRepository()
+    private val displayRepository = FakeDisplayRepository()
+    private val displayStateRepository = FakeDisplayStateRepository()
+    private val fingerprintPropertyRepository = FakeFingerprintPropertyRepository()
+
+    private lateinit var underTest: SideFpsOverlayViewBinder
+
+    private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
+    private lateinit var biometricStatusInteractor: BiometricStatusInteractor
+    private lateinit var deviceEntrySideFpsOverlayInteractor: DeviceEntrySideFpsOverlayInteractor
+    private lateinit var displayStateInteractor: DisplayStateInteractorImpl
+    private lateinit var primaryBouncerInteractor: PrimaryBouncerInteractor
+    private lateinit var sfpsSensorInteractor: SideFpsSensorInteractor
+
+    private lateinit var sideFpsProgressBarViewModel: SideFpsProgressBarViewModel
+
+    private lateinit var viewModel: SideFpsOverlayViewModel
+
+    private var displayWidth: Int = 0
+    private var displayHeight: Int = 0
+    private var boundsWidth: Int = 0
+    private var boundsHeight: Int = 0
+
+    private lateinit var deviceConfig: DeviceConfig
+    private lateinit var sensorLocation: SensorLocationInternal
+
+    private val testScope = TestScope(StandardTestDispatcher())
+    private val fakeExecutor = FakeExecutor(FakeSystemClock())
+
+    enum class DeviceConfig {
+        X_ALIGNED,
+        Y_ALIGNED,
+    }
+
+    @Before
+    fun setup() {
+        mSetFlagsRule.enableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
+
+        allowTestableLooperAsMainThread() // repeatWhenAttached requires the main thread
+
+        mContext = spy(mContext)
+
+        val resources = mContext.resources
+        whenever(mContext.display)
+            .thenReturn(
+                Display(mock(DisplayManagerGlobal::class.java), 1, contextDisplayInfo, resources)
+            )
+
+        alternateBouncerInteractor =
+            AlternateBouncerInteractor(
+                mock(StatusBarStateController::class.java),
+                mock(KeyguardStateController::class.java),
+                bouncerRepository,
+                fingerprintPropertyRepository,
+                biometricSettingsRepository,
+                FakeSystemClock(),
+                keyguardUpdateMonitor,
+                testScope.backgroundScope,
+            )
+
+        biometricStatusInteractor =
+            BiometricStatusInteractorImpl(activityTaskManager, biometricStatusRepository)
+
+        displayStateInteractor =
+            DisplayStateInteractorImpl(
+                testScope.backgroundScope,
+                mContext,
+                fakeExecutor,
+                displayStateRepository,
+                displayRepository,
+            )
+        displayStateInteractor.setScreenSizeFoldProvider(screenSizeFoldProvider)
+
+        primaryBouncerInteractor =
+            PrimaryBouncerInteractor(
+                bouncerRepository,
+                mock(BouncerView::class.java),
+                mock(Handler::class.java),
+                mock(KeyguardStateController::class.java),
+                mock(KeyguardSecurityModel::class.java),
+                mock(PrimaryBouncerCallbackInteractor::class.java),
+                mock(FalsingCollector::class.java),
+                mock(DismissCallbackRegistry::class.java),
+                mContext,
+                keyguardUpdateMonitor,
+                FakeTrustRepository(),
+                testScope.backgroundScope,
+                selectedUserInteractor,
+                faceAuthInteractor
+            )
+
+        deviceEntrySideFpsOverlayInteractor =
+            DeviceEntrySideFpsOverlayInteractor(
+                mContext,
+                deviceEntryFingerprintAuthRepository,
+                primaryBouncerInteractor,
+                alternateBouncerInteractor,
+                keyguardUpdateMonitor
+            )
+
+        whenever(fingerprintInteractiveToAuthProvider.enabledForCurrentUser)
+            .thenReturn(MutableStateFlow(false))
+
+        sfpsSensorInteractor =
+            SideFpsSensorInteractor(
+                mContext,
+                fingerprintPropertyRepository,
+                windowManager,
+                displayStateInteractor,
+                Optional.of(fingerprintInteractiveToAuthProvider),
+                SideFpsLogger(logcatLogBuffer("SfpsLogger"))
+            )
+
+        sideFpsProgressBarViewModel =
+            SideFpsProgressBarViewModel(
+                mContext,
+                deviceEntryFingerprintAuthRepository,
+                sfpsSensorInteractor,
+                displayStateInteractor,
+                testScope.backgroundScope,
+            )
+
+        viewModel =
+            SideFpsOverlayViewModel(
+                mContext,
+                biometricStatusInteractor,
+                deviceEntrySideFpsOverlayInteractor,
+                displayStateInteractor,
+                sfpsSensorInteractor,
+                sideFpsProgressBarViewModel
+            )
+
+        underTest =
+            SideFpsOverlayViewBinder(
+                testScope.backgroundScope,
+                mContext,
+                biometricStatusInteractor,
+                displayStateInteractor,
+                deviceEntrySideFpsOverlayInteractor,
+                fpsUnlockTracker,
+                layoutInflater,
+                sideFpsProgressBarViewModel,
+                sfpsSensorInteractor,
+                windowManager
+            )
+
+        context.addMockSystemService(DisplayManager::class.java, displayManager)
+        context.addMockSystemService(WindowManager::class.java, windowManager)
+
+        `when`(layoutInflater.inflate(R.layout.sidefps_view, null, false)).thenReturn(sideFpsView)
+        `when`(sideFpsView.requireViewById<LottieAnimationView>(eq(R.id.sidefps_animation)))
+            .thenReturn(mock(LottieAnimationView::class.java))
+        with(mock(ViewPropertyAnimator::class.java)) {
+            `when`(sideFpsView.animate()).thenReturn(this)
+            `when`(alpha(Mockito.anyFloat())).thenReturn(this)
+            `when`(setStartDelay(Mockito.anyLong())).thenReturn(this)
+            `when`(setDuration(Mockito.anyLong())).thenReturn(this)
+            `when`(setListener(any())).thenAnswer {
+                (it.arguments[0] as Animator.AnimatorListener).onAnimationEnd(
+                    mock(Animator::class.java)
+                )
+                this
+            }
+        }
+    }
+
+    @Test
+    fun verifyIndicatorNotAdded_whenInRearDisplayMode() {
+        testScope.runTest {
+            setupTestConfiguration(
+                DeviceConfig.X_ALIGNED,
+                rotation = DisplayRotation.ROTATION_0,
+                isInRearDisplayMode = true
+            )
+            biometricStatusRepository.setFingerprintAuthenticationReason(
+                AuthenticationReason.NotRunning
+            )
+            sideFpsProgressBarViewModel.setVisible(false)
+            updatePrimaryBouncer(
+                isShowing = true,
+                isAnimatingAway = false,
+                fpsDetectionRunning = true,
+                isUnlockingWithFpAllowed = true
+            )
+            runCurrent()
+
+            verify(windowManager, never()).addView(any(), any())
+        }
+    }
+
+    @Test
+    fun verifyIndicatorShowAndHide_onPrimaryBouncerShowAndHide() {
+        testScope.runTest {
+            setupTestConfiguration(
+                DeviceConfig.X_ALIGNED,
+                rotation = DisplayRotation.ROTATION_0,
+                isInRearDisplayMode = false
+            )
+            biometricStatusRepository.setFingerprintAuthenticationReason(
+                AuthenticationReason.NotRunning
+            )
+            sideFpsProgressBarViewModel.setVisible(false)
+            // Show primary bouncer
+            updatePrimaryBouncer(
+                isShowing = true,
+                isAnimatingAway = false,
+                fpsDetectionRunning = true,
+                isUnlockingWithFpAllowed = true
+            )
+            runCurrent()
+
+            verify(windowManager).addView(any(), any())
+
+            // Hide primary bouncer
+            updatePrimaryBouncer(
+                isShowing = false,
+                isAnimatingAway = false,
+                fpsDetectionRunning = true,
+                isUnlockingWithFpAllowed = true
+            )
+            runCurrent()
+
+            verify(windowManager).removeView(any())
+        }
+    }
+
+    @Test
+    fun verifyIndicatorShowAndHide_onAlternateBouncerShowAndHide() {
+        testScope.runTest {
+            setupTestConfiguration(
+                DeviceConfig.X_ALIGNED,
+                rotation = DisplayRotation.ROTATION_0,
+                isInRearDisplayMode = false
+            )
+            biometricStatusRepository.setFingerprintAuthenticationReason(
+                AuthenticationReason.NotRunning
+            )
+            sideFpsProgressBarViewModel.setVisible(false)
+            // Show alternate bouncer
+            bouncerRepository.setAlternateVisible(true)
+            runCurrent()
+
+            verify(windowManager).addView(any(), any())
+
+            // Hide alternate bouncer
+            bouncerRepository.setAlternateVisible(false)
+            runCurrent()
+
+            verify(windowManager).removeView(any())
+        }
+    }
+
+    @Test
+    fun verifyIndicatorShownAndHidden_onSystemServerAuthenticationStartedAndStopped() {
+        testScope.runTest {
+            setupTestConfiguration(
+                DeviceConfig.X_ALIGNED,
+                rotation = DisplayRotation.ROTATION_0,
+                isInRearDisplayMode = false
+            )
+            sideFpsProgressBarViewModel.setVisible(false)
+            updatePrimaryBouncer(
+                isShowing = false,
+                isAnimatingAway = false,
+                fpsDetectionRunning = true,
+                isUnlockingWithFpAllowed = true
+            )
+            // System server authentication started
+            biometricStatusRepository.setFingerprintAuthenticationReason(
+                AuthenticationReason.BiometricPromptAuthentication
+            )
+            runCurrent()
+
+            verify(windowManager).addView(any(), any())
+
+            // System server authentication stopped
+            biometricStatusRepository.setFingerprintAuthenticationReason(
+                AuthenticationReason.NotRunning
+            )
+            runCurrent()
+
+            verify(windowManager).removeView(any())
+        }
+    }
+
+    private fun updatePrimaryBouncer(
+        isShowing: Boolean,
+        isAnimatingAway: Boolean,
+        fpsDetectionRunning: Boolean,
+        isUnlockingWithFpAllowed: Boolean,
+    ) {
+        bouncerRepository.setPrimaryShow(isShowing)
+        bouncerRepository.setPrimaryStartingToHide(false)
+        val primaryStartDisappearAnimation = if (isAnimatingAway) Runnable {} else null
+        bouncerRepository.setPrimaryStartDisappearAnimation(primaryStartDisappearAnimation)
+
+        whenever(keyguardUpdateMonitor.isFingerprintDetectionRunning)
+            .thenReturn(fpsDetectionRunning)
+        whenever(keyguardUpdateMonitor.isUnlockingWithFingerprintAllowed)
+            .thenReturn(isUnlockingWithFpAllowed)
+        mContext.orCreateTestableResources.addOverride(
+            R.bool.config_show_sidefps_hint_on_bouncer,
+            true
+        )
+    }
+
+    private suspend fun TestScope.setupTestConfiguration(
+        deviceConfig: DeviceConfig,
+        rotation: DisplayRotation = DisplayRotation.ROTATION_0,
+        isInRearDisplayMode: Boolean,
+    ) {
+        this@SideFpsOverlayViewBinderTest.deviceConfig = deviceConfig
+
+        when (deviceConfig) {
+            DeviceConfig.X_ALIGNED -> {
+                displayWidth = 3000
+                displayHeight = 1500
+                boundsWidth = 200
+                boundsHeight = 100
+                sensorLocation = SensorLocationInternal("", 2500, 0, boundsWidth / 2)
+            }
+            DeviceConfig.Y_ALIGNED -> {
+                displayWidth = 2500
+                displayHeight = 2000
+                boundsWidth = 100
+                boundsHeight = 200
+                sensorLocation = SensorLocationInternal("", displayWidth, 300, boundsHeight / 2)
+            }
+        }
+
+        whenever(windowManager.maximumWindowMetrics)
+            .thenReturn(
+                WindowMetrics(
+                    Rect(0, 0, displayWidth, displayHeight),
+                    mock(WindowInsets::class.java),
+                )
+            )
+
+        contextDisplayInfo.uniqueId = DISPLAY_ID
+
+        fingerprintPropertyRepository.setProperties(
+            sensorId = 1,
+            strength = SensorStrength.STRONG,
+            sensorType = FingerprintSensorType.POWER_BUTTON,
+            sensorLocations = mapOf(DISPLAY_ID to sensorLocation)
+        )
+
+        displayStateRepository.setIsInRearDisplayMode(isInRearDisplayMode)
+        displayStateRepository.setCurrentRotation(rotation)
+        displayRepository.emitDisplayChangeEvent(0)
+        underTest.start()
+        runCurrent()
+    }
+
+    companion object {
+        private const val DISPLAY_ID = "displayId"
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/DefaultUdfpsTouchOverlayViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/DefaultUdfpsTouchOverlayViewModelTest.kt
index 575d8bf..fa17672 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/DefaultUdfpsTouchOverlayViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/DefaultUdfpsTouchOverlayViewModelTest.kt
@@ -30,7 +30,6 @@
 import com.android.systemui.runCurrent
 import com.android.systemui.runTest
 import com.android.systemui.shade.data.repository.FakeShadeRepository
-import com.android.systemui.shade.domain.model.ShadeModel
 import com.android.systemui.statusbar.phone.SystemUIDialogManager
 import com.android.systemui.user.domain.UserDomainLayerModule
 import com.android.systemui.util.mockito.mock
@@ -83,23 +82,13 @@
 
     private fun TestComponent.shadeExpanded(expanded: Boolean) {
         if (expanded) {
-            shadeRepository.setShadeModel(
-                ShadeModel(
-                    expansionAmount = 1f,
-                    isExpanded = true,
-                    isUserDragging = false,
-                )
-            )
+            shadeRepository.setLegacyShadeExpansion(1f)
+            shadeRepository.setLegacyShadeTracking(false)
             shadeRepository.setLegacyExpandedOrAwaitingInputTransfer(true)
         } else {
             keyguardRepository.setStatusBarState(StatusBarState.SHADE)
-            shadeRepository.setShadeModel(
-                ShadeModel(
-                    expansionAmount = 0f,
-                    isExpanded = false,
-                    isUserDragging = false,
-                )
-            )
+            shadeRepository.setLegacyShadeExpansion(0f)
+            shadeRepository.setLegacyShadeTracking(false)
             shadeRepository.setLegacyExpandedOrAwaitingInputTransfer(false)
         }
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/DeviceEntryUdfpsTouchOverlayViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/DeviceEntryUdfpsTouchOverlayViewModelTest.kt
index f5f1622..863d9eb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/DeviceEntryUdfpsTouchOverlayViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/DeviceEntryUdfpsTouchOverlayViewModelTest.kt
@@ -20,7 +20,7 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.flags.Flags
-import com.android.systemui.flags.featureFlagsClassic
+import com.android.systemui.flags.fakeFeatureFlagsClassic
 import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
 import com.android.systemui.keyguard.ui.viewmodel.deviceEntryIconViewModelTransitionsMock
 import com.android.systemui.kosmos.testScope
@@ -49,7 +49,7 @@
 class DeviceEntryUdfpsTouchOverlayViewModelTest : SysuiTestCase() {
     val kosmos =
         testKosmos().apply {
-            featureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, true) }
+            fakeFeatureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, true) }
         }
     val testScope = kosmos.testScope
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt
index d06cbbb..7475235 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.biometrics.ui.viewmodel
 
 import android.content.res.Configuration
+import android.graphics.Point
 import android.hardware.biometrics.PromptInfo
 import android.hardware.face.FaceSensorPropertiesInternal
 import android.hardware.fingerprint.FingerprintSensorProperties
@@ -25,7 +26,10 @@
 import android.view.MotionEvent
 import androidx.test.filters.SmallTest
 import com.android.internal.widget.LockPatternUtils
+import com.android.systemui.Flags.FLAG_BP_TALKBACK
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.biometrics.AuthController
+import com.android.systemui.biometrics.UdfpsUtils
 import com.android.systemui.biometrics.data.repository.FakeDisplayStateRepository
 import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository
 import com.android.systemui.biometrics.data.repository.FakePromptRepository
@@ -33,6 +37,7 @@
 import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractorImpl
 import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractor
 import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractorImpl
+import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor
 import com.android.systemui.biometrics.extractAuthenticatorTypes
 import com.android.systemui.biometrics.faceSensorPropertiesInternal
 import com.android.systemui.biometrics.fingerprintSensorPropertiesInternal
@@ -45,8 +50,10 @@
 import com.android.systemui.coroutines.collectValues
 import com.android.systemui.display.data.repository.FakeDisplayRepository
 import com.android.systemui.res.R
-import com.android.systemui.statusbar.VibratorHelper
+import com.android.systemui.user.domain.interactor.SelectedUserInteractor
 import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.whenever
 import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -77,7 +84,9 @@
     @JvmField @Rule var mockitoRule = MockitoJUnit.rule()
 
     @Mock private lateinit var lockPatternUtils: LockPatternUtils
-    @Mock private lateinit var vibrator: VibratorHelper
+    @Mock private lateinit var authController: AuthController
+    @Mock private lateinit var selectedUserInteractor: SelectedUserInteractor
+    @Mock private lateinit var udfpsUtils: UdfpsUtils
 
     private val fakeExecutor = FakeExecutor(FakeSystemClock())
     private val testScope = TestScope()
@@ -87,6 +96,7 @@
     private lateinit var displayStateRepository: FakeDisplayStateRepository
     private lateinit var displayRepository: FakeDisplayRepository
     private lateinit var displayStateInteractor: DisplayStateInteractor
+    private lateinit var udfpsOverlayInteractor: UdfpsOverlayInteractor
 
     private lateinit var selector: PromptSelectorInteractor
     private lateinit var viewModel: PromptViewModel
@@ -116,11 +126,24 @@
                 displayStateRepository,
                 displayRepository,
             )
+        udfpsOverlayInteractor =
+            UdfpsOverlayInteractor(
+                authController,
+                selectedUserInteractor,
+                testScope.backgroundScope
+            )
         selector =
             PromptSelectorInteractorImpl(fingerprintRepository, promptRepository, lockPatternUtils)
         selector.resetPrompt()
 
-        viewModel = PromptViewModel(displayStateInteractor, selector, mContext)
+        viewModel =
+            PromptViewModel(
+                displayStateInteractor,
+                selector,
+                mContext,
+                udfpsOverlayInteractor,
+                udfpsUtils
+            )
         iconViewModel = viewModel.iconViewModel
     }
 
@@ -1153,6 +1176,29 @@
         assertThat(size).isEqualTo(PromptSize.LARGE)
     }
 
+    @Test
+    fun hint_for_talkback_guidance() = runGenericTest {
+        mSetFlagsRule.enableFlags(FLAG_BP_TALKBACK)
+        val hint by collectLastValue(viewModel.accessibilityHint)
+
+        // Touches should fall outside of sensor area
+        whenever(udfpsUtils.getTouchInNativeCoordinates(any(), any(), any()))
+            .thenReturn(Point(0, 0))
+        whenever(udfpsUtils.onTouchOutsideOfSensorArea(any(), any(), any(), any(), any()))
+            .thenReturn("Direction")
+
+        viewModel.onAnnounceAccessibilityHint(
+            obtainMotionEvent(MotionEvent.ACTION_HOVER_ENTER),
+            true
+        )
+
+        if (testCase.modalities.hasUdfps) {
+            assertThat(hint?.isNotBlank()).isTrue()
+        } else {
+            assertThat(hint.isNullOrBlank()).isTrue()
+        }
+    }
+
     /** Asserts that the selected buttons are visible now. */
     private suspend fun TestScope.assertButtonsVisible(
         tryAgain: Boolean = false,
@@ -1220,14 +1266,19 @@
                     authenticatedModality = BiometricModality.Face,
                 ),
                 TestCase(
-                    fingerprint = fingerprintSensorPropertiesInternal(strong = true).first(),
+                    fingerprint =
+                        fingerprintSensorPropertiesInternal(
+                                strong = true,
+                                sensorType = FingerprintSensorProperties.TYPE_POWER_BUTTON
+                            )
+                            .first(),
                     authenticatedModality = BiometricModality.Fingerprint,
                 ),
                 TestCase(
                     fingerprint =
                         fingerprintSensorPropertiesInternal(
                                 strong = true,
-                                sensorType = FingerprintSensorProperties.TYPE_POWER_BUTTON
+                                sensorType = FingerprintSensorProperties.TYPE_UDFPS_OPTICAL
                             )
                             .first(),
                     authenticatedModality = BiometricModality.Fingerprint,
@@ -1264,20 +1315,30 @@
                 TestCase(
                     face = faceSensorPropertiesInternal(strong = true).first(),
                     fingerprint = fingerprintSensorPropertiesInternal(strong = true).first(),
-                    authenticatedModality = BiometricModality.Fingerprint,
-                ),
-                TestCase(
-                    face = faceSensorPropertiesInternal(strong = true).first(),
-                    fingerprint = fingerprintSensorPropertiesInternal(strong = true).first(),
                     authenticatedModality = BiometricModality.Face,
                     confirmationRequested = true,
                 ),
                 TestCase(
                     face = faceSensorPropertiesInternal(strong = true).first(),
-                    fingerprint = fingerprintSensorPropertiesInternal(strong = true).first(),
+                    fingerprint =
+                        fingerprintSensorPropertiesInternal(
+                                strong = true,
+                                sensorType = FingerprintSensorProperties.TYPE_POWER_BUTTON
+                            )
+                            .first(),
                     authenticatedModality = BiometricModality.Fingerprint,
                     confirmationRequested = true,
                 ),
+                TestCase(
+                    face = faceSensorPropertiesInternal(strong = true).first(),
+                    fingerprint =
+                        fingerprintSensorPropertiesInternal(
+                                strong = true,
+                                sensorType = FingerprintSensorProperties.TYPE_UDFPS_OPTICAL
+                            )
+                            .first(),
+                    authenticatedModality = BiometricModality.Fingerprint,
+                ),
             )
     }
 }
@@ -1309,6 +1370,9 @@
             else -> false
         }
 
+    val modalities: BiometricModalities
+        get() = BiometricModalities(fingerprint, face)
+
     val authenticatedByFingerprint: Boolean
         get() = authenticatedModality == BiometricModality.Fingerprint
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelTest.kt
new file mode 100644
index 0000000..2267bdc
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelTest.kt
@@ -0,0 +1,576 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.biometrics.ui.viewmodel
+
+import android.app.ActivityTaskManager
+import android.content.res.Configuration.UI_MODE_NIGHT_NO
+import android.content.res.Configuration.UI_MODE_NIGHT_YES
+import android.graphics.Color
+import android.graphics.Rect
+import android.hardware.biometrics.SensorLocationInternal
+import android.hardware.display.DisplayManagerGlobal
+import android.os.Handler
+import android.view.Display
+import android.view.DisplayInfo
+import android.view.WindowInsets
+import android.view.WindowManager
+import android.view.WindowMetrics
+import androidx.test.filters.SmallTest
+import com.airbnb.lottie.model.KeyPath
+import com.android.keyguard.KeyguardSecurityModel
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.settingslib.Utils
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.biometrics.FingerprintInteractiveToAuthProvider
+import com.android.systemui.biometrics.data.repository.FakeBiometricStatusRepository
+import com.android.systemui.biometrics.data.repository.FakeDisplayStateRepository
+import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository
+import com.android.systemui.biometrics.domain.interactor.BiometricStatusInteractor
+import com.android.systemui.biometrics.domain.interactor.BiometricStatusInteractorImpl
+import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractorImpl
+import com.android.systemui.biometrics.domain.interactor.SideFpsSensorInteractor
+import com.android.systemui.biometrics.shared.model.AuthenticationReason
+import com.android.systemui.biometrics.shared.model.DisplayRotation
+import com.android.systemui.biometrics.shared.model.FingerprintSensorType
+import com.android.systemui.biometrics.shared.model.LottieCallback
+import com.android.systemui.biometrics.shared.model.SensorStrength
+import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
+import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
+import com.android.systemui.bouncer.ui.BouncerView
+import com.android.systemui.classifier.FalsingCollector
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.display.data.repository.FakeDisplayRepository
+import com.android.systemui.dump.logcatLogBuffer
+import com.android.systemui.keyguard.DismissCallbackRegistry
+import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
+import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
+import com.android.systemui.keyguard.data.repository.FakeTrustRepository
+import com.android.systemui.keyguard.domain.interactor.DeviceEntrySideFpsOverlayInteractor
+import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor
+import com.android.systemui.keyguard.ui.viewmodel.SideFpsProgressBarViewModel
+import com.android.systemui.log.SideFpsLogger
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.res.R
+import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.unfold.compat.ScreenSizeFoldProvider
+import com.android.systemui.user.domain.interactor.SelectedUserInteractor
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.time.FakeSystemClock
+import com.google.common.truth.Truth.assertThat
+import java.util.Optional
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.Mock
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.spy
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class SideFpsOverlayViewModelTest : SysuiTestCase() {
+    @JvmField @Rule var mockitoRule: MockitoRule = MockitoJUnit.rule()
+
+    @Mock private lateinit var activityTaskManager: ActivityTaskManager
+    @Mock private lateinit var faceAuthInteractor: KeyguardFaceAuthInteractor
+    @Mock
+    private lateinit var fingerprintInteractiveToAuthProvider: FingerprintInteractiveToAuthProvider
+    @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
+    @Mock private lateinit var screenSizeFoldProvider: ScreenSizeFoldProvider
+    @Mock private lateinit var selectedUserInteractor: SelectedUserInteractor
+    @Mock private lateinit var windowManager: WindowManager
+
+    private val contextDisplayInfo = DisplayInfo()
+
+    private val bouncerRepository = FakeKeyguardBouncerRepository()
+    private val biometricSettingsRepository = FakeBiometricSettingsRepository()
+    private val biometricStatusRepository = FakeBiometricStatusRepository()
+    private val deviceEntryFingerprintAuthRepository = FakeDeviceEntryFingerprintAuthRepository()
+    private val displayRepository = FakeDisplayRepository()
+    private val displayStateRepository = FakeDisplayStateRepository()
+    private val fingerprintPropertyRepository = FakeFingerprintPropertyRepository()
+
+    private val indicatorColor =
+        Utils.getColorAttrDefaultColor(
+            context,
+            com.android.internal.R.attr.materialColorPrimaryFixed
+        )
+    private val outerRimColor =
+        Utils.getColorAttrDefaultColor(
+            context,
+            com.android.internal.R.attr.materialColorPrimaryFixedDim
+        )
+    private val chevronFill =
+        Utils.getColorAttrDefaultColor(
+            context,
+            com.android.internal.R.attr.materialColorOnPrimaryFixed
+        )
+    private val color_blue400 =
+        context.getColor(com.android.settingslib.color.R.color.settingslib_color_blue400)
+
+    private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
+    private lateinit var biometricStatusInteractor: BiometricStatusInteractor
+    private lateinit var deviceEntrySideFpsOverlayInteractor: DeviceEntrySideFpsOverlayInteractor
+    private lateinit var displayStateInteractor: DisplayStateInteractorImpl
+    private lateinit var primaryBouncerInteractor: PrimaryBouncerInteractor
+    private lateinit var sfpsSensorInteractor: SideFpsSensorInteractor
+
+    private lateinit var sideFpsProgressBarViewModel: SideFpsProgressBarViewModel
+
+    private lateinit var underTest: SideFpsOverlayViewModel
+
+    private var displayWidth: Int = 0
+    private var displayHeight: Int = 0
+    private var boundsWidth: Int = 0
+    private var boundsHeight: Int = 0
+
+    private lateinit var deviceConfig: DeviceConfig
+    private lateinit var sensorLocation: SensorLocationInternal
+
+    private val testScope = TestScope(StandardTestDispatcher())
+    private val fakeExecutor = FakeExecutor(FakeSystemClock())
+
+    enum class DeviceConfig {
+        X_ALIGNED,
+        Y_ALIGNED,
+    }
+
+    @Before
+    fun setup() {
+        mSetFlagsRule.enableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
+
+        mContext = spy(mContext)
+
+        val resources = mContext.resources
+        whenever(mContext.display)
+            .thenReturn(
+                Display(mock(DisplayManagerGlobal::class.java), 1, contextDisplayInfo, resources)
+            )
+
+        alternateBouncerInteractor =
+            AlternateBouncerInteractor(
+                mock(StatusBarStateController::class.java),
+                mock(KeyguardStateController::class.java),
+                bouncerRepository,
+                fingerprintPropertyRepository,
+                biometricSettingsRepository,
+                FakeSystemClock(),
+                keyguardUpdateMonitor,
+                testScope.backgroundScope,
+            )
+
+        biometricStatusInteractor =
+            BiometricStatusInteractorImpl(activityTaskManager, biometricStatusRepository)
+
+        displayStateInteractor =
+            DisplayStateInteractorImpl(
+                testScope.backgroundScope,
+                mContext,
+                fakeExecutor,
+                displayStateRepository,
+                displayRepository,
+            )
+        displayStateInteractor.setScreenSizeFoldProvider(screenSizeFoldProvider)
+
+        primaryBouncerInteractor =
+            PrimaryBouncerInteractor(
+                bouncerRepository,
+                mock(BouncerView::class.java),
+                mock(Handler::class.java),
+                mock(KeyguardStateController::class.java),
+                mock(KeyguardSecurityModel::class.java),
+                mock(PrimaryBouncerCallbackInteractor::class.java),
+                mock(FalsingCollector::class.java),
+                mock(DismissCallbackRegistry::class.java),
+                mContext,
+                keyguardUpdateMonitor,
+                FakeTrustRepository(),
+                testScope.backgroundScope,
+                selectedUserInteractor,
+                faceAuthInteractor
+            )
+
+        deviceEntrySideFpsOverlayInteractor =
+            DeviceEntrySideFpsOverlayInteractor(
+                mContext,
+                deviceEntryFingerprintAuthRepository,
+                primaryBouncerInteractor,
+                alternateBouncerInteractor,
+                keyguardUpdateMonitor
+            )
+
+        whenever(fingerprintInteractiveToAuthProvider.enabledForCurrentUser)
+            .thenReturn(MutableStateFlow(false))
+
+        sfpsSensorInteractor =
+            SideFpsSensorInteractor(
+                mContext,
+                fingerprintPropertyRepository,
+                windowManager,
+                displayStateInteractor,
+                Optional.of(fingerprintInteractiveToAuthProvider),
+                SideFpsLogger(logcatLogBuffer("SfpsLogger"))
+            )
+
+        sideFpsProgressBarViewModel =
+            SideFpsProgressBarViewModel(
+                mContext,
+                deviceEntryFingerprintAuthRepository,
+                sfpsSensorInteractor,
+                displayStateInteractor,
+                testScope.backgroundScope,
+            )
+
+        underTest =
+            SideFpsOverlayViewModel(
+                mContext,
+                biometricStatusInteractor,
+                deviceEntrySideFpsOverlayInteractor,
+                displayStateInteractor,
+                sfpsSensorInteractor,
+                sideFpsProgressBarViewModel,
+            )
+    }
+
+    @Test
+    fun updatesOverlayViewProperties_onDisplayRotationChange_xAlignedSensor() {
+        testScope.runTest {
+            setupTestConfiguration(
+                DeviceConfig.X_ALIGNED,
+                rotation = DisplayRotation.ROTATION_0,
+                isInRearDisplayMode = false
+            )
+
+            val overlayViewProperties by collectLastValue(underTest.overlayViewProperties)
+
+            runCurrent()
+
+            assertThat(overlayViewProperties?.indicatorAsset).isEqualTo(R.raw.sfps_pulse_landscape)
+            assertThat(overlayViewProperties?.overlayViewRotation).isEqualTo(0f)
+
+            displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_90)
+
+            assertThat(overlayViewProperties?.indicatorAsset).isEqualTo(R.raw.sfps_pulse)
+            assertThat(overlayViewProperties?.overlayViewRotation).isEqualTo(180f)
+
+            displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_180)
+
+            assertThat(overlayViewProperties?.indicatorAsset).isEqualTo(R.raw.sfps_pulse_landscape)
+            assertThat(overlayViewProperties?.overlayViewRotation).isEqualTo(180f)
+
+            displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_270)
+
+            assertThat(overlayViewProperties?.indicatorAsset).isEqualTo(R.raw.sfps_pulse)
+            assertThat(overlayViewProperties?.overlayViewRotation).isEqualTo(0f)
+        }
+    }
+
+    @Test
+    fun updatesOverlayViewProperties_onDisplayRotationChange_yAlignedSensor() {
+        testScope.runTest {
+            setupTestConfiguration(
+                DeviceConfig.Y_ALIGNED,
+                rotation = DisplayRotation.ROTATION_0,
+                isInRearDisplayMode = false
+            )
+
+            val overlayViewProperties by collectLastValue(underTest.overlayViewProperties)
+
+            runCurrent()
+
+            displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_0)
+            assertThat(overlayViewProperties?.indicatorAsset).isEqualTo(R.raw.sfps_pulse)
+            assertThat(overlayViewProperties?.overlayViewRotation).isEqualTo(0f)
+
+            displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_90)
+
+            assertThat(overlayViewProperties?.indicatorAsset).isEqualTo(R.raw.sfps_pulse_landscape)
+            assertThat(overlayViewProperties?.overlayViewRotation).isEqualTo(0f)
+
+            displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_180)
+            assertThat(overlayViewProperties?.indicatorAsset).isEqualTo(R.raw.sfps_pulse)
+            assertThat(overlayViewProperties?.overlayViewRotation).isEqualTo(180f)
+
+            displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_270)
+
+            assertThat(overlayViewProperties?.indicatorAsset).isEqualTo(R.raw.sfps_pulse_landscape)
+            assertThat(overlayViewProperties?.overlayViewRotation).isEqualTo(180f)
+        }
+    }
+
+    @Test
+    fun updatesOverlayViewParams_onDisplayRotationChange_xAlignedSensor() {
+        testScope.runTest {
+            setupTestConfiguration(
+                DeviceConfig.X_ALIGNED,
+                rotation = DisplayRotation.ROTATION_0,
+                isInRearDisplayMode = false
+            )
+
+            val overlayViewParams by collectLastValue(underTest.overlayViewParams)
+
+            underTest.setLottieBounds(Rect(0, 0, boundsWidth, boundsHeight))
+            runCurrent()
+
+            assertThat(overlayViewParams).isNotNull()
+            assertThat(overlayViewParams!!.x).isEqualTo(sensorLocation.sensorLocationX)
+            assertThat(overlayViewParams!!.y).isEqualTo(0)
+
+            displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_90)
+            assertThat(overlayViewParams).isNotNull()
+            assertThat(overlayViewParams!!.x).isEqualTo(0)
+            assertThat(overlayViewParams!!.y)
+                .isEqualTo(
+                    displayHeight - sensorLocation.sensorLocationX - sensorLocation.sensorRadius * 2
+                )
+
+            displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_180)
+            assertThat(overlayViewParams).isNotNull()
+            assertThat(overlayViewParams!!.x)
+                .isEqualTo(
+                    displayWidth - sensorLocation.sensorLocationX - sensorLocation.sensorRadius * 2
+                )
+            assertThat(overlayViewParams!!.y).isEqualTo(displayHeight - boundsHeight)
+
+            displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_270)
+            assertThat(overlayViewParams).isNotNull()
+            assertThat(overlayViewParams!!.x).isEqualTo(displayWidth - boundsWidth)
+            assertThat(overlayViewParams!!.y).isEqualTo(sensorLocation.sensorLocationX)
+        }
+    }
+
+    @Test
+    fun updatesOverlayViewParams_onDisplayRotationChange_yAlignedSensor() {
+        testScope.runTest {
+            setupTestConfiguration(
+                DeviceConfig.Y_ALIGNED,
+                rotation = DisplayRotation.ROTATION_0,
+                isInRearDisplayMode = false
+            )
+
+            val overlayViewParams by collectLastValue(underTest.overlayViewParams)
+
+            underTest.setLottieBounds(Rect(0, 0, boundsWidth, boundsHeight))
+            runCurrent()
+
+            assertThat(overlayViewParams).isNotNull()
+            assertThat(overlayViewParams!!.x).isEqualTo(displayWidth - boundsWidth)
+            assertThat(overlayViewParams!!.y).isEqualTo(sensorLocation.sensorLocationY)
+
+            displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_90)
+            assertThat(overlayViewParams).isNotNull()
+            assertThat(overlayViewParams!!.x).isEqualTo(sensorLocation.sensorLocationY)
+            assertThat(overlayViewParams!!.y).isEqualTo(0)
+
+            displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_180)
+            assertThat(overlayViewParams).isNotNull()
+            assertThat(overlayViewParams!!.x).isEqualTo(0)
+            assertThat(overlayViewParams!!.y)
+                .isEqualTo(
+                    displayHeight - sensorLocation.sensorLocationY - sensorLocation.sensorRadius * 2
+                )
+
+            displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_270)
+            assertThat(overlayViewParams).isNotNull()
+            assertThat(overlayViewParams!!.x)
+                .isEqualTo(
+                    displayWidth - sensorLocation.sensorLocationY - sensorLocation.sensorRadius * 2
+                )
+            assertThat(overlayViewParams!!.y).isEqualTo(displayHeight - boundsHeight)
+        }
+    }
+
+    @Test
+    fun updatesLottieCallbacks_onShowIndicatorForDeviceEntry() {
+        testScope.runTest {
+            val lottieCallbacks by collectLastValue(underTest.lottieCallbacks)
+
+            biometricStatusRepository.setFingerprintAuthenticationReason(
+                AuthenticationReason.NotRunning
+            )
+            sideFpsProgressBarViewModel.setVisible(false)
+
+            updatePrimaryBouncer(
+                isShowing = true,
+                isAnimatingAway = false,
+                fpsDetectionRunning = true,
+                isUnlockingWithFpAllowed = true
+            )
+            runCurrent()
+
+            assertThat(lottieCallbacks)
+                .contains(LottieCallback(KeyPath(".blue600", "**"), indicatorColor))
+            assertThat(lottieCallbacks)
+                .contains(LottieCallback(KeyPath(".blue400", "**"), outerRimColor))
+            assertThat(lottieCallbacks)
+                .contains(LottieCallback(KeyPath(".black", "**"), chevronFill))
+        }
+    }
+
+    @Test
+    fun updatesLottieCallbacks_onShowIndicatorForSystemServer_inDarkMode() {
+        testScope.runTest {
+            val lottieCallbacks by collectLastValue(underTest.lottieCallbacks)
+            setDarkMode(true)
+
+            biometricStatusRepository.setFingerprintAuthenticationReason(
+                AuthenticationReason.BiometricPromptAuthentication
+            )
+            sideFpsProgressBarViewModel.setVisible(false)
+
+            updatePrimaryBouncer(
+                isShowing = false,
+                isAnimatingAway = false,
+                fpsDetectionRunning = true,
+                isUnlockingWithFpAllowed = true
+            )
+            runCurrent()
+
+            assertThat(lottieCallbacks)
+                .contains(LottieCallback(KeyPath(".blue600", "**"), color_blue400))
+            assertThat(lottieCallbacks)
+                .contains(LottieCallback(KeyPath(".blue400", "**"), color_blue400))
+        }
+    }
+
+    @Test
+    fun updatesLottieCallbacks_onShowIndicatorForSystemServer_inLightMode() {
+        testScope.runTest {
+            val lottieCallbacks by collectLastValue(underTest.lottieCallbacks)
+            setDarkMode(false)
+
+            biometricStatusRepository.setFingerprintAuthenticationReason(
+                AuthenticationReason.BiometricPromptAuthentication
+            )
+            sideFpsProgressBarViewModel.setVisible(false)
+
+            updatePrimaryBouncer(
+                isShowing = false,
+                isAnimatingAway = false,
+                fpsDetectionRunning = true,
+                isUnlockingWithFpAllowed = true
+            )
+            runCurrent()
+
+            assertThat(lottieCallbacks)
+                .contains(LottieCallback(KeyPath(".black", "**"), Color.WHITE))
+            assertThat(lottieCallbacks)
+                .contains(LottieCallback(KeyPath(".blue600", "**"), color_blue400))
+            assertThat(lottieCallbacks)
+                .contains(LottieCallback(KeyPath(".blue400", "**"), color_blue400))
+        }
+    }
+
+    private fun setDarkMode(inDarkMode: Boolean) {
+        val uiMode =
+            if (inDarkMode) {
+                UI_MODE_NIGHT_YES
+            } else {
+                UI_MODE_NIGHT_NO
+            }
+
+        mContext.resources.configuration.uiMode = uiMode
+    }
+
+    private fun updatePrimaryBouncer(
+        isShowing: Boolean,
+        isAnimatingAway: Boolean,
+        fpsDetectionRunning: Boolean,
+        isUnlockingWithFpAllowed: Boolean,
+    ) {
+        bouncerRepository.setPrimaryShow(isShowing)
+        bouncerRepository.setPrimaryStartingToHide(false)
+        val primaryStartDisappearAnimation = if (isAnimatingAway) Runnable {} else null
+        bouncerRepository.setPrimaryStartDisappearAnimation(primaryStartDisappearAnimation)
+
+        whenever(keyguardUpdateMonitor.isFingerprintDetectionRunning)
+            .thenReturn(fpsDetectionRunning)
+        whenever(keyguardUpdateMonitor.isUnlockingWithFingerprintAllowed)
+            .thenReturn(isUnlockingWithFpAllowed)
+        mContext.orCreateTestableResources.addOverride(
+            R.bool.config_show_sidefps_hint_on_bouncer,
+            true
+        )
+    }
+
+    private suspend fun TestScope.setupTestConfiguration(
+        deviceConfig: DeviceConfig,
+        rotation: DisplayRotation = DisplayRotation.ROTATION_0,
+        isInRearDisplayMode: Boolean,
+    ) {
+        this@SideFpsOverlayViewModelTest.deviceConfig = deviceConfig
+
+        when (deviceConfig) {
+            DeviceConfig.X_ALIGNED -> {
+                displayWidth = 3000
+                displayHeight = 1500
+                boundsWidth = 200
+                boundsHeight = 100
+                sensorLocation = SensorLocationInternal("", 2500, 0, boundsWidth / 2)
+            }
+            DeviceConfig.Y_ALIGNED -> {
+                displayWidth = 2500
+                displayHeight = 2000
+                boundsWidth = 100
+                boundsHeight = 200
+                sensorLocation = SensorLocationInternal("", displayWidth, 300, boundsHeight / 2)
+            }
+        }
+
+        whenever(windowManager.maximumWindowMetrics)
+            .thenReturn(
+                WindowMetrics(
+                    Rect(0, 0, displayWidth, displayHeight),
+                    mock(WindowInsets::class.java),
+                )
+            )
+
+        contextDisplayInfo.uniqueId = DISPLAY_ID
+
+        fingerprintPropertyRepository.setProperties(
+            sensorId = 1,
+            strength = SensorStrength.STRONG,
+            sensorType = FingerprintSensorType.POWER_BUTTON,
+            sensorLocations = mapOf(DISPLAY_ID to sensorLocation)
+        )
+
+        displayStateRepository.setIsInRearDisplayMode(isInRearDisplayMode)
+
+        displayStateRepository.setCurrentRotation(rotation)
+
+        displayRepository.emitDisplayChangeEvent(0)
+        runCurrent()
+    }
+
+    companion object {
+        private const val DISPLAY_ID = "displayId"
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractorTest.kt
index 094616f..aa0d7b6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractorTest.kt
@@ -35,7 +35,7 @@
 import com.android.systemui.bouncer.ui.BouncerView
 import com.android.systemui.classifier.FalsingCollector
 import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.FakeFeatureFlagsClassic
 import com.android.systemui.flags.Flags
 import com.android.systemui.flags.SystemPropertiesHelper
 import com.android.systemui.keyguard.DismissCallbackRegistry
@@ -62,7 +62,6 @@
 import org.junit.runner.RunWith
 import org.mockito.ArgumentMatchers.eq
 import org.mockito.Mock
-import org.mockito.Mockito
 import org.mockito.Mockito.mock
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
@@ -108,17 +107,18 @@
 
     suspend fun TestScope.init() {
         userRepository.setSelectedUserInfo(PRIMARY_USER)
-        val featureFlags = FakeFeatureFlags().apply { set(Flags.REVAMPED_BOUNCER_MESSAGES, true) }
+        val featureFlags =
+            FakeFeatureFlagsClassic().apply { set(Flags.REVAMPED_BOUNCER_MESSAGES, true) }
         primaryBouncerInteractor =
             PrimaryBouncerInteractor(
                 bouncerRepository,
-                Mockito.mock(BouncerView::class.java),
-                Mockito.mock(Handler::class.java),
-                Mockito.mock(KeyguardStateController::class.java),
-                Mockito.mock(KeyguardSecurityModel::class.java),
-                Mockito.mock(PrimaryBouncerCallbackInteractor::class.java),
-                Mockito.mock(FalsingCollector::class.java),
-                Mockito.mock(DismissCallbackRegistry::class.java),
+                mock(BouncerView::class.java),
+                mock(Handler::class.java),
+                mock(KeyguardStateController::class.java),
+                mock(KeyguardSecurityModel::class.java),
+                mock(PrimaryBouncerCallbackInteractor::class.java),
+                mock(FalsingCollector::class.java),
+                mock(DismissCallbackRegistry::class.java),
                 context,
                 keyguardUpdateMonitor,
                 fakeTrustRepository,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorTest.kt
index 37a093e..dacf23a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorTest.kt
@@ -37,6 +37,7 @@
 import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.res.R
+import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.user.domain.interactor.SelectedUserInteractor
 import com.android.systemui.util.mockito.any
@@ -342,6 +343,7 @@
         assertThat(underTest.willDismissWithAction()).isFalse()
     }
 
+    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
     @Test
     fun testSideFpsVisibility() {
         updateSideFpsVisibilityParameters(
@@ -355,6 +357,7 @@
         verify(repository).setSideFpsShowing(true)
     }
 
+    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
     @Test
     fun testSideFpsVisibility_notVisible() {
         updateSideFpsVisibilityParameters(
@@ -368,6 +371,7 @@
         verify(repository).setSideFpsShowing(false)
     }
 
+    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
     @Test
     fun testSideFpsVisibility_sfpsNotEnabled() {
         updateSideFpsVisibilityParameters(
@@ -381,6 +385,7 @@
         verify(repository).setSideFpsShowing(false)
     }
 
+    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
     @Test
     fun testSideFpsVisibility_fpsDetectionNotRunning() {
         updateSideFpsVisibilityParameters(
@@ -394,6 +399,7 @@
         verify(repository).setSideFpsShowing(false)
     }
 
+    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
     @Test
     fun testSideFpsVisibility_UnlockingWithFpNotAllowed() {
         updateSideFpsVisibilityParameters(
@@ -407,6 +413,7 @@
         verify(repository).setSideFpsShowing(false)
     }
 
+    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
     @Test
     fun testSideFpsVisibility_AnimatingAway() {
         updateSideFpsVisibilityParameters(
@@ -492,6 +499,7 @@
         isUnlockingWithFpAllowed: Boolean,
         isAnimatingAway: Boolean
     ) {
+        mSetFlagsRule.disableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
         whenever(repository.primaryBouncerShow.value).thenReturn(isVisible)
         resources.addOverride(R.bool.config_show_sidefps_hint_on_bouncer, sfpsEnabled)
         whenever(keyguardUpdateMonitor.isFingerprintDetectionRunning)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/helper/BouncerSceneLayoutTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/helper/BouncerSceneLayoutTest.kt
index 395d712..ca95822 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/helper/BouncerSceneLayoutTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/helper/BouncerSceneLayoutTest.kt
@@ -18,10 +18,10 @@
 
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.bouncer.ui.helper.BouncerSceneLayout.SIDE_BY_SIDE
-import com.android.systemui.bouncer.ui.helper.BouncerSceneLayout.SPLIT
-import com.android.systemui.bouncer.ui.helper.BouncerSceneLayout.STACKED
-import com.android.systemui.bouncer.ui.helper.BouncerSceneLayout.STANDARD
+import com.android.systemui.bouncer.ui.helper.BouncerSceneLayout.BELOW_USER_SWITCHER
+import com.android.systemui.bouncer.ui.helper.BouncerSceneLayout.BESIDE_USER_SWITCHER
+import com.android.systemui.bouncer.ui.helper.BouncerSceneLayout.SPLIT_BOUNCER
+import com.android.systemui.bouncer.ui.helper.BouncerSceneLayout.STANDARD_BOUNCER
 import com.google.common.truth.Truth.assertThat
 import java.util.Locale
 import org.junit.Test
@@ -84,33 +84,33 @@
             listOf(
                     Phone to
                         Expected(
-                            whenNaturallyHeld = STANDARD,
-                            whenUnnaturallyHeld = SPLIT,
+                            whenNaturallyHeld = STANDARD_BOUNCER,
+                            whenUnnaturallyHeld = SPLIT_BOUNCER,
                         ),
                     Tablet to
                         Expected(
-                            whenNaturallyHeld = SIDE_BY_SIDE,
-                            whenUnnaturallyHeld = STACKED,
+                            whenNaturallyHeld = BESIDE_USER_SWITCHER,
+                            whenUnnaturallyHeld = BELOW_USER_SWITCHER,
                         ),
                     Folded to
                         Expected(
-                            whenNaturallyHeld = STANDARD,
-                            whenUnnaturallyHeld = SPLIT,
+                            whenNaturallyHeld = STANDARD_BOUNCER,
+                            whenUnnaturallyHeld = SPLIT_BOUNCER,
                         ),
                     Unfolded to
                         Expected(
-                            whenNaturallyHeld = SIDE_BY_SIDE,
-                            whenUnnaturallyHeld = STANDARD,
+                            whenNaturallyHeld = BESIDE_USER_SWITCHER,
+                            whenUnnaturallyHeld = STANDARD_BOUNCER,
                         ),
                     TallerFolded to
                         Expected(
-                            whenNaturallyHeld = STANDARD,
-                            whenUnnaturallyHeld = SPLIT,
+                            whenNaturallyHeld = STANDARD_BOUNCER,
+                            whenUnnaturallyHeld = SPLIT_BOUNCER,
                         ),
                     TallerUnfolded to
                         Expected(
-                            whenNaturallyHeld = SIDE_BY_SIDE,
-                            whenUnnaturallyHeld = SIDE_BY_SIDE,
+                            whenNaturallyHeld = BESIDE_USER_SWITCHER,
+                            whenUnnaturallyHeld = BESIDE_USER_SWITCHER,
                         ),
                 )
                 .flatMap { (device, expected) ->
@@ -124,13 +124,13 @@
                             )
                         )
 
-                        if (expected.whenNaturallyHeld == SIDE_BY_SIDE) {
+                        if (expected.whenNaturallyHeld == BESIDE_USER_SWITCHER) {
                             add(
                                 TestCase(
                                     device = device,
                                     held = device.naturallyHeld,
                                     isSideBySideSupported = false,
-                                    expected = STANDARD,
+                                    expected = STANDARD_BOUNCER,
                                 )
                             )
                         }
@@ -144,13 +144,13 @@
                             )
                         )
 
-                        if (expected.whenUnnaturallyHeld == SIDE_BY_SIDE) {
+                        if (expected.whenUnnaturallyHeld == BESIDE_USER_SWITCHER) {
                             add(
                                 TestCase(
                                     device = device,
                                     held = device.naturallyHeld.flip(),
                                     isSideBySideSupported = false,
-                                    expected = STANDARD,
+                                    expected = STANDARD_BOUNCER,
                                 )
                             )
                         }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/complication/DreamHomeControlsComplicationTest.java b/packages/SystemUI/tests/src/com/android/systemui/complication/DreamHomeControlsComplicationTest.java
index 2207180..07c980b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/complication/DreamHomeControlsComplicationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/complication/DreamHomeControlsComplicationTest.java
@@ -21,14 +21,13 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.content.ComponentName;
-import android.content.Context;
 import android.content.res.Resources;
 import android.testing.AndroidTestingRunner;
 import android.view.View;
@@ -48,6 +47,7 @@
 import com.android.systemui.dreams.DreamOverlayStateController;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.shared.condition.Monitor;
+import com.android.systemui.statusbar.policy.ConfigurationController;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -71,9 +71,6 @@
     private DreamOverlayStateController mDreamOverlayStateController;
 
     @Mock
-    private Context mContext;
-
-    @Mock
     private Resources mResources;
 
     @Mock
@@ -100,6 +97,9 @@
     @Mock
     private UiEventLogger mUiEventLogger;
 
+    @Mock
+    private ConfigurationController mConfigurationController;
+
     @Captor
     private ArgumentCaptor<DreamOverlayStateController.Callback> mStateCallbackCaptor;
 
@@ -109,7 +109,8 @@
     public void setup() {
         MockitoAnnotations.initMocks(this);
 
-        when(mContext.getString(anyInt())).thenReturn("");
+        mContext.ensureTestableResources();
+
         when(mControlsComponent.getControlsController()).thenReturn(
                 Optional.of(mControlsController));
         when(mControlsComponent.getControlsListingController()).thenReturn(
@@ -225,6 +226,7 @@
                         mHomeControlsView,
                         mActivityStarter,
                         mContext,
+                        mConfigurationController,
                         mControlsComponent,
                         mUiEventLogger);
         viewController.onViewAttached();
@@ -237,6 +239,24 @@
         verify(mUiEventLogger).log(DreamOverlayUiEvent.DREAM_HOME_CONTROLS_TAPPED);
     }
 
+    @Test
+    public void testUnregistersConfigurationCallback() {
+        final DreamHomeControlsComplication.DreamHomeControlsChipViewController viewController =
+                new DreamHomeControlsComplication.DreamHomeControlsChipViewController(
+                        mHomeControlsView,
+                        mActivityStarter,
+                        mContext,
+                        mConfigurationController,
+                        mControlsComponent,
+                        mUiEventLogger);
+        viewController.onViewAttached();
+        verify(mConfigurationController).addCallback(any());
+        verify(mConfigurationController, never()).removeCallback(any());
+
+        viewController.onViewDetached();
+        verify(mConfigurationController).removeCallback(any());
+    }
+
     private void setHaveFavorites(boolean value) {
         final List<StructureInfo> favorites = mock(List.class);
         when(favorites.isEmpty()).thenReturn(!value);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/contrast/ContrastDialogDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/contrast/ContrastDialogDelegateTest.kt
index e931384..65f68f9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/contrast/ContrastDialogDelegateTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/contrast/ContrastDialogDelegateTest.kt
@@ -22,6 +22,7 @@
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper.RunWithLooper
 import android.view.LayoutInflater
+import android.view.View
 import android.widget.FrameLayout
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
@@ -39,6 +40,8 @@
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.Mock
 import org.mockito.Mockito.eq
 import org.mockito.Mockito.verify
@@ -73,13 +76,20 @@
         if (Looper.myLooper() == null) Looper.prepare()
 
         mContrastDialogDelegate =
-                ContrastDialogDelegate(
-                        sysuiDialogFactory,
-                        mainExecutor,
-                        mockUiModeManager,
-                        mockUserTracker,
-                        mockSecureSettings
-                )
+            ContrastDialogDelegate(
+                sysuiDialogFactory,
+                mainExecutor,
+                mockUiModeManager,
+                mockUserTracker,
+                mockSecureSettings
+            )
+
+        mContrastDialogDelegate.createDialog()
+        val viewCaptor = ArgumentCaptor.forClass(View::class.java)
+        verify(sysuiDialog).setView(viewCaptor.capture())
+        whenever(sysuiDialog.requireViewById(anyInt()) as View?).then {
+            viewCaptor.value.requireViewById(it.getArgument(0))
+        }
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsInteractorTest.kt
index 9b8e581..59bcf01 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsInteractorTest.kt
@@ -18,157 +18,165 @@
 
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
-import com.android.keyguard.logging.BiometricUnlockLogger
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository
+import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository
 import com.android.systemui.biometrics.shared.model.FingerprintSensorType
 import com.android.systemui.biometrics.shared.model.SensorStrength
-import com.android.systemui.classifier.FalsingCollector
 import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.deviceentry.domain.interactor.DeviceEntryHapticsInteractor
-import com.android.systemui.keyevent.data.repository.FakeKeyEventRepository
-import com.android.systemui.keyevent.domain.interactor.KeyEventInteractor
-import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
-import com.android.systemui.plugins.statusbar.StatusBarStateController
-import com.android.systemui.power.data.repository.FakePowerRepository
-import com.android.systemui.power.domain.interactor.PowerInteractor
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryHapticsInteractor
+import com.android.systemui.keyevent.data.repository.fakeKeyEventRepository
+import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
+import com.android.systemui.keyguard.data.repository.deviceEntryFingerprintAuthRepository
+import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFaceAuthRepository
+import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
+import com.android.systemui.keyguard.shared.model.FailFingerprintAuthenticationStatus
+import com.android.systemui.keyguard.shared.model.FailedFaceAuthenticationStatus
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.power.data.repository.powerRepository
 import com.android.systemui.power.shared.model.WakeSleepReason
 import com.android.systemui.power.shared.model.WakefulnessState
-import com.android.systemui.statusbar.phone.ScreenOffAnimationController
-import com.android.systemui.util.time.FakeSystemClock
+import com.android.systemui.testKosmos
+import com.android.systemui.util.time.fakeSystemClock
 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
-import org.mockito.Mockito.mock
 
 @OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class DeviceEntryHapticsInteractorTest : SysuiTestCase() {
-
-    private lateinit var repository: DeviceEntryHapticsRepository
-    private lateinit var fingerprintPropertyRepository: FakeFingerprintPropertyRepository
-    private lateinit var biometricSettingsRepository: FakeBiometricSettingsRepository
-    private lateinit var keyEventRepository: FakeKeyEventRepository
-    private lateinit var powerRepository: FakePowerRepository
-    private lateinit var systemClock: FakeSystemClock
-    private lateinit var underTest: DeviceEntryHapticsInteractor
-
-    @Before
-    fun setUp() {
-        repository = DeviceEntryHapticsRepositoryImpl()
-        fingerprintPropertyRepository = FakeFingerprintPropertyRepository()
-        biometricSettingsRepository = FakeBiometricSettingsRepository()
-        keyEventRepository = FakeKeyEventRepository()
-        powerRepository = FakePowerRepository()
-        systemClock = FakeSystemClock()
-        underTest =
-            DeviceEntryHapticsInteractor(
-                repository = repository,
-                fingerprintPropertyRepository = fingerprintPropertyRepository,
-                biometricSettingsRepository = biometricSettingsRepository,
-                keyEventInteractor = KeyEventInteractor(keyEventRepository),
-                powerInteractor =
-                    PowerInteractor(
-                        powerRepository,
-                        mock(FalsingCollector::class.java),
-                        mock(ScreenOffAnimationController::class.java),
-                        mock(StatusBarStateController::class.java),
-                    ),
-                systemClock = systemClock,
-                logger = mock(BiometricUnlockLogger::class.java),
-            )
-    }
+    private val kosmos = testKosmos()
+    private val testScope = kosmos.testScope
+    private val underTest = kosmos.deviceEntryHapticsInteractor
 
     @Test
-    fun nonPowerButtonFPS_vibrateSuccess() = runTest {
-        val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic)
-        setFingerprintSensorType(FingerprintSensorType.UDFPS_ULTRASONIC)
-        underTest.vibrateSuccess()
-        assertThat(playSuccessHaptic).isTrue()
-    }
+    fun nonPowerButtonFPS_vibrateSuccess() =
+        testScope.runTest {
+            val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic)
+            setFingerprintSensorType(FingerprintSensorType.UDFPS_ULTRASONIC)
+            runCurrent()
+            enterDeviceFromBiometricUnlock()
+            assertThat(playSuccessHaptic).isNotNull()
+        }
 
     @Test
-    fun powerButtonFPS_vibrateSuccess() = runTest {
-        val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic)
-        setPowerButtonFingerprintProperty()
-        setFingerprintEnrolled()
-        keyEventRepository.setPowerButtonDown(false)
+    fun powerButtonFPS_vibrateSuccess() =
+        testScope.runTest {
+            val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic)
+            setPowerButtonFingerprintProperty()
+            setFingerprintEnrolled()
+            kosmos.fakeKeyEventRepository.setPowerButtonDown(false)
 
-        // It's been 10 seconds since the last power button wakeup
-        setAwakeFromPowerButton()
-        runCurrent()
-        systemClock.setUptimeMillis(systemClock.uptimeMillis() + 10000)
+            // It's been 10 seconds since the last power button wakeup
+            setAwakeFromPowerButton()
+            runCurrent()
+            kosmos.fakeSystemClock.setUptimeMillis(kosmos.fakeSystemClock.uptimeMillis() + 10000)
 
-        underTest.vibrateSuccess()
-        assertThat(playSuccessHaptic).isTrue()
-    }
+            enterDeviceFromBiometricUnlock()
+            assertThat(playSuccessHaptic).isNotNull()
+        }
 
     @Test
-    fun powerButtonFPS_powerDown_doNotVibrateSuccess() = runTest {
-        val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic)
-        setPowerButtonFingerprintProperty()
-        setFingerprintEnrolled()
-        keyEventRepository.setPowerButtonDown(true) // power button is currently DOWN
+    fun powerButtonFPS_powerDown_doNotVibrateSuccess() =
+        testScope.runTest {
+            val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic)
+            setPowerButtonFingerprintProperty()
+            setFingerprintEnrolled()
+            kosmos.fakeKeyEventRepository.setPowerButtonDown(true) // power button is currently DOWN
 
-        // It's been 10 seconds since the last power button wakeup
-        setAwakeFromPowerButton()
-        runCurrent()
-        systemClock.setUptimeMillis(systemClock.uptimeMillis() + 10000)
+            // It's been 10 seconds since the last power button wakeup
+            setAwakeFromPowerButton()
+            runCurrent()
+            kosmos.fakeSystemClock.setUptimeMillis(kosmos.fakeSystemClock.uptimeMillis() + 10000)
 
-        underTest.vibrateSuccess()
-        assertThat(playSuccessHaptic).isFalse()
-    }
+            enterDeviceFromBiometricUnlock()
+            assertThat(playSuccessHaptic).isNull()
+        }
 
     @Test
-    fun powerButtonFPS_powerButtonRecentlyPressed_doNotVibrateSuccess() = runTest {
-        val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic)
-        setPowerButtonFingerprintProperty()
-        setFingerprintEnrolled()
-        keyEventRepository.setPowerButtonDown(false)
+    fun powerButtonFPS_powerButtonRecentlyPressed_doNotVibrateSuccess() =
+        testScope.runTest {
+            val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic)
+            setPowerButtonFingerprintProperty()
+            setFingerprintEnrolled()
+            kosmos.fakeKeyEventRepository.setPowerButtonDown(false)
 
-        // It's only been 50ms since the last power button wakeup
-        setAwakeFromPowerButton()
-        runCurrent()
-        systemClock.setUptimeMillis(systemClock.uptimeMillis() + 50)
+            // It's only been 50ms since the last power button wakeup
+            setAwakeFromPowerButton()
+            runCurrent()
+            kosmos.fakeSystemClock.setUptimeMillis(kosmos.fakeSystemClock.uptimeMillis() + 50)
 
-        underTest.vibrateSuccess()
-        assertThat(playSuccessHaptic).isFalse()
-    }
+            enterDeviceFromBiometricUnlock()
+            assertThat(playSuccessHaptic).isNull()
+        }
 
     @Test
-    fun nonPowerButtonFPS_vibrateError() = runTest {
-        val playErrorHaptic by collectLastValue(underTest.playErrorHaptic)
-        setFingerprintSensorType(FingerprintSensorType.UDFPS_ULTRASONIC)
-        underTest.vibrateError()
-        assertThat(playErrorHaptic).isTrue()
-    }
+    fun nonPowerButtonFPS_vibrateError() =
+        testScope.runTest {
+            val playErrorHaptic by collectLastValue(underTest.playErrorHaptic)
+            setFingerprintSensorType(FingerprintSensorType.UDFPS_ULTRASONIC)
+            runCurrent()
+            fingerprintFailure()
+            assertThat(playErrorHaptic).isNotNull()
+        }
 
     @Test
-    fun powerButtonFPS_vibrateError() = runTest {
-        val playErrorHaptic by collectLastValue(underTest.playErrorHaptic)
-        setPowerButtonFingerprintProperty()
-        setFingerprintEnrolled()
-        underTest.vibrateError()
-        assertThat(playErrorHaptic).isTrue()
-    }
+    fun nonPowerButtonFPS_coExFaceFailure_doNotVibrateError() =
+        testScope.runTest {
+            val playErrorHaptic by collectLastValue(underTest.playErrorHaptic)
+            setFingerprintSensorType(FingerprintSensorType.UDFPS_ULTRASONIC)
+            coExEnrolledAndEnabled()
+            runCurrent()
+            faceFailure()
+            assertThat(playErrorHaptic).isNull()
+        }
 
     @Test
-    fun powerButtonFPS_powerDown_doNotVibrateError() = runTest {
-        val playErrorHaptic by collectLastValue(underTest.playErrorHaptic)
-        setPowerButtonFingerprintProperty()
-        setFingerprintEnrolled()
-        keyEventRepository.setPowerButtonDown(true)
-        underTest.vibrateError()
-        assertThat(playErrorHaptic).isFalse()
+    fun powerButtonFPS_vibrateError() =
+        testScope.runTest {
+            val playErrorHaptic by collectLastValue(underTest.playErrorHaptic)
+            setPowerButtonFingerprintProperty()
+            setFingerprintEnrolled()
+            runCurrent()
+            fingerprintFailure()
+            assertThat(playErrorHaptic).isNotNull()
+        }
+
+    @Test
+    fun powerButtonFPS_powerDown_doNotVibrateError() =
+        testScope.runTest {
+            val playErrorHaptic by collectLastValue(underTest.playErrorHaptic)
+            setPowerButtonFingerprintProperty()
+            setFingerprintEnrolled()
+            kosmos.fakeKeyEventRepository.setPowerButtonDown(true)
+            runCurrent()
+            fingerprintFailure()
+            assertThat(playErrorHaptic).isNull()
+        }
+
+    private suspend fun enterDeviceFromBiometricUnlock() {
+        kosmos.fakeDeviceEntryRepository.enteringDeviceFromBiometricUnlock(
+            BiometricUnlockSource.FINGERPRINT_SENSOR
+        )
+    }
+
+    private fun fingerprintFailure() {
+        kosmos.deviceEntryFingerprintAuthRepository.setAuthenticationStatus(
+            FailFingerprintAuthenticationStatus
+        )
+    }
+
+    private fun faceFailure() {
+        kosmos.fakeDeviceEntryFaceAuthRepository.setAuthenticationStatus(
+            FailedFaceAuthenticationStatus()
+        )
     }
 
     private fun setFingerprintSensorType(fingerprintSensorType: FingerprintSensorType) {
-        fingerprintPropertyRepository.setProperties(
+        kosmos.fingerprintPropertyRepository.setProperties(
             sensorId = 0,
             strength = SensorStrength.STRONG,
             sensorType = fingerprintSensorType,
@@ -181,15 +189,20 @@
     }
 
     private fun setFingerprintEnrolled() {
-        biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(true)
+        kosmos.biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(true)
     }
 
     private fun setAwakeFromPowerButton() {
-        powerRepository.updateWakefulness(
+        kosmos.powerRepository.updateWakefulness(
             WakefulnessState.AWAKE,
             WakeSleepReason.POWER_BUTTON,
             WakeSleepReason.POWER_BUTTON,
             powerButtonLaunchGestureTriggered = false,
         )
     }
+
+    private fun coExEnrolledAndEnabled() {
+        setFingerprintEnrolled()
+        kosmos.biometricSettingsRepository.setIsFaceAuthEnrolledAndEnabled(true)
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractorTest.kt
index 42b0f50..37c7409 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractorTest.kt
@@ -18,6 +18,7 @@
 
 import android.companion.virtual.VirtualDeviceManager
 import android.companion.virtual.flags.Flags.FLAG_INTERACTIVE_SCREEN_MIRROR
+import android.platform.test.annotations.EnableFlags
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
 import android.view.Display
@@ -75,7 +76,6 @@
 
     @Before
     fun setup() {
-        mSetFlagsRule.disableFlags(FLAG_INTERACTIVE_SCREEN_MIRROR)
         whenever(virtualDeviceManager.isVirtualDeviceOwnedMirrorDisplay(anyInt())).thenReturn(false)
         fakeKeyguardRepository.setKeyguardShowing(false)
     }
@@ -160,9 +160,9 @@
         }
 
     @Test
+    @EnableFlags(FLAG_INTERACTIVE_SCREEN_MIRROR)
     fun displayState_virtualDeviceOwnedMirrorVirtualDisplay_connected() =
         testScope.runTest {
-            mSetFlagsRule.enableFlags(FLAG_INTERACTIVE_SCREEN_MIRROR)
             whenever(virtualDeviceManager.isVirtualDeviceOwnedMirrorDisplay(anyInt()))
                 .thenReturn(true)
             val value by lastValue()
@@ -183,9 +183,9 @@
         }
 
     @Test
+    @EnableFlags(FLAG_INTERACTIVE_SCREEN_MIRROR)
     fun virtualDeviceOwnedMirrorVirtualDisplay_emitsConnectedDisplayAddition() =
         testScope.runTest {
-            mSetFlagsRule.enableFlags(FLAG_INTERACTIVE_SCREEN_MIRROR)
             whenever(virtualDeviceManager.isVirtualDeviceOwnedMirrorDisplay(anyInt()))
                 .thenReturn(true)
             var count = 0
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsClassicDebugTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsClassicDebugTest.kt
index a903d25..523127e0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsClassicDebugTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsClassicDebugTest.kt
@@ -21,6 +21,8 @@
 import android.content.pm.PackageManager.NameNotFoundException
 import android.content.res.Resources
 import android.content.res.Resources.NotFoundException
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
 import android.test.suitebuilder.annotation.SmallTest
 import com.android.systemui.Flags.FLAG_SYSUI_TEAMFOOD
 import com.android.systemui.SysuiTestCase
@@ -68,15 +70,14 @@
     private val serverFlagReader = ServerFlagReaderFake()
 
     private val teamfoodableFlagA = UnreleasedFlag(name = "a", namespace = "test", teamfood = true)
-    private val teamfoodableFlagB = ReleasedFlag(name = "b", namespace = "test", teamfood = true)
+    private val releasedFlagB = ReleasedFlag(name = "b", namespace = "test")
 
     @Before
     fun setup() {
         MockitoAnnotations.initMocks(this)
-        mSetFlagsRule.disableFlags(FLAG_SYSUI_TEAMFOOD)
 
         flagMap.put(teamfoodableFlagA.name, teamfoodableFlagA)
-        flagMap.put(teamfoodableFlagB.name, teamfoodableFlagB)
+        flagMap.put(releasedFlagB.name, releasedFlagB)
         mFeatureFlagsClassicDebug =
             FeatureFlagsClassicDebug(
                 flagManager,
@@ -99,7 +100,6 @@
 
     @Test
     fun readBooleanFlag() {
-        // Remember that the TEAMFOOD flag is id#1 and has special behavior.
         whenever(flagManager.readFlagValue<Boolean>(eq("3"), any())).thenReturn(true)
         whenever(flagManager.readFlagValue<Boolean>(eq("4"), any())).thenReturn(false)
 
@@ -122,9 +122,10 @@
     }
 
     @Test
+    @DisableFlags(FLAG_SYSUI_TEAMFOOD)
     fun teamFoodFlag_False() {
         assertThat(mFeatureFlagsClassicDebug.isEnabled(teamfoodableFlagA)).isFalse()
-        assertThat(mFeatureFlagsClassicDebug.isEnabled(teamfoodableFlagB)).isTrue()
+        assertThat(mFeatureFlagsClassicDebug.isEnabled(releasedFlagB)).isTrue()
 
         // Regular boolean flags should still test the same.
         // Only our teamfoodableFlag should change.
@@ -132,10 +133,10 @@
     }
 
     @Test
+    @EnableFlags(FLAG_SYSUI_TEAMFOOD)
     fun teamFoodFlag_True() {
-        mSetFlagsRule.enableFlags(FLAG_SYSUI_TEAMFOOD)
         assertThat(mFeatureFlagsClassicDebug.isEnabled(teamfoodableFlagA)).isTrue()
-        assertThat(mFeatureFlagsClassicDebug.isEnabled(teamfoodableFlagB)).isTrue()
+        assertThat(mFeatureFlagsClassicDebug.isEnabled(releasedFlagB)).isTrue()
 
         // Regular boolean flags should still test the same.
         // Only our teamfoodableFlag should change.
@@ -143,14 +144,14 @@
     }
 
     @Test
+    @EnableFlags(FLAG_SYSUI_TEAMFOOD)
     fun teamFoodFlag_Overridden() {
         whenever(flagManager.readFlagValue<Boolean>(eq(teamfoodableFlagA.name), any()))
             .thenReturn(true)
-        whenever(flagManager.readFlagValue<Boolean>(eq(teamfoodableFlagB.name), any()))
+        whenever(flagManager.readFlagValue<Boolean>(eq(releasedFlagB.name), any()))
             .thenReturn(false)
-        mSetFlagsRule.enableFlags(FLAG_SYSUI_TEAMFOOD)
         assertThat(mFeatureFlagsClassicDebug.isEnabled(teamfoodableFlagA)).isTrue()
-        assertThat(mFeatureFlagsClassicDebug.isEnabled(teamfoodableFlagB)).isFalse()
+        assertThat(mFeatureFlagsClassicDebug.isEnabled(releasedFlagB)).isFalse()
 
         // Regular boolean flags should still test the same.
         // Only our teamfoodableFlag should change.
@@ -400,6 +401,7 @@
     }
 
     @Test
+    @DisableFlags(FLAG_SYSUI_TEAMFOOD)
     fun serverSide_OverrideUncached_NoRestart() {
         // No one has read the flag, so it's not in the cache.
         serverFlagReader.setFlagValue(
@@ -411,6 +413,7 @@
     }
 
     @Test
+    @DisableFlags(FLAG_SYSUI_TEAMFOOD)
     fun serverSide_Override_Restarts() {
         // Read it to put it in the cache.
         mFeatureFlagsClassicDebug.isEnabled(teamfoodableFlagA)
@@ -423,6 +426,7 @@
     }
 
     @Test
+    @DisableFlags(FLAG_SYSUI_TEAMFOOD)
     fun serverSide_RedundantOverride_NoRestart() {
         // Read it to put it in the cache.
         mFeatureFlagsClassicDebug.isEnabled(teamfoodableFlagA)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProviderTest.kt
index 7750d25..ab6bc2c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProviderTest.kt
@@ -71,7 +71,7 @@
             VibrationEffect.startComposition()
                 .addPrimitive(
                     VibrationEffect.Composition.PRIMITIVE_CLICK,
-                    scaleAtBookends(config.maxVelocityToScale)
+                    sliderHapticFeedbackProvider.scaleOnEdgeCollision(config.maxVelocityToScale),
                 )
                 .compose()
 
@@ -86,7 +86,7 @@
             VibrationEffect.startComposition()
                 .addPrimitive(
                     VibrationEffect.Composition.PRIMITIVE_CLICK,
-                    scaleAtBookends(config.maxVelocityToScale)
+                    sliderHapticFeedbackProvider.scaleOnEdgeCollision(config.maxVelocityToScale)
                 )
                 .compose()
 
@@ -102,7 +102,7 @@
             VibrationEffect.startComposition()
                 .addPrimitive(
                     VibrationEffect.Composition.PRIMITIVE_CLICK,
-                    scaleAtBookends(config.maxVelocityToScale)
+                    sliderHapticFeedbackProvider.scaleOnEdgeCollision(config.maxVelocityToScale),
                 )
                 .compose()
 
@@ -117,7 +117,7 @@
             VibrationEffect.startComposition()
                 .addPrimitive(
                     VibrationEffect.Composition.PRIMITIVE_CLICK,
-                    scaleAtBookends(config.maxVelocityToScale)
+                    sliderHapticFeedbackProvider.scaleOnEdgeCollision(config.maxVelocityToScale),
                 )
                 .compose()
 
@@ -132,7 +132,11 @@
     fun playHapticAtProgress_onQuickSuccession_playsLowTicksOnce() {
         // GIVEN max velocity and slider progress
         val progress = 1f
-        val expectedScale = scaleAtProgressChange(config.maxVelocityToScale.toFloat(), progress)
+        val expectedScale =
+            sliderHapticFeedbackProvider.scaleOnDragTexture(
+                config.maxVelocityToScale,
+                progress,
+            )
         val ticks = VibrationEffect.startComposition()
         repeat(config.numberOfLowTicks) {
             ticks.addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK, expectedScale)
@@ -203,7 +207,11 @@
     fun playHapticAtLowerBookend_afterPlayingAtProgress_playsTwice() {
         // GIVEN max velocity and slider progress
         val progress = 1f
-        val expectedScale = scaleAtProgressChange(config.maxVelocityToScale.toFloat(), progress)
+        val expectedScale =
+            sliderHapticFeedbackProvider.scaleOnDragTexture(
+                config.maxVelocityToScale,
+                progress,
+            )
         val ticks = VibrationEffect.startComposition()
         repeat(config.numberOfLowTicks) {
             ticks.addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK, expectedScale)
@@ -212,7 +220,7 @@
             VibrationEffect.startComposition()
                 .addPrimitive(
                     VibrationEffect.Composition.PRIMITIVE_CLICK,
-                    scaleAtBookends(config.maxVelocityToScale)
+                    sliderHapticFeedbackProvider.scaleOnEdgeCollision(config.maxVelocityToScale),
                 )
                 .compose()
 
@@ -232,7 +240,11 @@
     fun playHapticAtUpperBookend_afterPlayingAtProgress_playsTwice() {
         // GIVEN max velocity and slider progress
         val progress = 1f
-        val expectedScale = scaleAtProgressChange(config.maxVelocityToScale.toFloat(), progress)
+        val expectedScale =
+            sliderHapticFeedbackProvider.scaleOnDragTexture(
+                config.maxVelocityToScale,
+                progress,
+            )
         val ticks = VibrationEffect.startComposition()
         repeat(config.numberOfLowTicks) {
             ticks.addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK, expectedScale)
@@ -241,7 +253,7 @@
             VibrationEffect.startComposition()
                 .addPrimitive(
                     VibrationEffect.Composition.PRIMITIVE_CLICK,
-                    scaleAtBookends(config.maxVelocityToScale)
+                    sliderHapticFeedbackProvider.scaleOnEdgeCollision(config.maxVelocityToScale),
                 )
                 .compose()
 
@@ -289,28 +301,12 @@
         assertEquals(-1f, sliderHapticFeedbackProvider.dragTextureLastProgress)
     }
 
-    private fun scaleAtBookends(velocity: Float): Float {
-        val range = config.upperBookendScale - config.lowerBookendScale
-        val interpolatedVelocity =
-            velocityInterpolator.getInterpolation(velocity / config.maxVelocityToScale)
-        return interpolatedVelocity * range + config.lowerBookendScale
-    }
-
-    private fun scaleAtProgressChange(velocity: Float, progress: Float): Float {
-        val range = config.progressBasedDragMaxScale - config.progressBasedDragMinScale
-        val interpolatedVelocity =
-            velocityInterpolator.getInterpolation(velocity / config.maxVelocityToScale)
-        val interpolatedProgress = progressInterpolator.getInterpolation(progress)
-        val bump = interpolatedVelocity * config.additionalVelocityMaxBump
-        return interpolatedProgress * range + config.progressBasedDragMinScale + bump
-    }
-
     private fun generateTicksComposition(velocity: Float, progress: Float): VibrationEffect {
         val ticks = VibrationEffect.startComposition()
         repeat(config.numberOfLowTicks) {
             ticks.addPrimitive(
                 VibrationEffect.Composition.PRIMITIVE_LOW_TICK,
-                scaleAtProgressChange(velocity, progress)
+                sliderHapticFeedbackProvider.scaleOnDragTexture(velocity, progress),
             )
         }
         return ticks.compose()
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 40c9432..076d725 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
@@ -53,9 +53,11 @@
 import com.android.systemui.res.R
 import com.android.systemui.settings.UserFileManager
 import com.android.systemui.settings.UserTracker
+import com.android.systemui.shade.domain.interactor.shadeInteractor
 import com.android.systemui.shared.customization.data.content.CustomizationProviderContract as Contract
 import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
 import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.testKosmos
 import com.android.systemui.util.FakeSharedPreferences
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.mock
@@ -101,6 +103,8 @@
     private lateinit var underTest: CustomizationProvider
     private lateinit var testScope: TestScope
 
+    private val kosmos = testKosmos()
+
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
@@ -185,6 +189,7 @@
                                 },
                         )
                         .keyguardInteractor,
+                shadeInteractor = kosmos.shadeInteractor,
                 lockPatternUtils = lockPatternUtils,
                 keyguardStateController = keyguardStateController,
                 userTracker = userTracker,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index d246f0e..b38c9ec 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -24,6 +24,7 @@
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
+import static com.android.systemui.Flags.FLAG_REFACTOR_GET_CURRENT_USER;
 import static com.android.systemui.keyguard.KeyguardViewMediator.DELAYED_KEYGUARD_ACTION;
 import static com.android.systemui.keyguard.KeyguardViewMediator.KEYGUARD_LOCK_AFTER_DELAY_DEFAULT;
 import static com.android.systemui.keyguard.KeyguardViewMediator.REBOOT_MAINLINE_UPDATE;
@@ -93,10 +94,12 @@
 import com.android.systemui.flags.FakeFeatureFlags;
 import com.android.systemui.flags.Flags;
 import com.android.systemui.flags.SystemPropertiesHelper;
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
 import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
 import com.android.systemui.log.SessionTracker;
 import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.scene.FakeWindowRootViewComponent;
+import com.android.systemui.scene.shared.flag.SceneContainerFlags;
 import com.android.systemui.scene.ui.view.WindowRootView;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.shade.NotificationShadeWindowControllerImpl;
@@ -189,6 +192,7 @@
     private @Mock ShadeInteractor mShadeInteractor;
     private @Mock ShadeWindowLogger mShadeWindowLogger;
     private @Mock SelectedUserInteractor mSelectedUserInteractor;
+    private @Mock KeyguardInteractor mKeyguardInteractor;
     private @Captor ArgumentCaptor<KeyguardStateController.Callback>
             mKeyguardStateControllerCallback;
     private @Captor ArgumentCaptor<KeyguardUpdateMonitorCallback>
@@ -214,6 +218,7 @@
     private @Mock CoroutineDispatcher mDispatcher;
     private @Mock DreamingToLockscreenTransitionViewModel mDreamingToLockscreenTransitionViewModel;
     private @Mock SystemPropertiesHelper mSystemPropertiesHelper;
+    private @Mock SceneContainerFlags mSceneContainerFlags;
 
     private FakeFeatureFlags mFeatureFlags;
     private final int mDefaultUserId = 100;
@@ -258,10 +263,11 @@
                 () -> mShadeInteractor,
                 mShadeWindowLogger,
                 () -> mSelectedUserInteractor,
-                mUserTracker);
+                mUserTracker,
+                mSceneContainerFlags);
         mFeatureFlags = new FakeFeatureFlags();
         mFeatureFlags.set(Flags.KEYGUARD_WM_STATE_REFACTOR, false);
-        mFeatureFlags.set(Flags.REFACTOR_GETCURRENTUSER, true);
+        mSetFlagsRule.enableFlags(FLAG_REFACTOR_GET_CURRENT_USER);
 
         DejankUtils.setImmediate(true);
 
@@ -1128,7 +1134,8 @@
                 () -> mDreamingToLockscreenTransitionViewModel,
                 mSystemPropertiesHelper,
                 () -> mock(WindowManagerLockscreenVisibilityManager.class),
-                mSelectedUserInteractor);
+                mSelectedUserInteractor,
+                mKeyguardInteractor);
         mViewMediator.start();
 
         mViewMediator.registerCentralSurfaces(mCentralSurfaces, null, null, null, null, null);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryTest.kt
index 5852bdb..f2bd817 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryTest.kt
@@ -15,6 +15,8 @@
  *
  */
 
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
 package com.android.systemui.keyguard.data.repository
 
 import androidx.test.filters.SmallTest
@@ -25,8 +27,10 @@
 import com.android.systemui.keyguard.ui.view.layout.blueprints.DefaultKeyguardBlueprint.Companion.DEFAULT
 import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.test.StandardTestDispatcher
 import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
 import org.junit.Test
@@ -76,8 +80,21 @@
     fun testTransitionToLayout_validId() {
         assertThat(underTest.applyBlueprint(DEFAULT)).isTrue()
     }
+
     @Test
     fun testTransitionToLayout_invalidId() {
         assertThat(underTest.applyBlueprint("abc")).isFalse()
     }
+
+    @Test
+    fun testTransitionToSameBlueprint_refreshesBlueprint() =
+        testScope.runTest {
+            val refreshBlueprint by collectLastValue(underTest.refreshBluePrint)
+            runCurrent()
+
+            underTest.applyBlueprint(defaultLockscreenBlueprint)
+            runCurrent()
+
+            assertThat(refreshBlueprint).isNotNull()
+        }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractorTest.kt
new file mode 100644
index 0000000..70d3f81
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractorTest.kt
@@ -0,0 +1,238 @@
+/*
+ * 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.domain.interactor
+
+import android.os.Handler
+import android.platform.test.annotations.RequiresFlagsEnabled
+import androidx.test.filters.SmallTest
+import com.android.keyguard.KeyguardSecurityModel
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository
+import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
+import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
+import com.android.systemui.bouncer.ui.BouncerView
+import com.android.systemui.classifier.FalsingCollector
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.keyguard.DismissCallbackRegistry
+import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
+import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
+import com.android.systemui.keyguard.data.repository.FakeTrustRepository
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.res.R
+import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.user.domain.interactor.SelectedUserInteractor
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.time.FakeSystemClock
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.Mock
+import org.mockito.Mockito.mock
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@RequiresFlagsEnabled(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
+@SmallTest
+@RunWith(JUnit4::class)
+class DeviceEntrySideFpsOverlayInteractorTest : SysuiTestCase() {
+    @JvmField @Rule var mockitoRule: MockitoRule = MockitoJUnit.rule()
+
+    @Mock private lateinit var faceAuthInteractor: KeyguardFaceAuthInteractor
+    @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
+    @Mock private lateinit var mSelectedUserInteractor: SelectedUserInteractor
+
+    private val bouncerRepository = FakeKeyguardBouncerRepository()
+    private val biometricSettingsRepository = FakeBiometricSettingsRepository()
+
+    private lateinit var primaryBouncerInteractor: PrimaryBouncerInteractor
+    private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
+
+    private lateinit var underTest: DeviceEntrySideFpsOverlayInteractor
+
+    private val testScope = TestScope(StandardTestDispatcher())
+
+    @Before
+    fun setup() {
+        primaryBouncerInteractor =
+            PrimaryBouncerInteractor(
+                bouncerRepository,
+                mock(BouncerView::class.java),
+                mock(Handler::class.java),
+                mock(KeyguardStateController::class.java),
+                mock(KeyguardSecurityModel::class.java),
+                mock(PrimaryBouncerCallbackInteractor::class.java),
+                mock(FalsingCollector::class.java),
+                mock(DismissCallbackRegistry::class.java),
+                mContext,
+                keyguardUpdateMonitor,
+                FakeTrustRepository(),
+                testScope.backgroundScope,
+                mSelectedUserInteractor,
+                faceAuthInteractor
+            )
+        alternateBouncerInteractor =
+            AlternateBouncerInteractor(
+                mock(StatusBarStateController::class.java),
+                mock(KeyguardStateController::class.java),
+                bouncerRepository,
+                FakeFingerprintPropertyRepository(),
+                biometricSettingsRepository,
+                FakeSystemClock(),
+                keyguardUpdateMonitor,
+                testScope.backgroundScope,
+            )
+        underTest =
+            DeviceEntrySideFpsOverlayInteractor(
+                mContext,
+                FakeDeviceEntryFingerprintAuthRepository(),
+                primaryBouncerInteractor,
+                alternateBouncerInteractor,
+                keyguardUpdateMonitor
+            )
+    }
+
+    @Test
+    fun updatesShowIndicatorForDeviceEntry_onPrimaryBouncerShowing() =
+        testScope.runTest {
+            val showIndicatorForDeviceEntry by
+                collectLastValue(underTest.showIndicatorForDeviceEntry)
+            runCurrent()
+
+            updatePrimaryBouncer(
+                isShowing = true,
+                isAnimatingAway = false,
+                fpsDetectionRunning = true,
+                isUnlockingWithFpAllowed = true
+            )
+            assertThat(showIndicatorForDeviceEntry).isEqualTo(true)
+        }
+
+    @Test
+    fun updatesShowIndicatorForDeviceEntry_onPrimaryBouncerHidden() =
+        testScope.runTest {
+            val showIndicatorForDeviceEntry by
+                collectLastValue(underTest.showIndicatorForDeviceEntry)
+            runCurrent()
+
+            updatePrimaryBouncer(
+                isShowing = false,
+                isAnimatingAway = false,
+                fpsDetectionRunning = true,
+                isUnlockingWithFpAllowed = true
+            )
+            assertThat(showIndicatorForDeviceEntry).isEqualTo(false)
+        }
+
+    @Test
+    fun updatesShowIndicatorForDeviceEntry_fromPrimaryBouncer_whenFpsDetectionNotRunning() {
+        testScope.runTest {
+            val showIndicatorForDeviceEntry by
+                collectLastValue(underTest.showIndicatorForDeviceEntry)
+            runCurrent()
+
+            updatePrimaryBouncer(
+                isShowing = true,
+                isAnimatingAway = false,
+                fpsDetectionRunning = false,
+                isUnlockingWithFpAllowed = true
+            )
+            assertThat(showIndicatorForDeviceEntry).isEqualTo(false)
+        }
+    }
+
+    @Test
+    fun updatesShowIndicatorForDeviceEntry_fromPrimaryBouncer_onUnlockingWithFpDisallowed() {
+        testScope.runTest {
+            val showIndicatorForDeviceEntry by
+                collectLastValue(underTest.showIndicatorForDeviceEntry)
+            runCurrent()
+
+            updatePrimaryBouncer(
+                isShowing = true,
+                isAnimatingAway = false,
+                fpsDetectionRunning = true,
+                isUnlockingWithFpAllowed = false
+            )
+            assertThat(showIndicatorForDeviceEntry).isEqualTo(false)
+        }
+    }
+
+    @Test
+    fun updatesShowIndicatorForDeviceEntry_onPrimaryBouncerAnimatingAway() {
+        testScope.runTest {
+            val showIndicatorForDeviceEntry by
+                collectLastValue(underTest.showIndicatorForDeviceEntry)
+            runCurrent()
+
+            updatePrimaryBouncer(
+                isShowing = true,
+                isAnimatingAway = true,
+                fpsDetectionRunning = true,
+                isUnlockingWithFpAllowed = true
+            )
+            assertThat(showIndicatorForDeviceEntry).isEqualTo(false)
+        }
+    }
+
+    @Test
+    fun updatesShowIndicatorForDeviceEntry_onAlternateBouncerRequest() =
+        testScope.runTest {
+            val showIndicatorForDeviceEntry by
+                collectLastValue(underTest.showIndicatorForDeviceEntry)
+            runCurrent()
+
+            bouncerRepository.setAlternateVisible(true)
+            assertThat(showIndicatorForDeviceEntry).isEqualTo(true)
+
+            bouncerRepository.setAlternateVisible(false)
+            assertThat(showIndicatorForDeviceEntry).isEqualTo(false)
+        }
+
+    private fun updatePrimaryBouncer(
+        isShowing: Boolean,
+        isAnimatingAway: Boolean,
+        fpsDetectionRunning: Boolean,
+        isUnlockingWithFpAllowed: Boolean,
+    ) {
+        bouncerRepository.setPrimaryShow(isShowing)
+        bouncerRepository.setPrimaryStartingToHide(false)
+        val primaryStartDisappearAnimation = if (isAnimatingAway) Runnable {} else null
+        bouncerRepository.setPrimaryStartDisappearAnimation(primaryStartDisappearAnimation)
+
+        whenever(keyguardUpdateMonitor.isFingerprintDetectionRunning)
+            .thenReturn(fpsDetectionRunning)
+        whenever(keyguardUpdateMonitor.isUnlockingWithFingerprintAllowed)
+            .thenReturn(isUnlockingWithFpAllowed)
+        mContext.orCreateTestableResources.addOverride(
+            R.bool.config_show_sidefps_hint_on_bouncer,
+            true
+        )
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractorTest.kt
index 8dea57c..8e81185 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractorTest.kt
@@ -20,8 +20,6 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.coroutines.collectValues
 import com.android.systemui.flags.FakeFeatureFlags
-import com.android.systemui.flags.FakeFeatureFlagsClassic
-import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.keyguard.shared.model.TransitionStep
@@ -46,11 +44,7 @@
 class FromPrimaryBouncerTransitionInteractorTest : KeyguardTransitionInteractorTestCase() {
     private lateinit var underTest: FromPrimaryBouncerTransitionInteractor
 
-    private val mSelectedUserInteractor =
-        SelectedUserInteractor(
-            FakeUserRepository(),
-            FakeFeatureFlagsClassic().apply { set(Flags.REFACTOR_GETCURRENTUSER, true) }
-        )
+    private val mSelectedUserInteractor = SelectedUserInteractor(FakeUserRepository())
 
     // Override the fromPrimaryBouncerTransitionInteractor provider from the superclass so our
     // underTest interactor is provided to any classes that need it.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt
index de12b8f..6eb95bd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt
@@ -17,8 +17,10 @@
 
 package com.android.systemui.keyguard.domain.interactor
 
+import android.app.trust.TrustManager
 import android.content.pm.UserInfo
 import android.hardware.biometrics.BiometricFaceConstants
+import android.hardware.biometrics.BiometricSourceType
 import android.os.Handler
 import android.os.PowerManager
 import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -62,6 +64,7 @@
 import com.android.systemui.user.data.model.SelectionStatus
 import com.android.systemui.user.data.repository.FakeUserRepository
 import com.android.systemui.user.domain.interactor.SelectedUserInteractor
+import com.android.systemui.util.mockito.eq
 import com.android.systemui.util.mockito.whenever
 import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
@@ -74,8 +77,11 @@
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.Mock
 import org.mockito.Mockito.mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
 
 @OptIn(ExperimentalCoroutinesApi::class)
@@ -99,7 +105,8 @@
 
     @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
     @Mock private lateinit var faceWakeUpTriggersConfig: FaceWakeUpTriggersConfig
-    @Mock private lateinit var mSelectedUserInteractor: SelectedUserInteractor
+    @Mock private lateinit var selectedUserInteractor: SelectedUserInteractor
+    @Mock private lateinit var trustManager: TrustManager
 
     @Before
     fun setup() {
@@ -130,7 +137,6 @@
                 mContext,
                 testScope.backgroundScope,
                 dispatcher,
-                dispatcher,
                 faceAuthRepository,
                 {
                     PrimaryBouncerInteractor(
@@ -146,7 +152,7 @@
                         keyguardUpdateMonitor,
                         FakeTrustRepository(),
                         testScope.backgroundScope,
-                        mSelectedUserInteractor,
+                        selectedUserInteractor,
                         underTest,
                     )
                 },
@@ -169,6 +175,7 @@
                 faceWakeUpTriggersConfig,
                 powerInteractor,
                 fakeBiometricSettingsRepository,
+                trustManager,
             )
     }
 
@@ -498,6 +505,22 @@
             assertThat(faceAuthRepository.isLockedOut.value).isTrue()
         }
 
+    @Test
+    fun whenIsAuthenticatedFalse_clearFaceBiometrics() =
+        testScope.runTest {
+            underTest.start()
+
+            faceAuthRepository.isAuthenticated.value = true
+            runCurrent()
+            verify(trustManager, never())
+                .clearAllBiometricRecognized(eq(BiometricSourceType.FACE), anyInt())
+
+            faceAuthRepository.isAuthenticated.value = false
+            runCurrent()
+
+            verify(trustManager).clearAllBiometricRecognized(eq(BiometricSourceType.FACE), anyInt())
+        }
+
     companion object {
         private const val primaryUserId = 1
         private val primaryUser = UserInfo(primaryUserId, "test user", UserInfo.FLAG_PRIMARY)
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 66c8a22..b4ae7e3 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
@@ -46,7 +46,9 @@
 import com.android.systemui.settings.FakeUserTracker
 import com.android.systemui.settings.UserFileManager
 import com.android.systemui.settings.UserTracker
+import com.android.systemui.shade.domain.interactor.shadeInteractor
 import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.testKosmos
 import com.android.systemui.util.FakeSharedPreferences
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.mock
@@ -242,6 +244,8 @@
     private lateinit var biometricSettingsRepository: FakeBiometricSettingsRepository
     private lateinit var userTracker: UserTracker
 
+    private val kosmos = testKosmos()
+
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
@@ -311,6 +315,7 @@
                             featureFlags = featureFlags,
                         )
                         .keyguardInteractor,
+                shadeInteractor = kosmos.shadeInteractor,
                 lockPatternUtils = lockPatternUtils,
                 keyguardStateController = keyguardStateController,
                 userTracker = userTracker,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
index bf6d5c4..b8a8bdf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
@@ -43,7 +43,6 @@
 import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest
 import com.android.systemui.power.domain.interactor.PowerInteractorFactory
 import com.android.systemui.shade.data.repository.FakeShadeRepository
-import com.android.systemui.shade.domain.model.ShadeModel
 import com.android.systemui.user.domain.interactor.SelectedUserInteractor
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.mock
@@ -1138,7 +1137,7 @@
             runCurrent()
 
             // WHEN primary bouncer shows
-            bouncerRepository.setPrimaryShow(true) // beverlyt
+            bouncerRepository.setPrimaryShow(true)
             runCurrent()
 
             val info =
@@ -1233,6 +1232,36 @@
         }
 
     @Test
+    fun dreamingToAod() =
+        testScope.runTest {
+            // GIVEN a prior transition has run to DREAMING
+            keyguardRepository.setDreaming(true)
+            runTransitionAndSetWakefulness(KeyguardState.LOCKSCREEN, KeyguardState.DREAMING)
+            runCurrent()
+
+            // WHEN the device starts DOZE_AOD
+            keyguardRepository.setDozeTransitionModel(
+                DozeTransitionModel(
+                    from = DozeStateModel.INITIALIZED,
+                    to = DozeStateModel.DOZE_AOD,
+                )
+            )
+            runCurrent()
+
+            val info =
+                withArgCaptor<TransitionInfo> {
+                    verify(transitionRepository).startTransition(capture())
+                }
+            // THEN a transition to AOD should occur
+            assertThat(info.ownerName).isEqualTo("FromDreamingTransitionInteractor")
+            assertThat(info.from).isEqualTo(KeyguardState.DREAMING)
+            assertThat(info.to).isEqualTo(KeyguardState.AOD)
+            assertThat(info.animator).isNotNull()
+
+            coroutineContext.cancelChildren()
+        }
+
+    @Test
     fun lockscreenToOccluded() =
         testScope.runTest {
             // GIVEN a prior transition has run to LOCKSCREEN
@@ -1329,12 +1358,8 @@
             // GIVEN the keyguard is showing locked
             keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
             runCurrent()
-            shadeRepository.setShadeModel(
-                ShadeModel(
-                    expansionAmount = .9f,
-                    isUserDragging = true,
-                )
-            )
+            shadeRepository.setLegacyShadeTracking(true)
+            shadeRepository.setLegacyShadeExpansion(.9f)
             runCurrent()
 
             // THEN a transition from LOCKSCREEN => PRIMARY_BOUNCER should occur
@@ -1350,12 +1375,8 @@
             // WHEN the user stops dragging and shade is back to expanded
             clearInvocations(transitionRepository)
             runTransitionAndSetWakefulness(KeyguardState.LOCKSCREEN, KeyguardState.PRIMARY_BOUNCER)
-            shadeRepository.setShadeModel(
-                ShadeModel(
-                    expansionAmount = 1f,
-                    isUserDragging = false,
-                )
-            )
+            shadeRepository.setLegacyShadeTracking(false)
+            shadeRepository.setLegacyShadeExpansion(1f)
             runCurrent()
 
             // THEN a transition from PRIMARY_BOUNCER => LOCKSCREEN should occur
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt
index 67fba42..22569e2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt
@@ -39,6 +39,7 @@
 import com.android.systemui.res.R
 import com.android.systemui.shade.NotificationPanelView
 import com.android.systemui.statusbar.NotificationShadeWindowController
+import com.android.systemui.statusbar.VibratorHelper
 import com.android.systemui.statusbar.gesture.TapGestureDetector
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -91,6 +92,7 @@
                 TestScope().backgroundScope,
                 { mock(SwipeUpAnywhereGestureHandler::class.java) },
                 { mock(TapGestureDetector::class.java) },
+                { mock(VibratorHelper::class.java) },
             )
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsTest.kt
index c9b14a4..daafe12 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlowsTest.kt
@@ -22,7 +22,7 @@
 import com.android.systemui.bouncer.domain.interactor.primaryBouncerInteractor
 import com.android.systemui.coroutines.collectValues
 import com.android.systemui.flags.Flags
-import com.android.systemui.flags.featureFlagsClassic
+import com.android.systemui.flags.fakeFeatureFlagsClassic
 import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER
@@ -55,7 +55,7 @@
 
     private val kosmos =
         testKosmos().apply {
-            featureFlagsClassic.apply {
+            fakeFeatureFlagsClassic.apply {
                 set(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT, false)
                 set(Flags.FULL_SCREEN_USER_SWITCHER, false)
             }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt
index 1584be0..af38523c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt
@@ -54,9 +54,11 @@
 import com.android.systemui.res.R
 import com.android.systemui.settings.UserFileManager
 import com.android.systemui.settings.UserTracker
+import com.android.systemui.shade.domain.interactor.shadeInteractor
 import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
 import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper
 import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.testKosmos
 import com.android.systemui.util.FakeSharedPreferences
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.mock
@@ -108,6 +110,8 @@
     private lateinit var dockManager: DockManagerFake
     private lateinit var biometricSettingsRepository: FakeBiometricSettingsRepository
 
+    private val kosmos = testKosmos()
+
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
@@ -221,6 +225,7 @@
                 quickAffordanceInteractor =
                     KeyguardQuickAffordanceInteractor(
                         keyguardInteractor = keyguardInteractor,
+                        shadeInteractor = kosmos.shadeInteractor,
                         lockPatternUtils = lockPatternUtils,
                         keyguardStateController = keyguardStateController,
                         userTracker = userTracker,
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 0c30d10..b6a661b 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
@@ -264,12 +264,14 @@
         whenever(lockscreenToPrimaryBouncerTransitionViewModel.shortcutsAlpha)
             .thenReturn(emptyFlow())
         whenever(shadeInteractor.qsExpansion).thenReturn(intendedShadeAlphaMutableStateFlow)
+        whenever(shadeInteractor.anyExpansion).thenReturn(MutableStateFlow(0f))
 
         underTest =
             KeyguardQuickAffordancesCombinedViewModel(
                 quickAffordanceInteractor =
                     KeyguardQuickAffordanceInteractor(
                         keyguardInteractor = keyguardInteractor,
+                        shadeInteractor = shadeInteractor,
                         lockPatternUtils = lockPatternUtils,
                         keyguardStateController = keyguardStateController,
                         userTracker = userTracker,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt
index 58624d3..459a74c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt
@@ -144,19 +144,50 @@
     @Test
     fun alpha() =
         testScope.runTest {
-            val value = collectLastValue(underTest.alpha)
-            assertThat(value()).isEqualTo(0f)
+            val alpha by collectLastValue(underTest.alpha)
+
+            keyguardTransitionRepository.sendTransitionSteps(
+                from = KeyguardState.OFF,
+                to = KeyguardState.LOCKSCREEN,
+                testScope = testScope,
+            )
 
             repository.setKeyguardAlpha(0.1f)
-            assertThat(value()).isEqualTo(0.1f)
+            assertThat(alpha).isEqualTo(0.1f)
             repository.setKeyguardAlpha(0.5f)
-            assertThat(value()).isEqualTo(0.5f)
+            assertThat(alpha).isEqualTo(0.5f)
             repository.setKeyguardAlpha(0.2f)
-            assertThat(value()).isEqualTo(0.2f)
+            assertThat(alpha).isEqualTo(0.2f)
             repository.setKeyguardAlpha(0f)
-            assertThat(value()).isEqualTo(0f)
+            assertThat(alpha).isEqualTo(0f)
             occludedToLockscreenAlpha.value = 0.8f
-            assertThat(value()).isEqualTo(0.8f)
+            assertThat(alpha).isEqualTo(0.8f)
+        }
+
+    @Test
+    fun alphaWhenGoneEqualsZero() =
+        testScope.runTest {
+            val alpha by collectLastValue(underTest.alpha)
+
+            keyguardTransitionRepository.sendTransitionSteps(
+                from = KeyguardState.LOCKSCREEN,
+                to = KeyguardState.GONE,
+                testScope = testScope,
+            )
+
+            repository.setKeyguardAlpha(0.1f)
+            assertThat(alpha).isEqualTo(0f)
+            repository.setKeyguardAlpha(0.5f)
+            assertThat(alpha).isEqualTo(0f)
+            repository.setKeyguardAlpha(1f)
+            assertThat(alpha).isEqualTo(0f)
+        }
+
+    @Test
+    fun translationYInitialValueIsZero() =
+        testScope.runTest {
+            val translationY by collectLastValue(underTest.translationY)
+            assertThat(translationY).isEqualTo(0)
         }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModelTest.kt
index c15a2c6..e139466 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToAodTransitionViewModelTest.kt
@@ -23,7 +23,7 @@
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.coroutines.collectValues
 import com.android.systemui.flags.Flags.FULL_SCREEN_USER_SWITCHER
-import com.android.systemui.flags.featureFlagsClassic
+import com.android.systemui.flags.fakeFeatureFlagsClassic
 import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
 import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
@@ -47,7 +47,9 @@
 @RunWith(AndroidJUnit4::class)
 class LockscreenToAodTransitionViewModelTest : SysuiTestCase() {
     private val kosmos =
-        testKosmos().apply { featureFlagsClassic.apply { set(FULL_SCREEN_USER_SWITCHER, false) } }
+        testKosmos().apply {
+            fakeFeatureFlagsClassic.apply { set(FULL_SCREEN_USER_SWITCHER, false) }
+        }
     private val testScope = kosmos.testScope
     private val repository = kosmos.fakeKeyguardTransitionRepository
     private val shadeRepository = kosmos.shadeRepository
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModelTest.kt
index b31968c..7a564ac 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModelTest.kt
@@ -21,7 +21,7 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.flags.Flags
-import com.android.systemui.flags.featureFlagsClassic
+import com.android.systemui.flags.fakeFeatureFlagsClassic
 import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
 import com.android.systemui.keyguard.shared.model.KeyguardState
@@ -45,7 +45,7 @@
 class LockscreenToPrimaryBouncerTransitionViewModelTest : SysuiTestCase() {
     private val kosmos =
         testKosmos().apply {
-            featureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) }
+            fakeFeatureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) }
         }
     private val testScope = kosmos.testScope
     private val repository = kosmos.fakeKeyguardTransitionRepository
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt
index 3bfdb84..310e0b8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt
@@ -54,6 +54,7 @@
 import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.util.concurrency.DelayableExecutor
+import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.capture
 import com.android.systemui.util.mockito.eq
@@ -124,6 +125,7 @@
     @Captor lateinit var settingsObserverCaptor: ArgumentCaptor<ContentObserver>
 
     private val clock = FakeSystemClock()
+    private lateinit var bgExecutor: FakeExecutor
     private lateinit var mediaCarouselController: MediaCarouselController
 
     @Before
@@ -131,6 +133,7 @@
         MockitoAnnotations.initMocks(this)
         context.resources.configuration.setLocales(LocaleList(Locale.US, Locale.UK))
         transitionRepository = FakeKeyguardTransitionRepository()
+        bgExecutor = FakeExecutor(clock)
         mediaCarouselController =
             MediaCarouselController(
                 context,
@@ -140,6 +143,7 @@
                 activityStarter,
                 clock,
                 executor,
+                bgExecutor,
                 mediaDataManager,
                 configurationController,
                 falsingManager,
@@ -458,6 +462,7 @@
             mediaHostState,
             animate = false
         )
+        bgExecutor.runAllReady()
         verify(logger).logCarouselPosition(LOCATION_QS)
     }
 
@@ -468,6 +473,7 @@
             mediaHostState,
             animate = false
         )
+        bgExecutor.runAllReady()
         verify(logger).logCarouselPosition(MediaHierarchyManager.LOCATION_QQS)
     }
 
@@ -478,6 +484,7 @@
             mediaHostState,
             animate = false
         )
+        bgExecutor.runAllReady()
         verify(logger).logCarouselPosition(MediaHierarchyManager.LOCATION_LOCKSCREEN)
     }
 
@@ -488,6 +495,7 @@
             mediaHostState,
             animate = false
         )
+        bgExecutor.runAllReady()
         verify(logger).logCarouselPosition(MediaHierarchyManager.LOCATION_DREAM_OVERLAY)
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
index b7618d2..4d42324 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
@@ -75,6 +75,7 @@
 import kotlinx.coroutines.test.UnconfinedTestDispatcher
 import kotlinx.coroutines.test.runCurrent
 import org.junit.Before
+import org.junit.Ignore
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.ArgumentMatchers.anyInt
@@ -462,6 +463,7 @@
 
     // region setNoteTaskShortcutEnabled
     @Test
+    @Ignore("b/316332684")
     fun setNoteTaskShortcutEnabled_setTrue() {
         createNoteTaskController().setNoteTaskShortcutEnabled(value = true, userTracker.userHandle)
 
@@ -478,6 +480,7 @@
     }
 
     @Test
+    @Ignore("b/316332684")
     fun setNoteTaskShortcutEnabled_setFalse() {
         createNoteTaskController().setNoteTaskShortcutEnabled(value = false, userTracker.userHandle)
 
@@ -494,6 +497,7 @@
     }
 
     @Test
+    @Ignore("b/316332684")
     fun setNoteTaskShortcutEnabled_workProfileUser_setTrue() {
         whenever(context.createContextAsUser(eq(workUserInfo.userHandle), any()))
             .thenReturn(workProfileContext)
@@ -515,6 +519,7 @@
     }
 
     @Test
+    @Ignore("b/316332684")
     fun setNoteTaskShortcutEnabled_workProfileUser_setFalse() {
         whenever(context.createContextAsUser(eq(workUserInfo.userHandle), any()))
             .thenReturn(workProfileContext)
@@ -733,6 +738,7 @@
 
     // region internalUpdateNoteTaskAsUser
     @Test
+    @Ignore("b/316332684")
     fun updateNoteTaskAsUserInternal_withNotesRole_withShortcuts_shouldUpdateShortcuts() {
         createNoteTaskController(isEnabled = true)
             .launchUpdateNoteTaskAsUser(userTracker.userHandle)
@@ -766,6 +772,7 @@
     }
 
     @Test
+    @Ignore("b/316332684")
     fun updateNoteTaskAsUserInternal_noNotesRole_shouldDisableShortcuts() {
         whenever(roleManager.getRoleHoldersAsUser(ROLE_NOTES, userTracker.userHandle))
             .thenReturn(emptyList())
@@ -789,6 +796,7 @@
     }
 
     @Test
+    @Ignore("b/316332684")
     fun updateNoteTaskAsUserInternal_flagDisabled_shouldDisableShortcuts() {
         createNoteTaskController(isEnabled = false)
             .launchUpdateNoteTaskAsUser(userTracker.userHandle)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfigTest.kt
index 119ffd2..ebd34de 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfigTest.kt
@@ -28,7 +28,6 @@
 import android.test.suitebuilder.annotation.SmallTest
 import android.testing.AndroidTestingRunner
 import com.android.dx.mockito.inline.extended.ExtendedMockito
-import com.android.systemui.res.R
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.common.shared.model.ContentDescription
 import com.android.systemui.common.shared.model.Icon
@@ -40,6 +39,7 @@
 import com.android.systemui.notetask.NoteTaskController
 import com.android.systemui.notetask.NoteTaskEntryPoint
 import com.android.systemui.notetask.NoteTaskInfoResolver
+import com.android.systemui.res.R
 import com.android.systemui.stylus.StylusManager
 import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.mockito.any
@@ -134,12 +134,9 @@
     // region lockScreenState
     @Test
     fun lockScreenState_stylusUsed_userUnlocked_isSelected_shouldEmitVisible() = runTest {
-        TestConfig()
-            .setStylusEverUsed(true)
-            .setUserUnlocked(true)
-            .setConfigSelections(mock<NoteTaskQuickAffordanceConfig>())
-
         val underTest = createUnderTest()
+        TestConfig().setStylusEverUsed(true).setUserUnlocked(true).setConfigSelections(underTest)
+
         val actual by collectLastValue(underTest.lockScreenState)
 
         assertThat(actual).isEqualTo(createLockScreenStateVisible())
@@ -148,10 +145,11 @@
     @Test
     fun lockScreenState_stylusUsed_userUnlocked_isSelected_noDefaultNotesAppSet_shouldEmitHidden() =
         runTest {
+            val underTest = createUnderTest()
             TestConfig()
                 .setStylusEverUsed(true)
                 .setUserUnlocked(true)
-                .setConfigSelections(mock<NoteTaskQuickAffordanceConfig>())
+                .setConfigSelections(underTest)
             whenever(
                     roleManager.getRoleHoldersAsUser(
                         eq(RoleManager.ROLE_NOTES),
@@ -160,7 +158,6 @@
                 )
                 .thenReturn(emptyList())
 
-            val underTest = createUnderTest()
             val actual by collectLastValue(underTest.lockScreenState)
 
             assertThat(actual).isEqualTo(LockScreenState.Hidden)
@@ -168,12 +165,9 @@
 
     @Test
     fun lockScreenState_stylusUnused_userUnlocked_isSelected_shouldEmitHidden() = runTest {
-        TestConfig()
-            .setStylusEverUsed(false)
-            .setUserUnlocked(true)
-            .setConfigSelections(mock<NoteTaskQuickAffordanceConfig>())
-
         val underTest = createUnderTest()
+        TestConfig().setStylusEverUsed(false).setUserUnlocked(true).setConfigSelections(underTest)
+
         val actual by collectLastValue(underTest.lockScreenState)
 
         assertThat(actual).isEqualTo(LockScreenState.Hidden)
@@ -181,25 +175,22 @@
 
     @Test
     fun lockScreenState_stylusUsed_userLocked_isSelected_shouldEmitHidden() = runTest {
-        TestConfig()
-            .setStylusEverUsed(true)
-            .setUserUnlocked(false)
-            .setConfigSelections(mock<NoteTaskQuickAffordanceConfig>())
-
         val underTest = createUnderTest()
+        TestConfig().setStylusEverUsed(true).setUserUnlocked(false).setConfigSelections(underTest)
+
         val actual by collectLastValue(underTest.lockScreenState)
 
         assertThat(actual).isEqualTo(LockScreenState.Hidden)
     }
 
     @Test
-    fun lockScreenState_stylusUsed_userUnlocked_noSelected_shouldEmitVisible() = runTest {
+    fun lockScreenState_stylusUsed_userUnlocked_noSelected_shouldEmitHidden() = runTest {
         TestConfig().setStylusEverUsed(true).setUserUnlocked(true).setConfigSelections()
 
         val underTest = createUnderTest()
         val actual by collectLastValue(underTest.lockScreenState)
 
-        assertThat(actual).isEqualTo(createLockScreenStateVisible())
+        assertThat(actual).isEqualTo(LockScreenState.Hidden)
     }
 
     @Test
@@ -223,13 +214,13 @@
     }
 
     @Test
-    fun lockScreenState_stylusUsed_userUnlocked_customSelections_shouldEmitVisible() = runTest {
+    fun lockScreenState_stylusUsed_userUnlocked_customSelections_shouldEmitHidden() = runTest {
         TestConfig().setStylusEverUsed(true).setUserUnlocked(true).setConfigSelections(mock())
 
         val underTest = createUnderTest()
         val actual by collectLastValue(underTest.lockScreenState)
 
-        assertThat(actual).isEqualTo(createLockScreenStateVisible())
+        assertThat(actual).isEqualTo(LockScreenState.Hidden)
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogControllerV2Test.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogControllerV2Test.kt
index 0a8c0ab..e4432f3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogControllerV2Test.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogControllerV2Test.kt
@@ -31,18 +31,20 @@
 import android.permission.PermissionManager
 import android.testing.AndroidTestingRunner
 import android.view.View
+import android.widget.LinearLayout
 import androidx.test.filters.SmallTest
 import com.android.internal.logging.UiEventLogger
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.animation.DialogLaunchAnimator
+import com.android.systemui.animation.LaunchableView
 import com.android.systemui.appops.AppOpsController
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.privacy.logging.PrivacyLogger
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.util.concurrency.FakeExecutor
-import com.android.systemui.util.mockito.capture
 import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.capture
 import com.android.systemui.util.mockito.eq
 import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
@@ -56,12 +58,12 @@
 import org.mockito.ArgumentMatchers.anyString
 import org.mockito.Captor
 import org.mockito.Mock
-import org.mockito.Mockito.`when`
 import org.mockito.Mockito.atLeastOnce
 import org.mockito.Mockito.mock
 import org.mockito.Mockito.never
 import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
 import org.mockito.MockitoAnnotations
 
 @SmallTest
@@ -83,60 +85,48 @@
         private val TEST_INTENT = Intent("test_intent_action")
     }
 
-    @Mock
-    private lateinit var dialog: PrivacyDialogV2
-    @Mock
-    private lateinit var permissionManager: PermissionManager
-    @Mock
-    private lateinit var packageManager: PackageManager
-    @Mock
-    private lateinit var privacyItemController: PrivacyItemController
-    @Mock
-    private lateinit var userTracker: UserTracker
-    @Mock
-    private lateinit var activityStarter: ActivityStarter
-    @Mock
-    private lateinit var privacyLogger: PrivacyLogger
-    @Mock
-    private lateinit var keyguardStateController: KeyguardStateController
-    @Mock
-    private lateinit var appOpsController: AppOpsController
+    @Mock private lateinit var dialog: PrivacyDialogV2
+    @Mock private lateinit var permissionManager: PermissionManager
+    @Mock private lateinit var packageManager: PackageManager
+    @Mock private lateinit var privacyItemController: PrivacyItemController
+    @Mock private lateinit var userTracker: UserTracker
+    @Mock private lateinit var activityStarter: ActivityStarter
+    @Mock private lateinit var privacyLogger: PrivacyLogger
+    @Mock private lateinit var keyguardStateController: KeyguardStateController
+    @Mock private lateinit var appOpsController: AppOpsController
     @Captor
     private lateinit var dialogDismissedCaptor: ArgumentCaptor<PrivacyDialogV2.OnDialogDismissed>
-    @Captor
-    private lateinit var activityStartedCaptor: ArgumentCaptor<ActivityStarter.Callback>
-    @Captor
-    private lateinit var intentCaptor: ArgumentCaptor<Intent>
-    @Mock
-    private lateinit var uiEventLogger: UiEventLogger
-    @Mock
-    private lateinit var dialogLaunchAnimator: DialogLaunchAnimator
+    @Captor private lateinit var activityStartedCaptor: ArgumentCaptor<ActivityStarter.Callback>
+    @Captor private lateinit var intentCaptor: ArgumentCaptor<Intent>
+    @Mock private lateinit var uiEventLogger: UiEventLogger
+    @Mock private lateinit var dialogLaunchAnimator: DialogLaunchAnimator
 
     private val backgroundExecutor = FakeExecutor(FakeSystemClock())
     private val uiExecutor = FakeExecutor(FakeSystemClock())
     private lateinit var controller: PrivacyDialogControllerV2
     private var nextUid: Int = 0
 
-    private val dialogProvider = object : PrivacyDialogControllerV2.DialogProvider {
-        var list: List<PrivacyDialogV2.PrivacyElement>? = null
-        var manageApp: ((String, Int, Intent) -> Unit)? = null
-        var closeApp: ((String, Int) -> Unit)? = null
-        var openPrivacyDashboard: (() -> Unit)? = null
+    private val dialogProvider =
+        object : PrivacyDialogControllerV2.DialogProvider {
+            var list: List<PrivacyDialogV2.PrivacyElement>? = null
+            var manageApp: ((String, Int, Intent) -> Unit)? = null
+            var closeApp: ((String, Int) -> Unit)? = null
+            var openPrivacyDashboard: (() -> Unit)? = null
 
-        override fun makeDialog(
-            context: Context,
-            list: List<PrivacyDialogV2.PrivacyElement>,
-            manageApp: (String, Int, Intent) -> Unit,
-            closeApp: (String, Int) -> Unit,
-            openPrivacyDashboard: () -> Unit
-        ): PrivacyDialogV2 {
-            this.list = list
-            this.manageApp = manageApp
-            this.closeApp = closeApp
-            this.openPrivacyDashboard = openPrivacyDashboard
-            return dialog
+            override fun makeDialog(
+                context: Context,
+                list: List<PrivacyDialogV2.PrivacyElement>,
+                manageApp: (String, Int, Intent) -> Unit,
+                closeApp: (String, Int) -> Unit,
+                openPrivacyDashboard: () -> Unit
+            ): PrivacyDialogV2 {
+                this.list = list
+                this.manageApp = manageApp
+                this.closeApp = closeApp
+                this.openPrivacyDashboard = openPrivacyDashboard
+                return dialog
+            }
         }
-    }
 
     @Before
     fun setUp() {
@@ -144,7 +134,8 @@
         nextUid = 0
         setUpDefaultMockResponses()
 
-        controller = PrivacyDialogControllerV2(
+        controller =
+            PrivacyDialogControllerV2(
                 permissionManager,
                 packageManager,
                 privacyItemController,
@@ -158,7 +149,7 @@
                 uiEventLogger,
                 dialogLaunchAnimator,
                 dialogProvider
-        )
+            )
     }
 
     @After
@@ -197,7 +188,7 @@
         verify(packageManager, never()).getApplicationInfoAsUser(anyString(), anyInt(), anyInt())
         backgroundExecutor.runAllReady()
         verify(packageManager, atLeastOnce())
-                .getApplicationInfoAsUser(anyString(), anyInt(), anyInt())
+            .getApplicationInfoAsUser(anyString(), anyInt(), anyInt())
     }
 
     @Test
@@ -208,20 +199,25 @@
         controller.showDialog(context)
         exhaustExecutors()
 
-        verify(dialogLaunchAnimator, never()).showFromView(any(), any(), any(), anyBoolean())
+        verify(dialogLaunchAnimator, never()).show(any(), any(), anyBoolean())
         verify(dialog).show()
     }
 
     @Test
     fun testShowDialogShowsDialogWithView() {
-        val view = View(context)
+        val parent = LinearLayout(context)
+        val view =
+            object : View(context), LaunchableView {
+                override fun setShouldBlockVisibilityChanges(block: Boolean) {}
+            }
+        parent.addView(view)
         val usage = createMockPermGroupUsage()
         `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(listOf(usage))
 
         controller.showDialog(context, view)
         exhaustExecutors()
 
-        verify(dialogLaunchAnimator).showFromView(dialog, view)
+        verify(dialogLaunchAnimator).show(eq(dialog), any(), anyBoolean())
         verify(dialog, never()).show()
     }
 
@@ -276,7 +272,8 @@
 
     @Test
     fun testSingleElementInList() {
-        val usage = createMockPermGroupUsage(
+        val usage =
+            createMockPermGroupUsage(
                 packageName = TEST_PACKAGE_NAME,
                 uid = generateUidForUser(USER_ID),
                 permissionGroupName = PERM_CAMERA,
@@ -285,7 +282,7 @@
                 isPhoneCall = false,
                 attributionTag = null,
                 proxyLabel = TEST_PROXY_LABEL
-        )
+            )
         `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(listOf(usage))
 
         controller.showDialog(context)
@@ -304,33 +301,38 @@
             assertThat(list.get(0).isPhoneCall).isFalse()
             assertThat(list.get(0).isService).isFalse()
             assertThat(list.get(0).permGroupName).isEqualTo(PERM_CAMERA)
-            assertThat(isIntentEqual(list.get(0).navigationIntent!!,
-                    controller.getDefaultManageAppPermissionsIntent(TEST_PACKAGE_NAME, USER_ID)))
-                    .isTrue()
+            assertThat(
+                    isIntentEqual(
+                        list.get(0).navigationIntent!!,
+                        controller.getDefaultManageAppPermissionsIntent(TEST_PACKAGE_NAME, USER_ID)
+                    )
+                )
+                .isTrue()
         }
     }
 
     private fun isIntentEqual(actual: Intent, expected: Intent): Boolean {
         return actual.action == expected.action &&
-                actual.getStringExtra(Intent.EXTRA_PACKAGE_NAME) ==
+            actual.getStringExtra(Intent.EXTRA_PACKAGE_NAME) ==
                 expected.getStringExtra(Intent.EXTRA_PACKAGE_NAME) &&
-                actual.getParcelableExtra(Intent.EXTRA_USER) as? UserHandle ==
+            actual.getParcelableExtra(Intent.EXTRA_USER) as? UserHandle ==
                 expected.getParcelableExtra(Intent.EXTRA_USER) as? UserHandle
     }
 
     @Test
     fun testTwoElementsDifferentType_sorted() {
-        val usage_camera = createMockPermGroupUsage(
+        val usage_camera =
+            createMockPermGroupUsage(
                 packageName = "${TEST_PACKAGE_NAME}_camera",
                 permissionGroupName = PERM_CAMERA
-        )
-        val usage_microphone = createMockPermGroupUsage(
+            )
+        val usage_microphone =
+            createMockPermGroupUsage(
                 packageName = "${TEST_PACKAGE_NAME}_microphone",
                 permissionGroupName = PERM_MICROPHONE
-        )
-        `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(
-                listOf(usage_microphone, usage_camera)
-        )
+            )
+        `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean()))
+            .thenReturn(listOf(usage_microphone, usage_camera))
 
         controller.showDialog(context)
         exhaustExecutors()
@@ -343,17 +345,12 @@
 
     @Test
     fun testTwoElementsSameType_oneActive() {
-        val usage_active = createMockPermGroupUsage(
-                packageName = "${TEST_PACKAGE_NAME}_active",
-                isActive = true
-        )
-        val usage_recent = createMockPermGroupUsage(
-                packageName = "${TEST_PACKAGE_NAME}_recent",
-                isActive = false
-        )
-        `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(
-                listOf(usage_recent, usage_active)
-        )
+        val usage_active =
+            createMockPermGroupUsage(packageName = "${TEST_PACKAGE_NAME}_active", isActive = true)
+        val usage_recent =
+            createMockPermGroupUsage(packageName = "${TEST_PACKAGE_NAME}_recent", isActive = false)
+        `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean()))
+            .thenReturn(listOf(usage_recent, usage_active))
 
         controller.showDialog(context)
         exhaustExecutors()
@@ -364,19 +361,20 @@
 
     @Test
     fun testTwoElementsSameType_twoActive() {
-        val usage_active = createMockPermGroupUsage(
+        val usage_active =
+            createMockPermGroupUsage(
                 packageName = "${TEST_PACKAGE_NAME}_active",
                 isActive = true,
                 lastAccessTimeMillis = 0L
-        )
-        val usage_active_moreRecent = createMockPermGroupUsage(
+            )
+        val usage_active_moreRecent =
+            createMockPermGroupUsage(
                 packageName = "${TEST_PACKAGE_NAME}_active_recent",
                 isActive = true,
                 lastAccessTimeMillis = 1L
-        )
-        `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(
-                listOf(usage_active, usage_active_moreRecent)
-        )
+            )
+        `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean()))
+            .thenReturn(listOf(usage_active, usage_active_moreRecent))
         controller.showDialog(context)
         exhaustExecutors()
         assertThat(dialogProvider.list).hasSize(2)
@@ -386,24 +384,26 @@
 
     @Test
     fun testManyElementsSameType_bothRecent() {
-        val usage_recent = createMockPermGroupUsage(
+        val usage_recent =
+            createMockPermGroupUsage(
                 packageName = "${TEST_PACKAGE_NAME}_recent",
                 isActive = false,
                 lastAccessTimeMillis = 0L
-        )
-        val usage_moreRecent = createMockPermGroupUsage(
+            )
+        val usage_moreRecent =
+            createMockPermGroupUsage(
                 packageName = "${TEST_PACKAGE_NAME}_moreRecent",
                 isActive = false,
                 lastAccessTimeMillis = 1L
-        )
-        val usage_mostRecent = createMockPermGroupUsage(
+            )
+        val usage_mostRecent =
+            createMockPermGroupUsage(
                 packageName = "${TEST_PACKAGE_NAME}_mostRecent",
                 isActive = false,
                 lastAccessTimeMillis = 2L
-        )
-        `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(
-                listOf(usage_recent, usage_mostRecent, usage_moreRecent)
-        )
+            )
+        `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean()))
+            .thenReturn(listOf(usage_recent, usage_mostRecent, usage_moreRecent))
 
         controller.showDialog(context)
         exhaustExecutors()
@@ -414,19 +414,12 @@
 
     @Test
     fun testMicAndCameraDisabled() {
-        val usage_camera = createMockPermGroupUsage(
-                permissionGroupName = PERM_CAMERA
-        )
-        val usage_microphone = createMockPermGroupUsage(
-                permissionGroupName = PERM_MICROPHONE
-        )
-        val usage_location = createMockPermGroupUsage(
-                permissionGroupName = PERM_LOCATION
-        )
+        val usage_camera = createMockPermGroupUsage(permissionGroupName = PERM_CAMERA)
+        val usage_microphone = createMockPermGroupUsage(permissionGroupName = PERM_MICROPHONE)
+        val usage_location = createMockPermGroupUsage(permissionGroupName = PERM_LOCATION)
 
-        `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(
-                listOf(usage_camera, usage_location, usage_microphone)
-        )
+        `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean()))
+            .thenReturn(listOf(usage_camera, usage_location, usage_microphone))
         `when`(privacyItemController.micCameraAvailable).thenReturn(false)
 
         controller.showDialog(context)
@@ -438,45 +431,29 @@
 
     @Test
     fun testLocationDisabled() {
-        val usage_camera = createMockPermGroupUsage(
-                permissionGroupName = PERM_CAMERA
-        )
-        val usage_microphone = createMockPermGroupUsage(
-                permissionGroupName = PERM_MICROPHONE
-        )
-        val usage_location = createMockPermGroupUsage(
-                permissionGroupName = PERM_LOCATION
-        )
+        val usage_camera = createMockPermGroupUsage(permissionGroupName = PERM_CAMERA)
+        val usage_microphone = createMockPermGroupUsage(permissionGroupName = PERM_MICROPHONE)
+        val usage_location = createMockPermGroupUsage(permissionGroupName = PERM_LOCATION)
 
-        `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(
-                listOf(usage_camera, usage_location, usage_microphone)
-        )
+        `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean()))
+            .thenReturn(listOf(usage_camera, usage_location, usage_microphone))
         `when`(privacyItemController.locationAvailable).thenReturn(false)
 
         controller.showDialog(context)
         exhaustExecutors()
 
         assertThat(dialogProvider.list).hasSize(2)
-        dialogProvider.list?.forEach {
-            assertThat(it.type).isNotEqualTo(PrivacyType.TYPE_LOCATION)
-        }
+        dialogProvider.list?.forEach { assertThat(it.type).isNotEqualTo(PrivacyType.TYPE_LOCATION) }
     }
 
     @Test
     fun testAllIndicatorsAvailable() {
-        val usage_camera = createMockPermGroupUsage(
-                permissionGroupName = PERM_CAMERA
-        )
-        val usage_microphone = createMockPermGroupUsage(
-                permissionGroupName = PERM_MICROPHONE
-        )
-        val usage_location = createMockPermGroupUsage(
-                permissionGroupName = PERM_LOCATION
-        )
+        val usage_camera = createMockPermGroupUsage(permissionGroupName = PERM_CAMERA)
+        val usage_microphone = createMockPermGroupUsage(permissionGroupName = PERM_MICROPHONE)
+        val usage_location = createMockPermGroupUsage(permissionGroupName = PERM_LOCATION)
 
-        `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(
-                listOf(usage_camera, usage_location, usage_microphone)
-        )
+        `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean()))
+            .thenReturn(listOf(usage_camera, usage_location, usage_microphone))
         `when`(privacyItemController.micCameraAvailable).thenReturn(true)
         `when`(privacyItemController.locationAvailable).thenReturn(true)
 
@@ -488,19 +465,12 @@
 
     @Test
     fun testNoIndicatorsAvailable() {
-        val usage_camera = createMockPermGroupUsage(
-                permissionGroupName = PERM_CAMERA
-        )
-        val usage_microphone = createMockPermGroupUsage(
-                permissionGroupName = PERM_MICROPHONE
-        )
-        val usage_location = createMockPermGroupUsage(
-                permissionGroupName = PERM_LOCATION
-        )
+        val usage_camera = createMockPermGroupUsage(permissionGroupName = PERM_CAMERA)
+        val usage_microphone = createMockPermGroupUsage(permissionGroupName = PERM_MICROPHONE)
+        val usage_location = createMockPermGroupUsage(permissionGroupName = PERM_LOCATION)
 
-        `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(
-                listOf(usage_camera, usage_location, usage_microphone)
-        )
+        `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean()))
+            .thenReturn(listOf(usage_camera, usage_location, usage_microphone))
         `when`(privacyItemController.micCameraAvailable).thenReturn(false)
         `when`(privacyItemController.locationAvailable).thenReturn(false)
 
@@ -512,11 +482,9 @@
 
     @Test
     fun testNotCurrentUser() {
-        val usage_other = createMockPermGroupUsage(
-                uid = generateUidForUser(ENT_USER_ID + 1)
-        )
+        val usage_other = createMockPermGroupUsage(uid = generateUidForUser(ENT_USER_ID + 1))
         `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean()))
-                .thenReturn(listOf(usage_other))
+            .thenReturn(listOf(usage_other))
 
         controller.showDialog(context)
         exhaustExecutors()
@@ -559,9 +527,7 @@
         // Calls happen in
         val usage = createMockPermGroupUsage(uid = SYSTEM_UID, isPhoneCall = true)
         `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(listOf(usage))
-        `when`(userTracker.userProfiles).thenReturn(listOf(
-                UserInfo(ENT_USER_ID, "", 0)
-        ))
+        `when`(userTracker.userProfiles).thenReturn(listOf(UserInfo(ENT_USER_ID, "", 0)))
 
         controller.showDialog(context)
         exhaustExecutors()
@@ -577,8 +543,12 @@
         exhaustExecutors()
 
         dialogProvider.manageApp?.invoke(TEST_PACKAGE_NAME, USER_ID, TEST_INTENT)
-        verify(uiEventLogger).log(PrivacyDialogEvent.PRIVACY_DIALOG_ITEM_CLICKED_TO_APP_SETTINGS,
-                USER_ID, TEST_PACKAGE_NAME)
+        verify(uiEventLogger)
+            .log(
+                PrivacyDialogEvent.PRIVACY_DIALOG_ITEM_CLICKED_TO_APP_SETTINGS,
+                USER_ID,
+                TEST_PACKAGE_NAME
+            )
     }
 
     @Test
@@ -589,8 +559,12 @@
         exhaustExecutors()
 
         dialogProvider.closeApp?.invoke(TEST_PACKAGE_NAME, USER_ID)
-        verify(uiEventLogger).log(PrivacyDialogEvent.PRIVACY_DIALOG_ITEM_CLICKED_TO_CLOSE_APP,
-                USER_ID, TEST_PACKAGE_NAME)
+        verify(uiEventLogger)
+            .log(
+                PrivacyDialogEvent.PRIVACY_DIALOG_ITEM_CLICKED_TO_CLOSE_APP,
+                USER_ID,
+                TEST_PACKAGE_NAME
+            )
     }
 
     @Test
@@ -629,9 +603,13 @@
         exhaustExecutors()
 
         dialogProvider.list?.let { list ->
-            assertThat(isIntentEqual(list.get(0).navigationIntent!!,
-                    controller.getDefaultManageAppPermissionsIntent(TEST_PACKAGE_NAME, USER_ID)))
-                    .isTrue()
+            assertThat(
+                    isIntentEqual(
+                        list.get(0).navigationIntent!!,
+                        controller.getDefaultManageAppPermissionsIntent(TEST_PACKAGE_NAME, USER_ID)
+                    )
+                )
+                .isTrue()
             assertThat(list.get(0).isService).isFalse()
         }
     }
@@ -648,45 +626,58 @@
         exhaustExecutors()
 
         dialogProvider.list?.let { list ->
-            assertThat(isIntentEqual(list.get(0).navigationIntent!!,
-                    controller.getDefaultManageAppPermissionsIntent(
-                        TEST_PACKAGE_NAME, ENT_USER_ID)))
-                        .isTrue()
+            assertThat(
+                    isIntentEqual(
+                        list.get(0).navigationIntent!!,
+                        controller.getDefaultManageAppPermissionsIntent(
+                            TEST_PACKAGE_NAME,
+                            ENT_USER_ID
+                        )
+                    )
+                )
+                .isTrue()
             assertThat(list.get(0).isService).isFalse()
         }
     }
 
     @Test
     fun testDefaultIntentOnInvalidAttributionTag() {
-        val usage = createMockPermGroupUsage(
+        val usage =
+            createMockPermGroupUsage(
                 attributionTag = "INVALID_ATTRIBUTION_TAG",
                 proxyLabel = TEST_PROXY_LABEL
-        )
+            )
         `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(listOf(usage))
 
         controller.showDialog(context)
         exhaustExecutors()
 
         dialogProvider.list?.let { list ->
-            assertThat(isIntentEqual(list.get(0).navigationIntent!!,
-                    controller.getDefaultManageAppPermissionsIntent(TEST_PACKAGE_NAME, USER_ID)))
-                    .isTrue()
+            assertThat(
+                    isIntentEqual(
+                        list.get(0).navigationIntent!!,
+                        controller.getDefaultManageAppPermissionsIntent(TEST_PACKAGE_NAME, USER_ID)
+                    )
+                )
+                .isTrue()
             assertThat(list.get(0).isService).isFalse()
         }
     }
 
     @Test
     fun testServiceIntentOnCorrectSubAttribution() {
-        val usage = createMockPermGroupUsage(
+        val usage =
+            createMockPermGroupUsage(
                 attributionTag = TEST_ATTRIBUTION_TAG,
                 attributionLabel = "TEST_LABEL"
-        )
+            )
 
         val activityInfo = createMockActivityInfo()
         val resolveInfo = createMockResolveInfo(activityInfo)
         `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(listOf(usage))
-        `when`(packageManager.resolveActivity(any(), any<ResolveInfoFlags>()))
-                .thenAnswer { resolveInfo }
+        `when`(packageManager.resolveActivity(any(), any<ResolveInfoFlags>())).thenAnswer {
+            resolveInfo
+        }
         controller.showDialog(context)
         exhaustExecutors()
 
@@ -694,57 +685,61 @@
             val navigationIntent = list.get(0).navigationIntent!!
             assertThat(navigationIntent.action).isEqualTo(Intent.ACTION_MANAGE_PERMISSION_USAGE)
             assertThat(navigationIntent.getStringExtra(Intent.EXTRA_PERMISSION_GROUP_NAME))
-                    .isEqualTo(PERM_CAMERA)
+                .isEqualTo(PERM_CAMERA)
             assertThat(navigationIntent.getStringArrayExtra(Intent.EXTRA_ATTRIBUTION_TAGS))
-                    .isEqualTo(arrayOf(TEST_ATTRIBUTION_TAG.toString()))
+                .isEqualTo(arrayOf(TEST_ATTRIBUTION_TAG.toString()))
             assertThat(navigationIntent.getBooleanExtra(Intent.EXTRA_SHOWING_ATTRIBUTION, false))
-                    .isTrue()
+                .isTrue()
             assertThat(list.get(0).isService).isTrue()
         }
     }
 
     @Test
     fun testDefaultIntentOnMissingAttributionLabel() {
-        val usage = createMockPermGroupUsage(
-                attributionTag = TEST_ATTRIBUTION_TAG
-        )
+        val usage = createMockPermGroupUsage(attributionTag = TEST_ATTRIBUTION_TAG)
 
         val activityInfo = createMockActivityInfo()
         val resolveInfo = createMockResolveInfo(activityInfo)
         `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(listOf(usage))
-        `when`(packageManager.resolveActivity(any(), any<ResolveInfoFlags>()))
-                .thenAnswer { resolveInfo }
+        `when`(packageManager.resolveActivity(any(), any<ResolveInfoFlags>())).thenAnswer {
+            resolveInfo
+        }
         controller.showDialog(context)
         exhaustExecutors()
 
         dialogProvider.list?.let { list ->
-            assertThat(isIntentEqual(list.get(0).navigationIntent!!,
-                    controller.getDefaultManageAppPermissionsIntent(TEST_PACKAGE_NAME, USER_ID)))
-                    .isTrue()
+            assertThat(
+                    isIntentEqual(
+                        list.get(0).navigationIntent!!,
+                        controller.getDefaultManageAppPermissionsIntent(TEST_PACKAGE_NAME, USER_ID)
+                    )
+                )
+                .isTrue()
             assertThat(list.get(0).isService).isFalse()
         }
     }
 
     @Test
     fun testDefaultIntentOnIncorrectPermission() {
-        val usage = createMockPermGroupUsage(
-                attributionTag = TEST_ATTRIBUTION_TAG
-        )
+        val usage = createMockPermGroupUsage(attributionTag = TEST_ATTRIBUTION_TAG)
 
-        val activityInfo = createMockActivityInfo(
-                permission = "INCORRECT_PERMISSION"
-        )
+        val activityInfo = createMockActivityInfo(permission = "INCORRECT_PERMISSION")
         val resolveInfo = createMockResolveInfo(activityInfo)
         `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(listOf(usage))
-        `when`(packageManager.resolveActivity(any(), any<ResolveInfoFlags>()))
-                .thenAnswer { resolveInfo }
+        `when`(packageManager.resolveActivity(any(), any<ResolveInfoFlags>())).thenAnswer {
+            resolveInfo
+        }
         controller.showDialog(context)
         exhaustExecutors()
 
         dialogProvider.list?.let { list ->
-            assertThat(isIntentEqual(list.get(0).navigationIntent!!,
-                    controller.getDefaultManageAppPermissionsIntent(TEST_PACKAGE_NAME, USER_ID)))
-                    .isTrue()
+            assertThat(
+                    isIntentEqual(
+                        list.get(0).navigationIntent!!,
+                        controller.getDefaultManageAppPermissionsIntent(TEST_PACKAGE_NAME, USER_ID)
+                    )
+                )
+                .isTrue()
             assertThat(list.get(0).isService).isFalse()
         }
     }
@@ -758,15 +753,18 @@
         `when`(appOpsController.isMicMuted).thenReturn(false)
 
         `when`(packageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
-                .thenAnswer { FakeApplicationInfo(it.getArgument(0)) }
+            .thenAnswer { FakeApplicationInfo(it.getArgument(0)) }
 
         `when`(privacyItemController.locationAvailable).thenReturn(true)
         `when`(privacyItemController.micCameraAvailable).thenReturn(true)
 
-        `when`(userTracker.userProfiles).thenReturn(listOf(
-                UserInfo(USER_ID, "", 0),
-                UserInfo(ENT_USER_ID, "", UserInfo.FLAG_MANAGED_PROFILE)
-        ))
+        `when`(userTracker.userProfiles)
+            .thenReturn(
+                listOf(
+                    UserInfo(USER_ID, "", 0),
+                    UserInfo(ENT_USER_ID, "", UserInfo.FLAG_MANAGED_PROFILE)
+                )
+            )
 
         `when`(keyguardStateController.isUnlocked).thenReturn(true)
     }
@@ -781,9 +779,7 @@
         return user * UserHandle.PER_USER_RANGE + nextUid++
     }
 
-    private fun createMockResolveInfo(
-        activityInfo: ActivityInfo? = null
-    ): ResolveInfo {
+    private fun createMockResolveInfo(activityInfo: ActivityInfo? = null): ResolveInfo {
         val resolveInfo = mock(ResolveInfo::class.java)
         resolveInfo.activityInfo = activityInfo
         return resolveInfo
@@ -822,4 +818,4 @@
         `when`(usage.proxyLabel).thenReturn(proxyLabel)
         return usage
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
index b825c08..018fa9e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
@@ -391,7 +391,7 @@
     }
 
     @Test
-    public void setTiles_differentTiles_allTilesRemovedAndNewTilesAdded() {
+    public void setTiles_differentTiles_extraTileRemoved() {
         when(mQSHost.getTiles()).thenReturn(List.of(mQSTile, mOtherTile));
         mController.setTiles();
 
@@ -400,8 +400,8 @@
         when(mQSHost.getTiles()).thenReturn(List.of(mQSTile));
         mController.setTiles();
 
-        verify(mQSPanel, times(2)).removeTile(any());
-        verify(mQSPanel).addTile(any());
+        verify(mQSPanel, times(1)).removeTile(any());
+        verify(mQSPanel, never()).addTile(any());
     }
 
     @Test
@@ -418,7 +418,7 @@
     }
 
     @Test
-    public void setTiles_sameTilesDifferentOrder_removesAndReadds() {
+    public void setTiles_sameTilesDifferentOrder_removesAndReads() {
         when(mQSHost.getTiles()).thenReturn(List.of(mQSTile, mOtherTile));
         mController.setTiles();
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
index 5245b22..5e2423a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
@@ -18,6 +18,7 @@
 
 
 import static com.android.systemui.Flags.FLAG_QS_NEW_PIPELINE;
+import static com.android.systemui.Flags.FLAG_QS_NEW_TILES;
 
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
@@ -53,7 +54,6 @@
 import com.android.systemui.classifier.FalsingManagerFake;
 import com.android.systemui.dump.nano.SystemUIProtoDump;
 import com.android.systemui.flags.FakeFeatureFlags;
-import com.android.systemui.flags.Flags;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.PluginManager;
 import com.android.systemui.plugins.qs.QSFactory;
@@ -79,6 +79,8 @@
 import com.android.systemui.util.settings.SecureSettings;
 import com.android.systemui.util.time.FakeSystemClock;
 
+import dagger.Lazy;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -93,8 +95,6 @@
 
 import javax.inject.Provider;
 
-import dagger.Lazy;
-
 @RunWith(AndroidTestingRunner.class)
 @SmallTest
 public class QSTileHostTest extends SysuiTestCase {
@@ -147,9 +147,8 @@
         mFeatureFlags = new FakeFeatureFlags();
 
         mSetFlagsRule.disableFlags(FLAG_QS_NEW_PIPELINE);
-        // TODO(b/299909337): Add test checking the new factory is used when the flag is on
-        mFeatureFlags.set(Flags.QS_PIPELINE_NEW_TILES, false);
-        mQSPipelineFlagsRepository = new QSPipelineFlagsRepository(mFeatureFlags);
+        mSetFlagsRule.disableFlags(FLAG_QS_NEW_TILES);
+        mQSPipelineFlagsRepository = new QSPipelineFlagsRepository();
 
         mMainExecutor = new FakeExecutor(new FakeSystemClock());
 
@@ -704,7 +703,7 @@
                 TileLifecycleManager.Factory tileLifecycleManagerFactory,
                 UserFileManager userFileManager, QSPipelineFlagsRepository featureFlags) {
             super(context, newQSTileFactoryProvider, defaultFactory, mainExecutor, pluginManager,
-                    tunerService, autoTiles,  shadeController, qsLogger,
+                    tunerService, autoTiles, shadeController, qsLogger,
                     userTracker, secureSettings, customTileStatePersister,
                     tileLifecycleManagerFactory, userFileManager, featureFlags);
         }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/shared/QSPipelineFlagsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/shared/QSPipelineFlagsRepositoryTest.kt
index 2e63708..970cd17 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/shared/QSPipelineFlagsRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/shared/QSPipelineFlagsRepositoryTest.kt
@@ -4,7 +4,6 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.Flags
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.flags.FakeFeatureFlagsClassic
 import com.google.common.truth.Truth.assertThat
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -13,9 +12,7 @@
 @RunWith(AndroidJUnit4::class)
 class QSPipelineFlagsRepositoryTest : SysuiTestCase() {
 
-    private val fakeFeatureFlagsClassic = FakeFeatureFlagsClassic()
-
-    private val underTest = QSPipelineFlagsRepository(fakeFeatureFlagsClassic)
+    private val underTest = QSPipelineFlagsRepository()
 
     @Test
     fun pipelineFlagDisabled() {
@@ -30,4 +27,18 @@
 
         assertThat(underTest.pipelineEnabled).isTrue()
     }
+
+    @Test
+    fun tilesFlagDisabled() {
+        mSetFlagsRule.disableFlags(Flags.FLAG_QS_NEW_TILES)
+
+        assertThat(underTest.tilesEnabled).isFalse()
+    }
+
+    @Test
+    fun tilesFlagEnabled() {
+        mSetFlagsRule.enableFlags(Flags.FLAG_QS_NEW_TILES)
+
+        assertThat(underTest.tilesEnabled).isTrue()
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RecordIssueTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RecordIssueTileTest.kt
new file mode 100644
index 0000000..9b61447
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RecordIssueTileTest.kt
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles
+
+import android.os.Handler
+import android.service.quicksettings.Tile
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
+import com.android.internal.logging.MetricsLogger
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.DialogLaunchAnimator
+import com.android.systemui.classifier.FalsingManagerFake
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.qs.QSHost
+import com.android.systemui.qs.QsEventLogger
+import com.android.systemui.qs.logging.QSLogger
+import com.android.systemui.res.R
+import com.android.systemui.settings.UserContextProvider
+import com.android.systemui.statusbar.phone.KeyguardDismissUtil
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.eq
+import org.mockito.ArgumentMatchers.isA
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+/**
+ * This class tests the functionality of the RecordIssueTile. The initial state of the tile is
+ * always be inactive at the start of these tests.
+ */
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+@SmallTest
+class RecordIssueTileTest : SysuiTestCase() {
+
+    @Mock private lateinit var host: QSHost
+    @Mock private lateinit var qsEventLogger: QsEventLogger
+    @Mock private lateinit var metricsLogger: MetricsLogger
+    @Mock private lateinit var statusBarStateController: StatusBarStateController
+    @Mock private lateinit var activityStarter: ActivityStarter
+    @Mock private lateinit var qsLogger: QSLogger
+    @Mock private lateinit var keyguardDismissUtil: KeyguardDismissUtil
+    @Mock private lateinit var keyguardStateController: KeyguardStateController
+    @Mock private lateinit var dialogLauncherAnimator: DialogLaunchAnimator
+    @Mock private lateinit var dialogFactory: SystemUIDialog.Factory
+    @Mock private lateinit var dialog: SystemUIDialog
+    @Mock private lateinit var userContextProvider: UserContextProvider
+
+    private lateinit var testableLooper: TestableLooper
+    private lateinit var tile: RecordIssueTile
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        whenever(host.context).thenReturn(mContext)
+        whenever(dialogFactory.create(any())).thenReturn(dialog)
+
+        testableLooper = TestableLooper.get(this)
+        tile =
+            RecordIssueTile(
+                host,
+                qsEventLogger,
+                testableLooper.looper,
+                Handler(testableLooper.looper),
+                FalsingManagerFake(),
+                metricsLogger,
+                statusBarStateController,
+                activityStarter,
+                qsLogger,
+                keyguardDismissUtil,
+                keyguardStateController,
+                dialogLauncherAnimator,
+                dialogFactory,
+                userContextProvider,
+            )
+    }
+
+    @Test
+    fun qsTileUi_shouldLookCorrect_whenInactive() {
+        tile.isRecording = false
+
+        val testState = tile.newTileState()
+        tile.handleUpdateState(testState, null)
+
+        assertThat(testState.state).isEqualTo(Tile.STATE_INACTIVE)
+        assertThat(testState.secondaryLabel.toString())
+            .isEqualTo(mContext.getString(R.string.qs_record_issue_start))
+    }
+
+    @Test
+    fun qsTileUi_shouldLookCorrect_whenRecording() {
+        tile.isRecording = true
+
+        val testState = tile.newTileState()
+        tile.handleUpdateState(testState, null)
+
+        assertThat(testState.state).isEqualTo(Tile.STATE_ACTIVE)
+        assertThat(testState.secondaryLabel.toString())
+            .isEqualTo(mContext.getString(R.string.qs_record_issue_stop))
+    }
+
+    @Test
+    fun inActiveQsTile_switchesToActive_whenClicked() {
+        tile.isRecording = false
+
+        val testState = tile.newTileState()
+        tile.handleUpdateState(testState, null)
+
+        assertThat(testState.state).isEqualTo(Tile.STATE_INACTIVE)
+    }
+
+    @Test
+    fun activeQsTile_switchesToInActive_whenClicked() {
+        tile.isRecording = true
+
+        val testState = tile.newTileState()
+        tile.handleUpdateState(testState, null)
+
+        assertThat(testState.state).isEqualTo(Tile.STATE_ACTIVE)
+    }
+
+    @Test
+    fun showPrompt_shouldUseKeyguardDismissUtil_ToShowDialog() {
+        tile.isRecording = false
+        tile.handleClick(null)
+        testableLooper.processAllMessages()
+
+        verify(keyguardDismissUtil)
+            .executeWhenUnlocked(
+                isA(ActivityStarter.OnDismissAction::class.java),
+                eq(false),
+                eq(true)
+            )
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
index 6dc7a06..b24b877 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
@@ -63,13 +63,13 @@
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.settingslib.wifi.WifiUtils;
 import com.android.settingslib.wifi.dpp.WifiDppIntentHelper;
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.animation.DialogLaunchAnimator;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.flags.FakeFeatureFlags;
 import com.android.systemui.flags.Flags;
 import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.connectivity.AccessPointController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.statusbar.policy.LocationController;
@@ -738,6 +738,44 @@
     }
 
     @Test
+    public void onWifiScan_isWifiEnabledFalse_callbackOnWifiScanFalse() {
+        reset(mInternetDialogCallback);
+        when(mWifiStateWorker.isWifiEnabled()).thenReturn(false);
+
+        mInternetDialogController.onWifiScan(true);
+
+        verify(mInternetDialogCallback).onWifiScan(false);
+    }
+
+    @Test
+    public void onWifiScan_isDeviceLockedTrue_callbackOnWifiScanFalse() {
+        reset(mInternetDialogCallback);
+        when(mKeyguardStateController.isUnlocked()).thenReturn(false);
+
+        mInternetDialogController.onWifiScan(true);
+
+        verify(mInternetDialogCallback).onWifiScan(false);
+    }
+
+    @Test
+    public void onWifiScan_onWifiScanFalse_callbackOnWifiScanFalse() {
+        reset(mInternetDialogCallback);
+
+        mInternetDialogController.onWifiScan(false);
+
+        verify(mInternetDialogCallback).onWifiScan(false);
+    }
+
+    @Test
+    public void onWifiScan_onWifiScanTrue_callbackOnWifiScanTrue() {
+        reset(mInternetDialogCallback);
+
+        mInternetDialogController.onWifiScan(true);
+
+        verify(mInternetDialogCallback).onWifiScan(true);
+    }
+
+    @Test
     public void setMergedCarrierWifiEnabledIfNeed_carrierProvisionsEnabled_doNothing() {
         when(mCarrierConfigTracker.getCarrierProvisionsWifiMergedNetworksBool(SUB_ID))
                 .thenReturn(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
index 039e58a..916bb79 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
@@ -6,12 +6,10 @@
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -33,9 +31,9 @@
 import com.android.dx.mockito.inline.extended.ExtendedMockito;
 import com.android.internal.logging.UiEventLogger;
 import com.android.settingslib.wifi.WifiEnterpriseRestrictionUtils;
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.animation.DialogLaunchAnimator;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.time.FakeSystemClock;
@@ -48,7 +46,6 @@
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
-import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 import org.mockito.MockitoSession;
 
@@ -613,66 +610,21 @@
     }
 
     @Test
-    public void showProgressBar_wifiDisabled_hideProgressBar() {
-        Mockito.reset(mHandler);
-        when(mInternetDialogController.isWifiEnabled()).thenReturn(false);
+    public void onWifiScan_isScanTrue_setProgressBarVisibleTrue() {
+        mInternetDialog.mIsProgressBarVisible = false;
 
-        mInternetDialog.showProgressBar();
+        mInternetDialog.onWifiScan(true);
 
-        assertThat(mInternetDialog.mIsProgressBarVisible).isFalse();
-        verify(mHandler, never()).postDelayed(any(Runnable.class), anyLong());
+        assertThat(mInternetDialog.mIsProgressBarVisible).isTrue();
     }
 
     @Test
-    public void showProgressBar_deviceLocked_hideProgressBar() {
-        Mockito.reset(mHandler);
-        when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
+    public void onWifiScan_isScanFalse_setProgressBarVisibleFalse() {
+        mInternetDialog.mIsProgressBarVisible = true;
 
-        mInternetDialog.showProgressBar();
+        mInternetDialog.onWifiScan(false);
 
         assertThat(mInternetDialog.mIsProgressBarVisible).isFalse();
-        verify(mHandler, never()).postDelayed(any(Runnable.class), anyLong());
-    }
-
-    @Test
-    public void showProgressBar_wifiEnabledWithWifiEntry_showProgressBarThenHide() {
-        Mockito.reset(mHandler);
-        when(mInternetDialogController.isWifiEnabled()).thenReturn(true);
-
-        mInternetDialog.showProgressBar();
-
-        // Show progress bar
-        assertThat(mInternetDialog.mIsProgressBarVisible).isTrue();
-
-        ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
-        verify(mHandler).postDelayed(runnableCaptor.capture(),
-                eq(InternetDialog.PROGRESS_DELAY_MS));
-        runnableCaptor.getValue().run();
-
-        // Then hide progress bar
-        assertThat(mInternetDialog.mIsProgressBarVisible).isFalse();
-    }
-
-    @Test
-    public void showProgressBar_wifiEnabledWithoutWifiEntries_showProgressBarThenHideSearch() {
-        Mockito.reset(mHandler);
-        when(mInternetDialogController.isWifiEnabled()).thenReturn(true);
-        mInternetDialog.mConnectedWifiEntry = null;
-        mInternetDialog.mWifiEntriesCount = 0;
-
-        mInternetDialog.showProgressBar();
-
-        // Show progress bar
-        assertThat(mInternetDialog.mIsProgressBarVisible).isTrue();
-
-        ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
-        verify(mHandler).postDelayed(runnableCaptor.capture(),
-                eq(InternetDialog.PROGRESS_DELAY_MS));
-        runnableCaptor.getValue().run();
-
-        // Then hide searching sub-title only
-        assertThat(mInternetDialog.mIsProgressBarVisible).isTrue();
-        assertThat(mInternetDialog.mIsSearchingHidden).isTrue();
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogTest.kt
index 313ccb8..154aa1c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogTest.kt
@@ -23,6 +23,8 @@
 import android.view.View
 import android.view.View.GONE
 import android.view.View.VISIBLE
+import android.view.ViewGroup.LayoutParams.MATCH_PARENT
+import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
 import androidx.recyclerview.widget.LinearLayoutManager
 import androidx.recyclerview.widget.RecyclerView
 import androidx.test.filters.SmallTest
@@ -54,6 +56,7 @@
         const val DEVICE_NAME = "device"
         const val DEVICE_CONNECTION_SUMMARY = "active"
         const val ENABLED = true
+        const val CONTENT_HEIGHT = WRAP_CONTENT
     }
 
     @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule()
@@ -88,6 +91,7 @@
             BluetoothTileDialog(
                 ENABLED,
                 subtitleResId,
+                CONTENT_HEIGHT,
                 bluetoothTileDialogCallback,
                 dispatcher,
                 fakeSystemClock,
@@ -116,9 +120,9 @@
 
         assertThat(bluetoothTileDialog.isShowing).isTrue()
         assertThat(recyclerView).isNotNull()
-        assertThat(recyclerView?.visibility).isEqualTo(VISIBLE)
-        assertThat(recyclerView?.adapter).isNotNull()
-        assertThat(recyclerView?.layoutManager is LinearLayoutManager).isTrue()
+        assertThat(recyclerView.visibility).isEqualTo(VISIBLE)
+        assertThat(recyclerView.adapter).isNotNull()
+        assertThat(recyclerView.layoutManager is LinearLayoutManager).isTrue()
     }
 
     @Test
@@ -128,6 +132,7 @@
                 BluetoothTileDialog(
                     ENABLED,
                     subtitleResId,
+                    CONTENT_HEIGHT,
                     bluetoothTileDialogCallback,
                     dispatcher,
                     fakeSystemClock,
@@ -144,7 +149,7 @@
             )
 
             val recyclerView = bluetoothTileDialog.requireViewById<RecyclerView>(R.id.device_list)
-            val adapter = recyclerView?.adapter as BluetoothTileDialog.Adapter
+            val adapter = recyclerView.adapter as BluetoothTileDialog.Adapter
             assertThat(adapter.itemCount).isEqualTo(1)
             assertThat(adapter.getItem(0).deviceName).isEqualTo(DEVICE_NAME)
             assertThat(adapter.getItem(0).connectionSummary).isEqualTo(DEVICE_CONNECTION_SUMMARY)
@@ -162,6 +167,7 @@
             BluetoothTileDialog(
                     ENABLED,
                     subtitleResId,
+                    CONTENT_HEIGHT,
                     bluetoothTileDialogCallback,
                     dispatcher,
                     fakeSystemClock,
@@ -189,6 +195,7 @@
             BluetoothTileDialog(
                     ENABLED,
                     subtitleResId,
+                    CONTENT_HEIGHT,
                     bluetoothTileDialogCallback,
                     dispatcher,
                     fakeSystemClock,
@@ -213,6 +220,7 @@
                 BluetoothTileDialog(
                     ENABLED,
                     subtitleResId,
+                    CONTENT_HEIGHT,
                     bluetoothTileDialogCallback,
                     dispatcher,
                     fakeSystemClock,
@@ -232,13 +240,38 @@
             val pairNewButton =
                 bluetoothTileDialog.requireViewById<View>(R.id.pair_new_device_button)
             val recyclerView = bluetoothTileDialog.requireViewById<RecyclerView>(R.id.device_list)
-            val adapter = recyclerView?.adapter as BluetoothTileDialog.Adapter
+            val adapter = recyclerView.adapter as BluetoothTileDialog.Adapter
+            val scrollViewContent = bluetoothTileDialog.requireViewById<View>(R.id.scroll_view)
 
             assertThat(seeAllButton).isNotNull()
             assertThat(seeAllButton.visibility).isEqualTo(GONE)
             assertThat(pairNewButton).isNotNull()
             assertThat(pairNewButton.visibility).isEqualTo(VISIBLE)
             assertThat(adapter.itemCount).isEqualTo(1)
+            assertThat(scrollViewContent.layoutParams.height).isEqualTo(WRAP_CONTENT)
+        }
+    }
+
+    @Test
+    fun testShowDialog_displayFromCachedHeight() {
+        testScope.runTest {
+            bluetoothTileDialog =
+                BluetoothTileDialog(
+                    ENABLED,
+                    subtitleResId,
+                    MATCH_PARENT,
+                    bluetoothTileDialogCallback,
+                    dispatcher,
+                    fakeSystemClock,
+                    uiEventLogger,
+                    logger,
+                    mContext
+                )
+            bluetoothTileDialog.show()
+            assertThat(
+                    bluetoothTileDialog.requireViewById<View>(R.id.scroll_view).layoutParams.height
+                )
+                .isEqualTo(MATCH_PARENT)
         }
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogViewModelTest.kt
index 99993f2..33066d2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/bluetooth/BluetoothTileDialogViewModelTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.qs.tiles.dialog.bluetooth
 
+import android.content.SharedPreferences
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
 import android.view.View
@@ -78,6 +79,8 @@
 
     @Mock private lateinit var logger: BluetoothTileDialogLogger
 
+    @Mock private lateinit var sharedPreferences: SharedPreferences
+
     private lateinit var scheduler: TestCoroutineScheduler
     private lateinit var dispatcher: CoroutineDispatcher
     private lateinit var testScope: TestScope
@@ -98,6 +101,8 @@
                 logger,
                 testScope.backgroundScope,
                 dispatcher,
+                dispatcher,
+                sharedPreferences,
             )
         `when`(deviceItemInteractor.deviceItemUpdate).thenReturn(MutableSharedFlow())
         `when`(bluetoothStateInteractor.bluetoothStateUpdate)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/recordissue/RecordIssueDialogDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/recordissue/RecordIssueDialogDelegateTest.kt
new file mode 100644
index 0000000..c5d3524
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/recordissue/RecordIssueDialogDelegateTest.kt
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recordissue
+
+import android.app.Dialog
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.widget.Button
+import android.widget.Switch
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.DialogLaunchAnimator
+import com.android.systemui.broadcast.BroadcastDispatcher
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.model.SysUiState
+import com.android.systemui.res.R
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import com.android.systemui.statusbar.phone.SystemUIDialogManager
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.ArgumentMatchers.anyInt
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+class RecordIssueDialogDelegateTest : SysuiTestCase() {
+
+    private lateinit var dialog: SystemUIDialog
+    private lateinit var latch: CountDownLatch
+
+    @Before
+    fun setup() {
+        val dialogFactory =
+            SystemUIDialog.Factory(
+                context,
+                mock<FeatureFlags>(),
+                mock<SystemUIDialogManager>(),
+                mock<SysUiState>().apply {
+                    whenever(setFlag(anyInt(), anyBoolean())).thenReturn(this)
+                },
+                mock<BroadcastDispatcher>(),
+                mock<DialogLaunchAnimator>()
+            )
+
+        latch = CountDownLatch(1)
+        dialog =
+            RecordIssueDialogDelegate(dialogFactory, mock()) { latch.countDown() }.createDialog()
+        dialog.show()
+    }
+
+    @After
+    fun teardown() {
+        dialog.dismiss()
+    }
+
+    @Test
+    fun dialog_hasCorrectUiElements_afterCreation() {
+        dialog.requireViewById<Switch>(R.id.screenrecord_switch)
+        dialog.requireViewById<Button>(R.id.issue_type_button)
+
+        assertThat(dialog.getButton(Dialog.BUTTON_POSITIVE).text)
+            .isEqualTo(context.getString(R.string.qs_record_issue_start))
+        assertThat(dialog.getButton(Dialog.BUTTON_NEGATIVE).text)
+            .isEqualTo(context.getString(R.string.cancel))
+    }
+
+    @Test
+    fun onStarted_isCalled_afterStartButtonIsClicked() {
+        dialog.getButton(Dialog.BUTTON_POSITIVE).callOnClick()
+        latch.await(1L, TimeUnit.MILLISECONDS)
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.kt
index 0173c32..b90ccc0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.kt
@@ -27,6 +27,7 @@
 import com.android.systemui.flags.ResourceBooleanFlag
 import com.android.systemui.flags.UnreleasedFlag
 import com.android.systemui.keyguard.shared.KeyguardShadeMigrationNssl
+import com.android.systemui.media.controls.util.MediaInSceneContainerFlag
 import com.android.systemui.res.R
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
@@ -71,6 +72,7 @@
                 AconfigFlags.FLAG_SCENE_CONTAINER,
                 AconfigFlags.FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR,
                 KeyguardShadeMigrationNssl.FLAG_NAME,
+                MediaInSceneContainerFlag.FLAG_NAME,
             )
             .forEach { flagToken ->
                 setFlagsRule.enableFlags(flagToken)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsActivityTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsActivityTest.java
index 0f33aaf..2c7b606 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsActivityTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsActivityTest.java
@@ -56,6 +56,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -138,6 +139,7 @@
     }
 
     @Test
+    @Ignore("b/315848285")
     public void screenshotDisplayed_userConsented_screenshotExportedSuccessfully() {
         ResultReceiver resultReceiver = createResultReceiver((resultCode, data) -> {
             assertThat(resultCode).isEqualTo(RESULT_OK);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
index 657f912..e572dcc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
@@ -23,6 +23,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyFloat;
@@ -37,8 +39,6 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
-
 import android.annotation.IdRes;
 import android.content.ContentResolver;
 import android.content.res.Configuration;
@@ -86,6 +86,7 @@
 import com.android.systemui.classifier.FalsingManagerFake;
 import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository;
 import com.android.systemui.common.ui.view.LongPressHandlingView;
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor;
 import com.android.systemui.doze.DozeLog;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FakeFeatureFlagsClassic;
@@ -402,6 +403,10 @@
         mPowerInteractor = keyguardInteractorDeps.getPowerInteractor();
         when(mKeyguardTransitionInteractor.isInTransitionToStateWhere(any())).thenReturn(
                 StateFlowKt.MutableStateFlow(false));
+        DeviceEntryUdfpsInteractor deviceEntryUdfpsInteractor =
+                mock(DeviceEntryUdfpsInteractor.class);
+        when(deviceEntryUdfpsInteractor.isUdfpsSupported()).thenReturn(emptyFlow());
+
         mShadeInteractor = new ShadeInteractorImpl(
                 mTestScope.getBackgroundScope(),
                 new FakeDeviceProvisioningRepository(),
@@ -418,7 +423,9 @@
                         new SharedNotificationContainerInteractor(
                                 new FakeConfigurationRepository(),
                                 mContext,
-                                new ResourcesSplitShadeStateController()
+                                new ResourcesSplitShadeStateController(),
+                                mKeyguardInteractor,
+                                deviceEntryUdfpsInteractor
                         ),
                         mShadeRepository
                 )
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
index 39739e7..9d8b214 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
@@ -23,6 +23,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
@@ -54,6 +56,7 @@
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository;
 import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor;
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FakeFeatureFlagsClassic;
 import com.android.systemui.keyguard.KeyguardViewMediator;
@@ -75,6 +78,7 @@
 import com.android.systemui.scene.data.repository.SceneContainerRepository;
 import com.android.systemui.scene.domain.interactor.SceneInteractor;
 import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags;
+import com.android.systemui.scene.shared.flag.SceneContainerFlags;
 import com.android.systemui.scene.shared.logger.SceneLogger;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.shade.data.repository.FakeShadeRepository;
@@ -138,6 +142,7 @@
     @Mock private ShadeWindowLogger mShadeWindowLogger;
     @Mock private SelectedUserInteractor mSelectedUserInteractor;
     @Mock private UserTracker mUserTracker;
+    @Mock private SceneContainerFlags mSceneContainerFlags;
     @Captor private ArgumentCaptor<WindowManager.LayoutParams> mLayoutParameters;
     @Captor private ArgumentCaptor<StatusBarStateController.StateListener> mStateListener;
 
@@ -233,6 +238,11 @@
                 mKeyguardSecurityModel,
                 mSelectedUserInteractor,
                 powerInteractor);
+
+        DeviceEntryUdfpsInteractor deviceEntryUdfpsInteractor =
+                mock(DeviceEntryUdfpsInteractor.class);
+        when(deviceEntryUdfpsInteractor.isUdfpsSupported()).thenReturn(emptyFlow());
+
         mShadeInteractor = new ShadeInteractorImpl(
                 mTestScope.getBackgroundScope(),
                 new FakeDeviceProvisioningRepository(),
@@ -249,7 +259,9 @@
                         new SharedNotificationContainerInteractor(
                                 configurationRepository,
                                 mContext,
-                                new ResourcesSplitShadeStateController()),
+                                new ResourcesSplitShadeStateController(),
+                                keyguardInteractor,
+                                deviceEntryUdfpsInteractor),
                         shadeRepository
                 )
         );
@@ -274,7 +286,8 @@
                 () -> mShadeInteractor,
                 mShadeWindowLogger,
                 () -> mSelectedUserInteractor,
-                mUserTracker) {
+                mUserTracker,
+                mSceneContainerFlags) {
                     @Override
                     protected boolean isDebuggable() {
                         return false;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java
index e723d7d..eb5633b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java
@@ -22,6 +22,7 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
 import static kotlinx.coroutines.test.TestCoroutineDispatchersKt.StandardTestDispatcher;
 
 import android.content.res.Resources;
@@ -41,6 +42,7 @@
 import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository;
 import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository;
 import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor;
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FakeFeatureFlagsClassic;
 import com.android.systemui.flags.FeatureFlags;
@@ -275,6 +277,10 @@
         ResourcesSplitShadeStateController splitShadeStateController =
                 new ResourcesSplitShadeStateController();
 
+        DeviceEntryUdfpsInteractor deviceEntryUdfpsInteractor =
+                mock(DeviceEntryUdfpsInteractor.class);
+        when(deviceEntryUdfpsInteractor.isUdfpsSupported()).thenReturn(emptyFlow());
+
         mShadeInteractor = new ShadeInteractorImpl(
                 mTestScope.getBackgroundScope(),
                 deviceProvisioningRepository,
@@ -291,7 +297,9 @@
                         new SharedNotificationContainerInteractor(
                                 configurationRepository,
                                 mContext,
-                                splitShadeStateController),
+                                splitShadeStateController,
+                                keyguardInteractor,
+                                deviceEntryUdfpsInteractor),
                         mShadeRepository
                 )
         );
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt
index f8aa359..750693c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt
@@ -19,33 +19,20 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.shade.ShadeExpansionChangeEvent
-import com.android.systemui.shade.ShadeExpansionStateManager
-import com.android.systemui.shade.domain.model.ShadeModel
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.withArgCaptor
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.flow.launchIn
-import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.test.StandardTestDispatcher
 import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when`
-import org.mockito.MockitoAnnotations
 
 @OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class ShadeRepositoryImplTest : SysuiTestCase() {
 
-    @Mock private lateinit var shadeExpansionStateManager: ShadeExpansionStateManager
     private val testDispatcher = StandardTestDispatcher()
     private val testScope = TestScope(testDispatcher)
 
@@ -53,57 +40,10 @@
 
     @Before
     fun setUp() {
-        MockitoAnnotations.initMocks(this)
-
-        underTest = ShadeRepositoryImpl(shadeExpansionStateManager)
-        `when`(shadeExpansionStateManager.addExpansionListener(any()))
-            .thenReturn(ShadeExpansionChangeEvent(0f, false, false, 0f))
+        underTest = ShadeRepositoryImpl()
     }
 
     @Test
-    fun shadeExpansionChangeEvent() =
-        testScope.runTest {
-            var latest: ShadeModel? = null
-            val job = underTest.shadeModel.onEach { latest = it }.launchIn(this)
-            runCurrent()
-            assertThat(latest?.expansionAmount).isEqualTo(0f)
-            assertThat(latest?.isExpanded).isEqualTo(false)
-            assertThat(latest?.isUserDragging).isEqualTo(false)
-
-            val captor = withArgCaptor {
-                verify(shadeExpansionStateManager).addExpansionListener(capture())
-            }
-
-            captor.onPanelExpansionChanged(
-                ShadeExpansionChangeEvent(
-                    fraction = 1f,
-                    expanded = true,
-                    tracking = false,
-                    dragDownPxAmount = 0f,
-                )
-            )
-            runCurrent()
-            assertThat(latest?.expansionAmount).isEqualTo(1f)
-            assertThat(latest?.isExpanded).isEqualTo(true)
-            assertThat(latest?.isUserDragging).isEqualTo(false)
-
-            captor.onPanelExpansionChanged(
-                ShadeExpansionChangeEvent(
-                    fraction = .67f,
-                    expanded = false,
-                    tracking = true,
-                    dragDownPxAmount = 0f,
-                )
-            )
-            runCurrent()
-            assertThat(latest?.expansionAmount).isEqualTo(.67f)
-            assertThat(latest?.isExpanded).isEqualTo(false)
-            assertThat(latest?.isUserDragging).isEqualTo(true)
-
-            job.cancel()
-        }
-
-    @Test
     fun updateQsExpansion() =
         testScope.runTest {
             assertThat(underTest.qsExpansion.value).isEqualTo(0f)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java
index b98dc00..76c4015 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java
@@ -30,8 +30,6 @@
 
 import android.app.ActivityManager;
 import android.app.Notification;
-import android.os.Handler;
-import android.os.Looper;
 import android.os.UserHandle;
 import android.service.notification.StatusBarNotification;
 import android.testing.AndroidTestingRunner;
@@ -39,15 +37,18 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.policy.HeadsUpManagerLogger;
+import com.android.systemui.util.concurrency.DelayableExecutor;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.settings.FakeGlobalSettings;
+import com.android.systemui.util.time.FakeSystemClock;
+import com.android.systemui.util.time.SystemClock;
 
-import org.junit.After;
-import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -70,22 +71,27 @@
     protected static final int TEST_STICKY_AUTO_DISMISS_TIME = 800;
     // Number of notifications to use in tests requiring multiple notifications
     private static final int TEST_NUM_NOTIFICATIONS = 4;
-    protected static final int TEST_TIMEOUT_TIME = 2_000;
-    protected final Runnable mTestTimeoutRunnable = () -> mTimedOut = true;
 
-    protected Handler mTestHandler;
-    protected boolean mTimedOut = false;
+    protected final FakeGlobalSettings mGlobalSettings = new FakeGlobalSettings();
+    protected final FakeSystemClock mSystemClock = new FakeSystemClock();
+    protected final FakeExecutor mExecutor = new FakeExecutor(mSystemClock);
 
     @Mock protected ExpandableNotificationRow mRow;
 
+    static {
+        assertThat(TEST_MINIMUM_DISPLAY_TIME).isLessThan(TEST_AUTO_DISMISS_TIME);
+        assertThat(TEST_AUTO_DISMISS_TIME).isLessThan(TEST_STICKY_AUTO_DISMISS_TIME);
+    }
+
     private static class TestableAlertingNotificationManager extends AlertingNotificationManager {
         private AlertEntry mLastCreatedEntry;
 
-        private TestableAlertingNotificationManager(Handler handler) {
-            super(new HeadsUpManagerLogger(logcatLogBuffer()), handler);
+        private TestableAlertingNotificationManager(SystemClock systemClock,
+                DelayableExecutor executor) {
+            super(new HeadsUpManagerLogger(logcatLogBuffer()), systemClock, executor);
             mMinimumDisplayTime = TEST_MINIMUM_DISPLAY_TIME;
-            mAutoDismissNotificationDecay = TEST_AUTO_DISMISS_TIME;
-            mStickyDisplayTime = TEST_STICKY_AUTO_DISMISS_TIME;
+            mAutoDismissTime = TEST_AUTO_DISMISS_TIME;
+            mStickyForSomeTimeAutoDismissTime = TEST_STICKY_AUTO_DISMISS_TIME;
         }
 
         @Override
@@ -107,7 +113,7 @@
     }
 
     protected AlertingNotificationManager createAlertingNotificationManager() {
-        return new TestableAlertingNotificationManager(mTestHandler);
+        return new TestableAlertingNotificationManager(mSystemClock, mExecutor);
     }
 
     protected StatusBarNotification createSbn(int id, Notification n) {
@@ -144,39 +150,6 @@
         return new NotificationEntryBuilder().setSbn(createSbn(id)).build();
     }
 
-    protected void verifyAlertingAtTime(AlertingNotificationManager anm, NotificationEntry entry,
-            boolean shouldBeAlerting, int whenToCheckAlertingMillis, String whenCondition) {
-        final Boolean[] wasAlerting = {null};
-        final Runnable checkAlerting =
-                () -> wasAlerting[0] = anm.isAlerting(entry.getKey());
-
-        mTestHandler.postDelayed(checkAlerting, whenToCheckAlertingMillis);
-        mTestHandler.postDelayed(mTestTimeoutRunnable, TEST_TIMEOUT_TIME);
-        TestableLooper.get(this).processMessages(2);
-
-        assertFalse("Test timed out", mTimedOut);
-        if (shouldBeAlerting) {
-            assertTrue("Should still be alerting after " + whenCondition, wasAlerting[0]);
-        } else {
-            assertFalse("Should not still be alerting after " + whenCondition, wasAlerting[0]);
-        }
-        assertFalse("Should not still be alerting after processing",
-                anm.isAlerting(entry.getKey()));
-    }
-
-    @Before
-    public void setUp() {
-        mTestHandler = Handler.createAsync(Looper.myLooper());
-
-        assertThat(TEST_MINIMUM_DISPLAY_TIME).isLessThan(TEST_AUTO_DISMISS_TIME);
-        assertThat(TEST_AUTO_DISMISS_TIME).isLessThan(TEST_STICKY_AUTO_DISMISS_TIME);
-        assertThat(TEST_STICKY_AUTO_DISMISS_TIME).isLessThan(TEST_TIMEOUT_TIME);
-    }
-
-    @After
-    public void tearDown() {
-        mTestHandler.removeCallbacksAndMessages(null);
-    }
 
     @Test
     public void testShowNotification_addsEntry() {
@@ -196,9 +169,7 @@
         final NotificationEntry entry = createEntry(/* id = */ 0);
 
         alm.showNotification(entry);
-
-        verifyAlertingAtTime(alm, entry, false, TEST_AUTO_DISMISS_TIME * 3 / 2,
-                "auto dismiss time");
+        mSystemClock.advanceTime(TEST_AUTO_DISMISS_TIME * 3 / 2);
 
         assertFalse(alm.isAlerting(entry.getKey()));
     }
@@ -210,10 +181,8 @@
 
         alm.showNotification(entry);
 
-        // Try to remove but defer, since the notification has not been shown long enough.
-        final boolean removedImmediately = alm.removeNotification(entry.getKey(),
-                false /* releaseImmediately */);
-
+        final boolean removedImmediately = alm.removeNotification(
+                entry.getKey(), /* releaseImmediately = */ false);
         assertFalse(removedImmediately);
         assertTrue(alm.isAlerting(entry.getKey()));
     }
@@ -225,10 +194,8 @@
 
         alm.showNotification(entry);
 
-        // Remove forcibly with releaseImmediately = true.
-        final boolean removedImmediately = alm.removeNotification(entry.getKey(),
-                true /* releaseImmediately */);
-
+        final boolean removedImmediately = alm.removeNotification(
+                entry.getKey(), /* releaseImmediately = */ true);
         assertTrue(removedImmediately);
         assertFalse(alm.isAlerting(entry.getKey()));
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
index 8bc5e70..42c7375 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
@@ -55,8 +55,10 @@
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.FlagsParameterization;
 import android.provider.Settings;
-import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.util.SparseArray;
 
@@ -96,12 +98,26 @@
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.List;
 import java.util.concurrent.Executor;
 
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
+import platform.test.runner.parameterized.Parameters;
+
 @SmallTest
-@RunWith(AndroidTestingRunner.class)
+@RunWith(ParameterizedAndroidJunit4.class)
 @TestableLooper.RunWithLooper
 public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
+
+    @Parameters(name = "{0}")
+    public static List<FlagsParameterization> getParams() {
+        return FlagsParameterization.allCombinationsOf(FLAG_ALLOW_PRIVATE_PROFILE);
+    }
+
+    public NotificationLockscreenUserManagerTest(FlagsParameterization flags) {
+        mSetFlagsRule.setFlagsParameterization(flags);
+    }
+
     private static final int TEST_PROFILE_USERHANDLE = 12;
     @Mock
     private NotificationPresenter mPresenter;
@@ -499,6 +515,29 @@
     }
 
     @Test
+    public void testDevicePolicyDoesNotAllowNotifications_deviceOwnerSetsForUserAll() {
+        // User allows them
+        mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 1, mCurrentUser.id);
+        mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 1, mSecondaryUser.id);
+        changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
+
+        // DevicePolicy hides notifs on lockscreen
+        when(mDevicePolicyManager.getKeyguardDisabledFeatures(null, mCurrentUser.id))
+                .thenReturn(KEYGUARD_DISABLE_SECURE_NOTIFICATIONS);
+        when(mDevicePolicyManager.getKeyguardDisabledFeatures(null, mSecondaryUser.id))
+                .thenReturn(KEYGUARD_DISABLE_SECURE_NOTIFICATIONS);
+
+        BroadcastReceiver.PendingResult pr = new BroadcastReceiver.PendingResult(
+                0, null, null, 0, true, false, null, USER_ALL, 0);
+        mLockscreenUserManager.mAllUsersReceiver.setPendingResult(pr);
+        mLockscreenUserManager.mAllUsersReceiver.onReceive(mContext,
+                new Intent(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED));
+
+        assertFalse(mLockscreenUserManager.userAllowsNotificationsInPublic(mCurrentUser.id));
+        assertFalse(mLockscreenUserManager.userAllowsNotificationsInPublic(mSecondaryUser.id));
+    }
+
+    @Test
     public void testDevicePolicyDoesNotAllowNotifications_userAll() {
         // User allows them
         mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 1, mCurrentUser.id);
@@ -762,8 +801,8 @@
     }
 
     @Test
+    @EnableFlags(FLAG_ALLOW_PRIVATE_PROFILE)
     public void testProfileAvailabilityIntent() {
-        mSetFlagsRule.enableFlags(FLAG_ALLOW_PRIVATE_PROFILE);
         mLockscreenUserManager.mCurrentProfiles.clear();
         assertEquals(0, mLockscreenUserManager.mCurrentProfiles.size());
         mLockscreenUserManager.mCurrentProfiles.append(0, mock(UserInfo.class));
@@ -773,8 +812,8 @@
     }
 
     @Test
+    @EnableFlags(FLAG_ALLOW_PRIVATE_PROFILE)
     public void testProfileUnAvailabilityIntent() {
-        mSetFlagsRule.enableFlags(FLAG_ALLOW_PRIVATE_PROFILE);
         mLockscreenUserManager.mCurrentProfiles.clear();
         assertEquals(0, mLockscreenUserManager.mCurrentProfiles.size());
         mLockscreenUserManager.mCurrentProfiles.append(0, mock(UserInfo.class));
@@ -784,8 +823,8 @@
     }
 
     @Test
+    @DisableFlags(FLAG_ALLOW_PRIVATE_PROFILE)
     public void testManagedProfileAvailabilityIntent() {
-        mSetFlagsRule.disableFlags(FLAG_ALLOW_PRIVATE_PROFILE);
         mLockscreenUserManager.mCurrentProfiles.clear();
         mLockscreenUserManager.mCurrentManagedProfiles.clear();
         assertEquals(0, mLockscreenUserManager.mCurrentProfiles.size());
@@ -798,8 +837,8 @@
     }
 
     @Test
+    @DisableFlags(FLAG_ALLOW_PRIVATE_PROFILE)
     public void testManagedProfileUnAvailabilityIntent() {
-        mSetFlagsRule.disableFlags(FLAG_ALLOW_PRIVATE_PROFILE);
         mLockscreenUserManager.mCurrentProfiles.clear();
         mLockscreenUserManager.mCurrentManagedProfiles.clear();
         assertEquals(0, mLockscreenUserManager.mCurrentProfiles.size());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt
index dff91dd..f25ce0a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt
@@ -27,6 +27,7 @@
 import com.android.systemui.classifier.FalsingCollectorFake
 import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
 import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor;
 import com.android.systemui.flags.FakeFeatureFlagsClassic
 import com.android.systemui.keyguard.data.repository.FakeCommandQueue
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
@@ -53,6 +54,7 @@
 import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController
 import com.android.systemui.statusbar.policy.data.repository.FakeDeviceProvisioningRepository
 import com.android.systemui.util.mockito.mock
+import kotlinx.coroutines.flow.emptyFlow
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertFalse
 import org.junit.Assert.assertTrue
@@ -83,6 +85,7 @@
         FromPrimaryBouncerTransitionInteractor
     @Mock lateinit var interactionJankMonitor: InteractionJankMonitor
     @Mock lateinit var mockDarkAnimator: ObjectAnimator
+    @Mock lateinit var deviceEntryUdfpsInteractor: DeviceEntryUdfpsInteractor
 
     private lateinit var controller: StatusBarStateControllerImpl
     private lateinit var uiEventLogger: UiEventLoggerFake
@@ -164,6 +167,8 @@
                 mock(),
                 powerInteractor
             )
+
+        whenever(deviceEntryUdfpsInteractor.isUdfpsSupported).thenReturn(emptyFlow())
         shadeInteractor =
             ShadeInteractorImpl(
                 testScope.backgroundScope,
@@ -181,7 +186,9 @@
                     SharedNotificationContainerInteractor(
                         configurationRepository,
                         mContext,
-                        ResourcesSplitShadeStateController()
+                        ResourcesSplitShadeStateController(),
+                        keyguardInteractor,
+                        deviceEntryUdfpsInteractor,
                     ),
                     shadeRepository,
                 )
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImplTest.kt
index 3fef1d9..5bc75e8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImplTest.kt
@@ -148,6 +148,24 @@
     }
 
     @Test
+    fun onWifiEntriesChanged_reasonIsScanResults_fireWifiScanCallbackFalse() {
+        controller.addAccessPointCallback(callback)
+
+        controller.onWifiEntriesChanged(WifiPickerTracker.WIFI_ENTRIES_CHANGED_REASON_SCAN_RESULTS)
+
+        verify(callback).onWifiScan(false)
+    }
+
+    @Test
+    fun onScanRequested_fireWifiScanCallbackTrue() {
+        controller.addAccessPointCallback(callback)
+
+        controller.onScanRequested()
+
+        verify(callback).onWifiScan(true)
+    }
+
+    @Test
     fun testOnNumSavedNetworksChangedDoesntTriggerCallback() {
         controller.addAccessPointCallback(callback)
         controller.onNumSavedNetworksChanged()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
index bfa03ee..8cf64a5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
@@ -48,7 +48,6 @@
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.util.ArrayMap;
-import android.util.Log;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -56,6 +55,7 @@
 
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.log.LogAssertKt;
 import com.android.systemui.statusbar.NotificationInteractionTracker;
 import com.android.systemui.statusbar.RankingBuilder;
 import com.android.systemui.statusbar.notification.NotifPipelineFlags;
@@ -76,6 +76,7 @@
 import com.android.systemui.statusbar.notification.collection.notifcollection.CollectionReadyForBuildListener;
 import com.android.systemui.util.time.FakeSystemClock;
 
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -129,10 +130,6 @@
     private Map<String, Integer> mNextIdMap = new ArrayMap<>();
     private int mNextRank = 0;
 
-    private Log.TerribleFailureHandler mOldWtfHandler = null;
-    private Log.TerribleFailure mLastWtf = null;
-    private int mWtfCount = 0;
-
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
@@ -1756,20 +1753,19 @@
         mListBuilder.addPreGroupFilter(filter);
         mListBuilder.addOnBeforeTransformGroupsListener(listener);
 
-        interceptWtfs();
-
         // WHEN we try to run the pipeline and the filter is invalidated exactly
         // MAX_CONSECUTIVE_REENTRANT_REBUILDS times,
         addNotif(0, PACKAGE_2);
         invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS);
-        dispatchBuild();
-        runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2);
 
         // THEN an exception is NOT thrown directly, but a WTF IS logged.
-        expectWtfs(MAX_CONSECUTIVE_REENTRANT_REBUILDS);
+        LogAssertKt.assertLogsWtfs(() -> {
+            dispatchBuild();
+            runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2);
+        });
     }
 
-    @Test(expected = IllegalStateException.class)
+    @Test
     public void testOutOfOrderPreGroupFilterInvalidationThrowsAfterTooManyRuns() {
         // GIVEN a PreGroupNotifFilter that gets invalidated during the grouping stage,
         NotifFilter filter = new PackageFilter(PACKAGE_1);
@@ -1778,20 +1774,20 @@
         mListBuilder.addPreGroupFilter(filter);
         mListBuilder.addOnBeforeTransformGroupsListener(listener);
 
-        interceptWtfs();
-
         // WHEN we try to run the pipeline and the filter is invalidated more than
         // MAX_CONSECUTIVE_REENTRANT_REBUILDS times,
-        addNotif(0, PACKAGE_2);
-        invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 1);
-        dispatchBuild();
-        try {
-            runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2);
-        } finally {
-            expectWtfs(MAX_CONSECUTIVE_REENTRANT_REBUILDS);
-        }
 
         // THEN an exception IS thrown.
+
+        addNotif(0, PACKAGE_2);
+        invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 1);
+
+        LogAssertKt.assertLogsWtfs(() -> {
+            Assert.assertThrows(IllegalStateException.class, () -> {
+                dispatchBuild();
+                runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2);
+            });
+        });
     }
 
     @Test
@@ -1803,26 +1799,30 @@
         mListBuilder.addPreGroupFilter(filter);
         mListBuilder.addOnBeforeTransformGroupsListener(listener);
 
-        interceptWtfs();
-
         // WHEN we try to run the pipeline and the filter is invalidated
         // MAX_CONSECUTIVE_REENTRANT_REBUILDS times, the pipeline runs for a non-reentrant reason,
         // and then the filter is invalidated MAX_CONSECUTIVE_REENTRANT_REBUILDS times again,
-        addNotif(0, PACKAGE_2);
-        invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS);
-        dispatchBuild();
-        runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2);
-        invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS);
-        // Note: dispatchBuild itself triggers a non-reentrant pipeline run.
-        dispatchBuild();
-        runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2);
 
         // THEN an exception is NOT thrown, but WTFs ARE logged.
-        expectWtfs(MAX_CONSECUTIVE_REENTRANT_REBUILDS * 2);
+
+        addNotif(0, PACKAGE_2);
+
+        invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS);
+        LogAssertKt.assertLogsWtfs(() -> {
+            dispatchBuild();
+            runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2);
+        });
+
+        invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS);
+        LogAssertKt.assertLogsWtfs(() -> {
+            // Note: dispatchBuild itself triggers a non-reentrant pipeline run.
+            dispatchBuild();
+            runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2);
+        });
     }
 
     @Test
-    public void testOutOfOrderPrompterInvalidationDoesNotThrowBeforeTooManyRuns() {
+    public void testOutOfOrderPromoterInvalidationDoesNotThrowBeforeTooManyRuns() {
         // GIVEN a NotifPromoter that gets invalidated during the sorting stage,
         NotifPromoter promoter = new IdPromoter(47);
         CountingInvalidator invalidator = new CountingInvalidator(promoter);
@@ -1830,22 +1830,22 @@
         mListBuilder.addPromoter(promoter);
         mListBuilder.addOnBeforeSortListener(listener);
 
-        interceptWtfs();
-
         // WHEN we try to run the pipeline and the promoter is invalidated exactly
         // MAX_CONSECUTIVE_REENTRANT_REBUILDS times,
-        addNotif(0, PACKAGE_1);
-        invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS);
-        dispatchBuild();
-        runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2);
 
         // THEN an exception is NOT thrown directly, but a WTF IS logged.
-        expectWtfs(MAX_CONSECUTIVE_REENTRANT_REBUILDS);
 
+        addNotif(0, PACKAGE_1);
+        invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS);
+
+        LogAssertKt.assertLogsWtfs(() -> {
+            dispatchBuild();
+            runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2);
+        });
     }
 
-    @Test(expected = IllegalStateException.class)
-    public void testOutOfOrderPrompterInvalidationThrowsAfterTooManyRuns() {
+    @Test
+    public void testOutOfOrderPromoterInvalidationThrowsAfterTooManyRuns() {
         // GIVEN a NotifPromoter that gets invalidated during the sorting stage,
         NotifPromoter promoter = new IdPromoter(47);
         CountingInvalidator invalidator = new CountingInvalidator(promoter);
@@ -1853,20 +1853,20 @@
         mListBuilder.addPromoter(promoter);
         mListBuilder.addOnBeforeSortListener(listener);
 
-        interceptWtfs();
-
         // WHEN we try to run the pipeline and the promoter is invalidated more than
         // MAX_CONSECUTIVE_REENTRANT_REBUILDS times,
-        addNotif(0, PACKAGE_1);
-        invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 1);
-        dispatchBuild();
-        try {
-            runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2);
-        } finally {
-            expectWtfs(MAX_CONSECUTIVE_REENTRANT_REBUILDS);
-        }
 
         // THEN an exception IS thrown.
+
+        addNotif(0, PACKAGE_1);
+        invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 1);
+
+        LogAssertKt.assertLogsWtfs(() -> {
+            Assert.assertThrows(IllegalStateException.class, () -> {
+                dispatchBuild();
+                runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2);
+            });
+        });
     }
 
     @Test
@@ -1878,20 +1878,21 @@
         mListBuilder.setComparators(singletonList(comparator));
         mListBuilder.addOnBeforeRenderListListener(listener);
 
-        interceptWtfs();
-
         // WHEN we try to run the pipeline and the comparator is invalidated exactly
         // MAX_CONSECUTIVE_REENTRANT_REBUILDS times,
-        addNotif(0, PACKAGE_2);
-        invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS);
-        dispatchBuild();
-        runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2);
 
         // THEN an exception is NOT thrown directly, but a WTF IS logged.
-        expectWtfs(MAX_CONSECUTIVE_REENTRANT_REBUILDS);
+
+        addNotif(0, PACKAGE_2);
+        invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS);
+
+        LogAssertKt.assertLogsWtfs(() -> {
+            dispatchBuild();
+            runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2);
+        });
     }
 
-    @Test(expected = IllegalStateException.class)
+    @Test
     public void testOutOfOrderComparatorInvalidationThrowsAfterTooManyRuns() {
         // GIVEN a NotifComparator that gets invalidated during the finalizing stage,
         NotifComparator comparator = new HypeComparator(PACKAGE_1);
@@ -1900,16 +1901,20 @@
         mListBuilder.setComparators(singletonList(comparator));
         mListBuilder.addOnBeforeRenderListListener(listener);
 
-        interceptWtfs();
-
         // WHEN we try to run the pipeline and the comparator is invalidated more than
         // MAX_CONSECUTIVE_REENTRANT_REBUILDS times,
-        addNotif(0, PACKAGE_2);
-        invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 1);
-        dispatchBuild();
-        runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2);
 
         // THEN an exception IS thrown.
+
+        addNotif(0, PACKAGE_2);
+        invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 1);
+
+        LogAssertKt.assertLogsWtfs(() -> {
+            Assert.assertThrows(IllegalStateException.class, () -> {
+                dispatchBuild();
+                runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2);
+            });
+        });
     }
 
     @Test
@@ -1921,20 +1926,21 @@
         mListBuilder.addFinalizeFilter(filter);
         mListBuilder.addOnBeforeRenderListListener(listener);
 
-        interceptWtfs();
-
         // WHEN we try to run the pipeline and the PreRenderFilter is invalidated exactly
         // MAX_CONSECUTIVE_REENTRANT_REBUILDS times,
-        addNotif(0, PACKAGE_2);
-        invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS);
-        dispatchBuild();
-        runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2);
 
         // THEN an exception is NOT thrown directly, but a WTF IS logged.
-        expectWtfs(MAX_CONSECUTIVE_REENTRANT_REBUILDS);
+
+        addNotif(0, PACKAGE_2);
+        invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS);
+
+        LogAssertKt.assertLogsWtfs(() -> {
+            dispatchBuild();
+            runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2);
+        });
     }
 
-    @Test(expected = IllegalStateException.class)
+    @Test
     public void testOutOfOrderPreRenderFilterInvalidationThrowsAfterTooManyRuns() {
         // GIVEN a PreRenderNotifFilter that gets invalidated during the finalizing stage,
         NotifFilter filter = new PackageFilter(PACKAGE_1);
@@ -1943,59 +1949,22 @@
         mListBuilder.addFinalizeFilter(filter);
         mListBuilder.addOnBeforeRenderListListener(listener);
 
-        interceptWtfs();
-
         // WHEN we try to run the pipeline and the PreRenderFilter is invalidated more than
         // MAX_CONSECUTIVE_REENTRANT_REBUILDS times,
-        addNotif(0, PACKAGE_2);
-        invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 1);
-        dispatchBuild();
-        try {
-            runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2);
-        } finally {
-            expectWtfs(MAX_CONSECUTIVE_REENTRANT_REBUILDS);
-        }
 
         // THEN an exception IS thrown.
-    }
 
-    private void interceptWtfs() {
-        assertNull(mOldWtfHandler);
+        addNotif(0, PACKAGE_2);
+        invalidator.setInvalidationCount(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 1);
 
-        mLastWtf = null;
-        mWtfCount = 0;
-
-        mOldWtfHandler = Log.setWtfHandler((tag, e, system) -> {
-            Log.e("ShadeListBuilderTest", "Observed WTF: " + e);
-            mLastWtf = e;
-            mWtfCount++;
+        LogAssertKt.assertLogsWtfs(() -> {
+            Assert.assertThrows(IllegalStateException.class, () -> {
+                dispatchBuild();
+                runWhileScheduledUpTo(MAX_CONSECUTIVE_REENTRANT_REBUILDS + 2);
+            });
         });
     }
 
-    private void expectNoWtfs() {
-        assertNull(expectWtfs(0));
-    }
-
-    private Log.TerribleFailure expectWtf() {
-        return expectWtfs(1);
-    }
-
-    private Log.TerribleFailure expectWtfs(int expectedWtfCount) {
-        assertNotNull(mOldWtfHandler);
-
-        Log.setWtfHandler(mOldWtfHandler);
-        mOldWtfHandler = null;
-
-        Log.TerribleFailure wtf = mLastWtf;
-        int wtfCount = mWtfCount;
-
-        mLastWtf = null;
-        mWtfCount = 0;
-
-        assertEquals(expectedWtfCount, wtfCount);
-        return wtf;
-    }
-
     @Test
     public void testStableOrdering() {
         mStabilityManager.setAllowEntryReordering(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt
index fa5fad0..255cf6f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt
@@ -15,11 +15,12 @@
  */
 package com.android.systemui.statusbar.notification.collection.coordinator
 
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper.RunWithLooper
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.flags.setFlagValue
 import com.android.systemui.statusbar.notification.collection.NotifPipeline
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
@@ -40,10 +41,9 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Mock
-import org.mockito.Mockito.reset
 import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when` as whenever
 import org.mockito.MockitoAnnotations.initMocks
+import org.mockito.Mockito.`when` as whenever
 
 @SmallTest
 @RunWith(AndroidTestingRunner::class)
@@ -66,12 +66,6 @@
     fun setUp() {
         initMocks(this)
         entry = NotificationEntryBuilder().setSection(section).build()
-        setUpWithFlags()
-    }
-
-    private fun setUpWithFlags(vararg flags: Pair<String, Boolean>) {
-        flags.forEach { (name, value) -> mSetFlagsRule.setFlagValue(name, value) }
-        reset(pipeline)
         coordinator =
             StackCoordinator(
                 groupExpansionManagerImpl,
@@ -86,15 +80,15 @@
     }
 
     @Test
+    @DisableFlags(NotificationIconContainerRefactor.FLAG_NAME)
     fun testUpdateNotificationIcons() {
-        setUpWithFlags(NotificationIconContainerRefactor.FLAG_NAME to false)
         afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
         verify(notificationIconAreaController).updateNotificationIcons(eq(listOf(entry)))
     }
 
     @Test
+    @EnableFlags(NotificationIconContainerRefactor.FLAG_NAME)
     fun testSetRenderedListOnInteractor() {
-        setUpWithFlags(NotificationIconContainerRefactor.FLAG_NAME to true)
         afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
         verify(renderListInteractor).setRenderedList(eq(listOf(entry)))
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterViewTest.java
index 22c5bae..57dac3a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterViewTest.java
@@ -16,12 +16,11 @@
 
 package com.android.systemui.statusbar.notification.footer.ui.view;
 
+import static com.android.systemui.log.LogAssertKt.assertLogsWtf;
 import static com.google.common.truth.Truth.assertThat;
-
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertNotNull;
 import static junit.framework.Assert.assertTrue;
-
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.clearInvocations;
@@ -31,33 +30,47 @@
 import static org.mockito.Mockito.verify;
 
 import android.content.Context;
-import android.testing.AndroidTestingRunner;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.FlagsParameterization;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.TextView;
 
 import androidx.test.filters.SmallTest;
 
-import com.android.systemui.Flags;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.res.R;
+import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.List;
+
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
+import platform.test.runner.parameterized.Parameters;
+
 @SmallTest
-@RunWith(AndroidTestingRunner.class)
+@RunWith(ParameterizedAndroidJunit4.class)
 public class FooterViewTest extends SysuiTestCase {
 
+    @Parameters(name = "{0}")
+    public static List<FlagsParameterization> getFlags() {
+        return FlagsParameterization.allCombinationsOf(FooterViewRefactor.FLAG_NAME);
+    }
+
+    public FooterViewTest(FlagsParameterization flags) {
+        mSetFlagsRule.setFlagsParameterization(flags);
+    }
+
     FooterView mView;
 
     Context mSpyContext = spy(mContext);
 
     @Before
     public void setUp() {
-        mSetFlagsRule.enableFlags(Flags.FLAG_NOTIFICATIONS_FOOTER_VIEW_REFACTOR);
-
         mView = (FooterView) LayoutInflater.from(mSpyContext).inflate(
                 R.layout.status_bar_notification_footer, null, false);
         mView.setAnimationDuration(0);
@@ -114,6 +127,7 @@
     }
 
     @Test
+    @EnableFlags(FooterViewRefactor.FLAG_NAME)
     public void testSetClearAllButtonText_resourceOnlyFetchedOnce() {
         int resId = R.string.clear_all_notifications_text;
         mView.setClearAllButtonText(resId);
@@ -132,6 +146,16 @@
     }
 
     @Test
+    @DisableFlags(FooterViewRefactor.FLAG_NAME)
+    public void testSetClearAllButtonText_expectsFlagEnabled() {
+        clearInvocations(mSpyContext);
+        int resId = R.string.clear_all_notifications_text;
+        assertLogsWtf(()-> mView.setClearAllButtonText(resId));
+        verify(mSpyContext, never()).getString(anyInt());
+    }
+
+    @Test
+    @EnableFlags(FooterViewRefactor.FLAG_NAME)
     public void testSetClearAllButtonDescription_resourceOnlyFetchedOnce() {
         int resId = R.string.accessibility_clear_all;
         mView.setClearAllButtonDescription(resId);
@@ -150,6 +174,16 @@
     }
 
     @Test
+    @DisableFlags(FooterViewRefactor.FLAG_NAME)
+    public void testSetClearAllButtonDescription_expectsFlagEnabled() {
+        clearInvocations(mSpyContext);
+        int resId = R.string.accessibility_clear_all;
+        assertLogsWtf(()-> mView.setClearAllButtonDescription(resId));
+        verify(mSpyContext, never()).getString(anyInt());
+    }
+
+    @Test
+    @EnableFlags(FooterViewRefactor.FLAG_NAME)
     public void testSetMessageString_resourceOnlyFetchedOnce() {
         int resId = R.string.unlock_to_see_notif_text;
         mView.setMessageString(resId);
@@ -168,6 +202,16 @@
     }
 
     @Test
+    @DisableFlags(FooterViewRefactor.FLAG_NAME)
+    public void testSetMessageString_expectsFlagEnabled() {
+        clearInvocations(mSpyContext);
+        int resId = R.string.unlock_to_see_notif_text;
+        assertLogsWtf(()-> mView.setMessageString(resId));
+        verify(mSpyContext, never()).getString(anyInt());
+    }
+
+    @Test
+    @EnableFlags(FooterViewRefactor.FLAG_NAME)
     public void testSetMessageIcon_resourceOnlyFetchedOnce() {
         int resId = R.drawable.ic_friction_lock_closed;
         mView.setMessageIcon(resId);
@@ -183,6 +227,15 @@
     }
 
     @Test
+    @DisableFlags(FooterViewRefactor.FLAG_NAME)
+    public void testSetMessageIcon_expectsFlagEnabled() {
+        clearInvocations(mSpyContext);
+        int resId = R.drawable.ic_friction_lock_closed;
+        assertLogsWtf(()-> mView.setMessageIcon(resId));
+        verify(mSpyContext, never()).getDrawable(anyInt());
+    }
+
+    @Test
     public void testSetFooterLabelVisible() {
         mView.setFooterLabelVisible(true);
         assertThat(mView.findViewById(R.id.manage_text).getVisibility()).isEqualTo(View.GONE);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModelTest.kt
index 0ba820f..8ab13f5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModelTest.kt
@@ -16,9 +16,9 @@
 
 package com.android.systemui.statusbar.notification.footer.ui.viewmodel
 
+import android.platform.test.annotations.EnableFlags
 import android.testing.AndroidTestingRunner
 import androidx.test.filters.SmallTest
-import com.android.systemui.Flags
 import com.android.systemui.SysUITestComponent
 import com.android.systemui.SysUITestModule
 import com.android.systemui.SysuiTestCase
@@ -38,6 +38,7 @@
 import com.android.systemui.shade.data.repository.FakeShadeRepository
 import com.android.systemui.statusbar.notification.collection.render.NotifStats
 import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository
+import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor
 import com.android.systemui.statusbar.notification.row.ui.viewmodel.ActivatableNotificationViewModelModule
 import com.android.systemui.statusbar.phone.DozeParameters
 import com.android.systemui.user.domain.interactor.HeadlessSystemUserModeModule
@@ -55,6 +56,7 @@
 
 @RunWith(AndroidTestingRunner::class)
 @SmallTest
+@EnableFlags(FooterViewRefactor.FLAG_NAME)
 class FooterViewModelTest : SysuiTestCase() {
     private lateinit var footerViewModel: FooterViewModel
 
@@ -106,8 +108,6 @@
     fun setUp() {
         MockitoAnnotations.initMocks(this)
 
-        mSetFlagsRule.enableFlags(Flags.FLAG_NOTIFICATIONS_FOOTER_VIEW_REFACTOR)
-
         // The underTest in the component is Optional, because that matches the provider we
         // currently have for the footer view model.
         footerViewModel = testComponent.underTest.get()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderWrapperTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderWrapperTest.kt
index 7361f6b..7ed3312 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderWrapperTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderWrapperTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.notification.interruption
 
+import android.platform.test.annotations.DisableFlags
 import android.testing.AndroidTestingRunner
 import androidx.test.filters.SmallTest
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
@@ -34,11 +35,8 @@
 
 @SmallTest
 @RunWith(AndroidTestingRunner::class)
+@DisableFlags(VisualInterruptionRefactor.FLAG_NAME)
 class NotificationInterruptStateProviderWrapperTest : VisualInterruptionDecisionProviderTestBase() {
-    init {
-        mSetFlagsRule.disableFlags(VisualInterruptionRefactor.FLAG_NAME)
-    }
-
     override val provider by lazy {
         NotificationInterruptStateProviderWrapper(
             NotificationInterruptStateProviderImpl(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImplTest.kt
index d2c046c..da68d9c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImplTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.notification.interruption
 
+import android.platform.test.annotations.EnableFlags
 import android.testing.AndroidTestingRunner
 import androidx.test.filters.SmallTest
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
@@ -27,11 +28,8 @@
 
 @SmallTest
 @RunWith(AndroidTestingRunner::class)
+@EnableFlags(VisualInterruptionRefactor.FLAG_NAME)
 class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionProviderTestBase() {
-    init {
-        mSetFlagsRule.enableFlags(VisualInterruptionRefactor.FLAG_NAME)
-    }
-
     override val provider by lazy {
         VisualInterruptionDecisionProviderImpl(
             ambientDisplayConfiguration,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractorTest.kt
index 198f278..327a07d6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractorTest.kt
@@ -19,56 +19,87 @@
 
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
-import com.android.systemui.res.R
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
+import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository
+import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
 import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController
+import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.res.R
+import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
-import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class SharedNotificationContainerInteractorTest : SysuiTestCase() {
-    private lateinit var configurationRepository: FakeConfigurationRepository
-    private lateinit var underTest: SharedNotificationContainerInteractor
-
-    @Before
-    fun setUp() {
-        configurationRepository = FakeConfigurationRepository()
-        underTest =
-            SharedNotificationContainerInteractor(
-                configurationRepository,
-                mContext,
-                ResourcesSplitShadeStateController()
-            )
-    }
+    private val kosmos = testKosmos()
+    private val testScope = kosmos.testScope
+    private val keyguardRepository = kosmos.fakeKeyguardRepository
+    private val configurationRepository = kosmos.fakeConfigurationRepository
+    private val fingerprintPropertyRepository = kosmos.fingerprintPropertyRepository
+    private val underTest = kosmos.sharedNotificationContainerInteractor
 
     @Test
-    fun validateConfigValues() = runTest {
-        overrideResource(R.bool.config_use_split_notification_shade, true)
-        overrideResource(R.bool.config_use_large_screen_shade_header, false)
-        overrideResource(R.dimen.notification_panel_margin_horizontal, 0)
-        overrideResource(R.dimen.notification_panel_margin_bottom, 10)
-        overrideResource(R.dimen.notification_panel_margin_top, 10)
-        overrideResource(R.dimen.large_screen_shade_header_height, 0)
+    fun validateConfigValues() =
+        testScope.runTest {
+            overrideResource(R.bool.config_use_split_notification_shade, true)
+            overrideResource(R.bool.config_use_large_screen_shade_header, false)
+            overrideResource(R.dimen.notification_panel_margin_horizontal, 0)
+            overrideResource(R.dimen.notification_panel_margin_bottom, 10)
+            overrideResource(R.dimen.notification_panel_margin_top, 10)
+            overrideResource(R.dimen.large_screen_shade_header_height, 0)
+            overrideResource(R.dimen.keyguard_split_shade_top_margin, 55)
 
-        val dimens = collectLastValue(underTest.configurationBasedDimensions)
+            val dimens = collectLastValue(underTest.configurationBasedDimensions)
 
-        configurationRepository.onAnyConfigurationChange()
-        runCurrent()
+            configurationRepository.onAnyConfigurationChange()
+            runCurrent()
 
-        val lastDimens = dimens()!!
+            val lastDimens = dimens()!!
 
-        assertThat(lastDimens.useSplitShade).isTrue()
-        assertThat(lastDimens.useLargeScreenHeader).isFalse()
-        assertThat(lastDimens.marginHorizontal).isEqualTo(0)
-        assertThat(lastDimens.marginBottom).isGreaterThan(0)
-        assertThat(lastDimens.marginTop).isGreaterThan(0)
-        assertThat(lastDimens.marginTopLargeScreen).isEqualTo(0)
-    }
+            assertThat(lastDimens.useSplitShade).isTrue()
+            assertThat(lastDimens.useLargeScreenHeader).isFalse()
+            assertThat(lastDimens.marginHorizontal).isEqualTo(0)
+            assertThat(lastDimens.marginBottom).isGreaterThan(0)
+            assertThat(lastDimens.marginTop).isGreaterThan(0)
+            assertThat(lastDimens.marginTopLargeScreen).isEqualTo(0)
+            assertThat(lastDimens.keyguardSplitShadeTopMargin).isEqualTo(55)
+        }
+
+    @Test
+    fun useExtraShelfSpaceIsTrueWithUdfps() =
+        testScope.runTest {
+            val useExtraShelfSpace by collectLastValue(underTest.useExtraShelfSpace)
+
+            keyguardRepository.ambientIndicationVisible.value = true
+            fingerprintPropertyRepository.supportsUdfps()
+
+            assertThat(useExtraShelfSpace).isEqualTo(true)
+        }
+
+    @Test
+    fun useExtraShelfSpaceIsTrueWithRearFpsAndNoAmbientIndicationArea() =
+        testScope.runTest {
+            val useExtraShelfSpace by collectLastValue(underTest.useExtraShelfSpace)
+
+            keyguardRepository.ambientIndicationVisible.value = false
+            fingerprintPropertyRepository.supportsRearFps()
+
+            assertThat(useExtraShelfSpace).isEqualTo(true)
+        }
+
+    @Test
+    fun useExtraShelfSpaceIsFalseWithRearFpsAndAmbientIndicationArea() =
+        testScope.runTest {
+            val useExtraShelfSpace by collectLastValue(underTest.useExtraShelfSpace)
+
+            keyguardRepository.ambientIndicationVisible.value = true
+            fingerprintPropertyRepository.supportsRearFps()
+
+            assertThat(useExtraShelfSpace).isEqualTo(false)
+        }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelTest.kt
index f00abc9..21774aa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelTest.kt
@@ -19,10 +19,10 @@
 package com.android.systemui.statusbar.notification.stack.ui.viewmodel
 
 import android.app.NotificationManager.Policy
+import android.platform.test.annotations.EnableFlags
 import android.provider.Settings
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
-import com.android.systemui.Flags
 import com.android.systemui.SysUITestComponent
 import com.android.systemui.SysUITestModule
 import com.android.systemui.SysuiTestCase
@@ -41,6 +41,7 @@
 import com.android.systemui.shade.data.repository.FakeShadeRepository
 import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository
 import com.android.systemui.statusbar.notification.data.repository.setActiveNotifs
+import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor
 import com.android.systemui.statusbar.notification.footer.ui.viewmodel.FooterViewModelModule
 import com.android.systemui.statusbar.notification.row.ui.viewmodel.ActivatableNotificationViewModelModule
 import com.android.systemui.statusbar.policy.FakeConfigurationController
@@ -59,6 +60,7 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4::class)
+@EnableFlags(FooterViewRefactor.FLAG_NAME)
 class NotificationListViewModelTest : SysuiTestCase() {
 
     @SysUISingleton
@@ -104,8 +106,6 @@
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
-
-        mSetFlagsRule.enableFlags(Flags.FLAG_NOTIFICATIONS_FOOTER_VIEW_REFACTOR)
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
index b4f7b20..36a4712 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
@@ -26,7 +26,7 @@
 import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.flags.Flags
-import com.android.systemui.flags.featureFlagsClassic
+import com.android.systemui.flags.fakeFeatureFlagsClassic
 import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
 import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
@@ -55,7 +55,7 @@
 
     val kosmos =
         testKosmos().apply {
-            featureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) }
+            fakeFeatureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) }
         }
     val testScope = kosmos.testScope
     val configurationRepository = kosmos.fakeConfigurationRepository
@@ -100,6 +100,34 @@
         }
 
     @Test
+    fun validatePaddingTopInSplitShade() =
+        testScope.runTest {
+            overrideResource(R.bool.config_use_split_notification_shade, true)
+            overrideResource(R.dimen.large_screen_shade_header_height, 10)
+            overrideResource(R.dimen.keyguard_split_shade_top_margin, 50)
+
+            val dimens by collectLastValue(underTest.configurationBasedDimensions)
+
+            configurationRepository.onAnyConfigurationChange()
+
+            assertThat(dimens!!.paddingTop).isEqualTo(30)
+        }
+
+    @Test
+    fun validatePaddingTop() =
+        testScope.runTest {
+            overrideResource(R.bool.config_use_split_notification_shade, false)
+            overrideResource(R.dimen.large_screen_shade_header_height, 10)
+            overrideResource(R.dimen.keyguard_split_shade_top_margin, 50)
+
+            val dimens by collectLastValue(underTest.configurationBasedDimensions)
+
+            configurationRepository.onAnyConfigurationChange()
+
+            assertThat(dimens!!.paddingTop).isEqualTo(0)
+        }
+
+    @Test
     fun validateMarginEnd() =
         testScope.runTest {
             overrideResource(R.dimen.notification_panel_margin_horizontal, 50)
@@ -226,9 +254,9 @@
         }
 
     @Test
-    fun positionOnLockscreenNotInSplitShade() =
+    fun boundsOnLockscreenNotInSplitShade() =
         testScope.runTest {
-            val position by collectLastValue(underTest.bounds)
+            val bounds by collectLastValue(underTest.bounds)
 
             // When not in split shade
             overrideResource(R.bool.config_use_split_notification_shade, false)
@@ -242,16 +270,19 @@
                 NotificationContainerBounds(top = 1f, bottom = 2f)
             )
 
-            assertThat(position).isEqualTo(NotificationContainerBounds(top = 1f, bottom = 2f))
+            assertThat(bounds).isEqualTo(NotificationContainerBounds(top = 1f, bottom = 2f))
         }
 
     @Test
-    fun positionOnLockscreenInSplitShade() =
+    fun boundsOnLockscreenInSplitShade() =
         testScope.runTest {
-            val position by collectLastValue(underTest.bounds)
+            val bounds by collectLastValue(underTest.bounds)
 
             // When in split shade
             overrideResource(R.bool.config_use_split_notification_shade, true)
+            overrideResource(R.dimen.large_screen_shade_header_height, 10)
+            overrideResource(R.dimen.keyguard_split_shade_top_margin, 50)
+
             configurationRepository.onAnyConfigurationChange()
             runCurrent()
 
@@ -263,8 +294,8 @@
             )
             runCurrent()
 
-            // Top should be overridden to 0f
-            assertThat(position).isEqualTo(NotificationContainerBounds(top = 0f, bottom = 2f))
+            // Top should be equal to bounds (1) + padding adjustment (30)
+            assertThat(bounds).isEqualTo(NotificationContainerBounds(top = 31f, bottom = 2f))
         }
 
     @Test
@@ -301,8 +332,8 @@
     fun maxNotificationsOnLockscreen() =
         testScope.runTest {
             var notificationCount = 10
-            val maxNotifications by
-                collectLastValue(underTest.getMaxNotifications { notificationCount })
+            val calculateSpace = { space: Float, useExtraShelfSpace: Boolean -> notificationCount }
+            val maxNotifications by collectLastValue(underTest.getMaxNotifications(calculateSpace))
 
             showLockscreen()
 
@@ -324,8 +355,8 @@
     fun maxNotificationsOnLockscreen_DoesNotUpdateWhenUserInteracting() =
         testScope.runTest {
             var notificationCount = 10
-            val maxNotifications by
-                collectLastValue(underTest.getMaxNotifications { notificationCount })
+            val calculateSpace = { space: Float, useExtraShelfSpace: Boolean -> notificationCount }
+            val maxNotifications by collectLastValue(underTest.getMaxNotifications(calculateSpace))
 
             showLockscreen()
 
@@ -359,7 +390,8 @@
     @Test
     fun maxNotificationsOnShade() =
         testScope.runTest {
-            val maxNotifications by collectLastValue(underTest.getMaxNotifications { 10 })
+            val calculateSpace = { space: Float, useExtraShelfSpace: Boolean -> 10 }
+            val maxNotifications by collectLastValue(underTest.getMaxNotifications(calculateSpace))
 
             // Show lockscreen with shade expanded
             showLockscreenWithShadeExpanded()
@@ -382,7 +414,7 @@
             val top = 123f
             val bottom = 456f
             keyguardRootViewModel.onNotificationContainerBoundsChanged(top, bottom)
-            assertThat(bounds).isEqualTo(NotificationContainerBounds(top, bottom))
+            assertThat(bounds).isEqualTo(NotificationContainerBounds(top = top, bottom = bottom))
         }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
index 051a4c1..6f65eb4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
@@ -47,7 +47,6 @@
 import com.android.keyguard.logging.BiometricUnlockLogger;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.biometrics.AuthController;
-import com.android.systemui.deviceentry.domain.interactor.DeviceEntryHapticsInteractor;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
@@ -122,8 +121,6 @@
     @Mock
     private ViewRootImpl mViewRootImpl;
     @Mock
-    private DeviceEntryHapticsInteractor mDeviceEntryHapticsInteractor;
-    @Mock
     private SelectedUserInteractor mSelectedUserInteractor;
     @Mock
     private BiometricUnlockInteractor mBiometricUnlockInteractor;
@@ -160,7 +157,6 @@
                 mAuthController, mStatusBarStateController,
                 mSessionTracker, mLatencyTracker, mScreenOffAnimationController, mVibratorHelper,
                 mSystemClock,
-                mDeviceEntryHapticsInteractor,
                 () -> mSelectedUserInteractor,
                 mBiometricUnlockInteractor
         );
@@ -466,26 +462,6 @@
     }
 
     @Test
-    public void onFingerprintSuccess_requestSuccessHaptic() {
-        // WHEN biometric fingerprint succeeds
-        givenFingerprintModeUnlockCollapsing();
-        mBiometricUnlockController.startWakeAndUnlock(BiometricSourceType.FINGERPRINT,
-                true);
-
-        // THEN always vibrate the device
-        verify(mDeviceEntryHapticsInteractor).vibrateSuccess();
-    }
-
-    @Test
-    public void onFingerprintFail_requestErrorHaptic() {
-        // WHEN biometric fingerprint fails
-        mBiometricUnlockController.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT);
-
-        // THEN always vibrate the device
-        verify(mDeviceEntryHapticsInteractor).vibrateError();
-    }
-
-    @Test
     public void onFingerprintDetect_showBouncer() {
         // WHEN fingerprint detect occurs
         mBiometricUnlockController.onBiometricDetected(UserHandle.USER_CURRENT,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
index 48b95d4..e1bd89f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.phone;
 
 import static com.android.systemui.dump.LogBufferHelperKt.logcatLogBuffer;
+import static com.android.systemui.util.concurrency.MockExecutorHandlerKt.mockExecutorHandler;
 
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
@@ -25,7 +26,6 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
-import android.os.Handler;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 
@@ -45,9 +45,11 @@
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.statusbar.policy.HeadsUpManagerLogger;
+import com.android.systemui.util.concurrency.DelayableExecutor;
 import com.android.systemui.util.kotlin.JavaAdapter;
+import com.android.systemui.util.settings.GlobalSettings;
+import com.android.systemui.util.time.SystemClock;
 
-import org.junit.After;
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Rule;
@@ -86,7 +88,9 @@
                 StatusBarStateController statusBarStateController,
                 KeyguardBypassController keyguardBypassController,
                 ConfigurationController configurationController,
-                Handler handler,
+                GlobalSettings globalSettings,
+                SystemClock systemClock,
+                DelayableExecutor executor,
                 AccessibilityManagerWrapper accessibilityManagerWrapper,
                 UiEventLogger uiEventLogger,
                 JavaAdapter javaAdapter,
@@ -100,14 +104,17 @@
                     groupManager,
                     visualStabilityProvider,
                     configurationController,
-                    handler,
+                    mockExecutorHandler(executor),
+                    globalSettings,
+                    systemClock,
+                    executor,
                     accessibilityManagerWrapper,
                     uiEventLogger,
                     javaAdapter,
                     shadeInteractor
             );
             mMinimumDisplayTime = TEST_MINIMUM_DISPLAY_TIME;
-            mAutoDismissNotificationDecay = TEST_AUTO_DISMISS_TIME;
+            mAutoDismissTime = TEST_AUTO_DISMISS_TIME;
         }
     }
 
@@ -120,7 +127,9 @@
                 mStatusBarStateController,
                 mBypassController,
                 mConfigurationController,
-                mTestHandler,
+                mGlobalSettings,
+                mSystemClock,
+                mExecutor,
                 mAccessibilityManagerWrapper,
                 mUiEventLogger,
                 mJavaAdapter,
@@ -134,7 +143,6 @@
     }
 
     @Before
-    @Override
     public void setUp() {
         when(mShadeInteractor.isAnyExpanded()).thenReturn(StateFlowKt.MutableStateFlow(false));
         final AccessibilityManagerWrapper accessibilityMgr =
@@ -145,14 +153,6 @@
         mDependency.injectMockDependency(NotificationShadeWindowController.class);
         mContext.getOrCreateTestableResources().addOverride(
                 R.integer.ambient_notification_extension_time, 500);
-
-        super.setUp();
-    }
-
-    @After
-    @Override
-    public void tearDown() {
-        super.tearDown();
     }
 
     @Test
@@ -216,8 +216,8 @@
 
         hmp.showNotification(entry);
         hmp.extendHeadsUp();
+        mSystemClock.advanceTime(TEST_AUTO_DISMISS_TIME + hmp.mExtensionTime / 2);
 
-        final int pastNormalTimeMillis = TEST_AUTO_DISMISS_TIME + hmp.mExtensionTime / 2;
-        verifyAlertingAtTime(hmp, entry, true, pastNormalTimeMillis, "normal time");
+        assertTrue(hmp.isAlerting(entry.getKey()));
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LegacyNotificationIconAreaControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LegacyNotificationIconAreaControllerImplTest.java
index c24d9ad..b3708ba 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LegacyNotificationIconAreaControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LegacyNotificationIconAreaControllerImplTest.java
@@ -20,6 +20,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.platform.test.annotations.DisableFlags;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 
@@ -49,6 +50,7 @@
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
+@DisableFlags(NotificationIconContainerRefactor.FLAG_NAME)
 public class LegacyNotificationIconAreaControllerImplTest extends SysuiTestCase {
 
     @Mock
@@ -83,7 +85,6 @@
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
-        mSetFlagsRule.disableFlags(NotificationIconContainerRefactor.FLAG_NAME);
         mController = new LegacyNotificationIconAreaControllerImpl(
                 mContext,
                 mStatusBarStateController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProviderTest.kt
index 5c56246..84b2c4b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProviderTest.kt
@@ -24,6 +24,7 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.dump.DumpManager
+import com.android.systemui.statusbar.commandline.CommandRegistry
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.util.leak.RotationUtils
 import com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE
@@ -31,6 +32,7 @@
 import com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE
 import com.android.systemui.util.leak.RotationUtils.ROTATION_UPSIDE_DOWN
 import com.android.systemui.util.leak.RotationUtils.Rotation
+import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
 import junit.framework.Assert.assertTrue
@@ -39,7 +41,6 @@
 import org.mockito.ArgumentMatchers.any
 import org.mockito.Mock
 import org.mockito.Mockito.`when`
-import org.mockito.Mockito.mock
 import org.mockito.MockitoAnnotations
 
 @SmallTest
@@ -556,7 +557,7 @@
     fun testDisplayChanged_returnsUpdatedInsets() {
         // GIVEN: get insets on the first display and switch to the second display
         val provider = StatusBarContentInsetsProvider(contextMock, configurationController,
-            mock(DumpManager::class.java))
+            mock<DumpManager>(), mock<CommandRegistry>())
 
         configuration.windowConfiguration.setMaxBounds(Rect(0, 0, 1080, 2160))
         val firstDisplayInsets = provider.getStatusBarContentAreaForRotation(ROTATION_NONE)
@@ -575,7 +576,7 @@
         // GIVEN: get insets on the first display, switch to the second display,
         // get insets and switch back
         val provider = StatusBarContentInsetsProvider(contextMock, configurationController,
-            mock(DumpManager::class.java))
+            mock<DumpManager>(), mock<CommandRegistry>())
 
         configuration.windowConfiguration.setMaxBounds(Rect(0, 0, 1080, 2160))
         val firstDisplayInsetsFirstCall = provider
@@ -601,7 +602,7 @@
         configuration.windowConfiguration.setMaxBounds(0, 0, 100, 100)
         configurationController.onConfigurationChanged(configuration)
         val provider = StatusBarContentInsetsProvider(contextMock, configurationController,
-                mock(DumpManager::class.java))
+                mock<DumpManager>(), mock<CommandRegistry>())
         val listener = object : StatusBarContentInsetsChangedListener {
             var triggered = false
 
@@ -623,7 +624,7 @@
     fun onDensityOrFontScaleChanged_listenerNotified() {
         configuration.densityDpi = 12
         val provider = StatusBarContentInsetsProvider(contextMock, configurationController,
-                mock(DumpManager::class.java))
+                mock<DumpManager>(), mock<CommandRegistry>())
         val listener = object : StatusBarContentInsetsChangedListener {
             var triggered = false
 
@@ -644,7 +645,7 @@
     @Test
     fun onThemeChanged_listenerNotified() {
         val provider = StatusBarContentInsetsProvider(contextMock, configurationController,
-                mock(DumpManager::class.java))
+                mock<DumpManager>(), mock<CommandRegistry>())
         val listener = object : StatusBarContentInsetsChangedListener {
             var triggered = false
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
index bbdc9ce..1dafcc4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
@@ -15,12 +15,13 @@
 package com.android.systemui.statusbar.phone;
 
 import static android.view.Display.DEFAULT_DISPLAY;
-
 import static com.android.systemui.statusbar.notification.interruption.VisualInterruptionType.BUBBLE;
 import static com.android.systemui.statusbar.notification.interruption.VisualInterruptionType.PEEK;
 import static com.android.systemui.statusbar.notification.interruption.VisualInterruptionType.PULSE;
-
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
@@ -30,14 +31,14 @@
 import android.app.Notification;
 import android.app.PendingIntent;
 import android.app.StatusBarManager;
-import android.platform.test.flag.junit.SetFlagsRule;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 
 import androidx.test.filters.SmallTest;
 
-import com.android.systemui.Flags;
 import com.android.systemui.InitController;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.ActivityStarter;
@@ -64,6 +65,7 @@
 import com.android.systemui.statusbar.notification.interruption.VisualInterruptionCondition;
 import com.android.systemui.statusbar.notification.interruption.VisualInterruptionDecisionProvider;
 import com.android.systemui.statusbar.notification.interruption.VisualInterruptionFilter;
+import com.android.systemui.statusbar.notification.interruption.VisualInterruptionRefactor;
 import com.android.systemui.statusbar.notification.interruption.VisualInterruptionType;
 import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
@@ -73,7 +75,6 @@
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 
 import org.junit.Before;
-import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
@@ -100,10 +101,6 @@
     private final KeyguardStateController mKeyguardStateController =
             mock(KeyguardStateController.class);
 
-    @Rule
-    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(
-            SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT);
-
     @Before
     public void setup() {
         mCommandQueue = new CommandQueue(mContext, new FakeDisplayTracker(mContext));
@@ -114,29 +111,46 @@
         mDependency.injectMockDependency(NotificationShadeWindowController.class);
 
         when(mNotificationAlertsInteractor.areNotificationAlertsEnabled()).thenReturn(true);
+
+        createPresenter();
+        if (VisualInterruptionRefactor.isEnabled()) {
+            verifyAndCaptureSuppressors();
+        } else {
+            verifyAndCaptureLegacySuppressor();
+        }
     }
 
     @Test
+    @DisableFlags(VisualInterruptionRefactor.FLAG_NAME)
     public void testInit_refactorDisabled() {
-        ensureRefactorDisabledState();
+        assertFalse(VisualInterruptionRefactor.isEnabled());
+        assertNull(mAlertsDisabledCondition);
+        assertNull(mVrModeCondition);
+        assertNull(mNeedsRedactionFilter);
+        assertNull(mPanelsDisabledCondition);
+        assertNotNull(mInterruptSuppressor);
     }
 
     @Test
+    @EnableFlags(VisualInterruptionRefactor.FLAG_NAME)
     public void testInit_refactorEnabled() {
-        ensureRefactorEnabledState();
+        assertTrue(VisualInterruptionRefactor.isEnabled());
+        assertNotNull(mAlertsDisabledCondition);
+        assertNotNull(mVrModeCondition);
+        assertNotNull(mNeedsRedactionFilter);
+        assertNotNull(mPanelsDisabledCondition);
+        assertNull(mInterruptSuppressor);
     }
 
     @Test
+    @DisableFlags(VisualInterruptionRefactor.FLAG_NAME)
     public void testNoSuppressHeadsUp_default_refactorDisabled() {
-        ensureRefactorDisabledState();
-
         assertFalse(mInterruptSuppressor.suppressAwakeHeadsUp(createNotificationEntry()));
     }
 
     @Test
+    @EnableFlags(VisualInterruptionRefactor.FLAG_NAME)
     public void testNoSuppressHeadsUp_default_refactorEnabled() {
-        ensureRefactorEnabledState();
-
         assertFalse(mAlertsDisabledCondition.shouldSuppress());
         assertFalse(mVrModeCondition.shouldSuppress());
         assertFalse(mNeedsRedactionFilter.shouldSuppress(createNotificationEntry()));
@@ -144,9 +158,8 @@
     }
 
     @Test
+    @DisableFlags(VisualInterruptionRefactor.FLAG_NAME)
     public void testSuppressHeadsUp_disabledStatusBar_refactorDisabled() {
-        ensureRefactorDisabledState();
-
         mCommandQueue.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_EXPAND, 0,
                 false /* animate */);
         TestableLooper.get(this).processAllMessages();
@@ -156,9 +169,8 @@
     }
 
     @Test
+    @EnableFlags(VisualInterruptionRefactor.FLAG_NAME)
     public void testSuppressHeadsUp_disabledStatusBar_refactorEnabled() {
-        ensureRefactorEnabledState();
-
         mCommandQueue.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_EXPAND, 0,
                 false /* animate */);
         TestableLooper.get(this).processAllMessages();
@@ -168,9 +180,8 @@
     }
 
     @Test
+    @DisableFlags(VisualInterruptionRefactor.FLAG_NAME)
     public void testSuppressHeadsUp_disabledNotificationShade_refactorDisabled() {
-        ensureRefactorDisabledState();
-
         mCommandQueue.disable(DEFAULT_DISPLAY, 0, StatusBarManager.DISABLE2_NOTIFICATION_SHADE,
                 false /* animate */);
         TestableLooper.get(this).processAllMessages();
@@ -180,9 +191,8 @@
     }
 
     @Test
+    @EnableFlags(VisualInterruptionRefactor.FLAG_NAME)
     public void testSuppressHeadsUp_disabledNotificationShade_refactorEnabled() {
-        ensureRefactorEnabledState();
-
         mCommandQueue.disable(DEFAULT_DISPLAY, 0, StatusBarManager.DISABLE2_NOTIFICATION_SHADE,
                 false /* animate */);
         TestableLooper.get(this).processAllMessages();
@@ -192,9 +202,8 @@
     }
 
     @Test
+    @EnableFlags(VisualInterruptionRefactor.FLAG_NAME)
     public void testPanelsDisabledConditionSuppressesPeek() {
-        ensureRefactorEnabledState();
-
         final Set<VisualInterruptionType> types = mPanelsDisabledCondition.getTypes();
         assertTrue(types.contains(PEEK));
         assertFalse(types.contains(PULSE));
@@ -202,9 +211,8 @@
     }
 
     @Test
+    @DisableFlags(VisualInterruptionRefactor.FLAG_NAME)
     public void testNoSuppressHeadsUp_FSI_nonOccludedKeyguard_refactorDisabled() {
-        ensureRefactorDisabledState();
-
         when(mKeyguardStateController.isShowing()).thenReturn(true);
         when(mKeyguardStateController.isOccluded()).thenReturn(false);
 
@@ -212,9 +220,8 @@
     }
 
     @Test
+    @EnableFlags(VisualInterruptionRefactor.FLAG_NAME)
     public void testNoSuppressHeadsUp_FSI_nonOccludedKeyguard_refactorEnabled() {
-        ensureRefactorEnabledState();
-
         when(mKeyguardStateController.isShowing()).thenReturn(true);
         when(mKeyguardStateController.isOccluded()).thenReturn(false);
 
@@ -227,9 +234,8 @@
     }
 
     @Test
+    @DisableFlags(VisualInterruptionRefactor.FLAG_NAME)
     public void testSuppressInterruptions_vrMode_refactorDisabled() {
-        ensureRefactorDisabledState();
-
         mStatusBarNotificationPresenter.mVrMode = true;
 
         assertTrue("Vr mode should suppress interruptions",
@@ -237,9 +243,8 @@
     }
 
     @Test
+    @EnableFlags(VisualInterruptionRefactor.FLAG_NAME)
     public void testSuppressInterruptions_vrMode_refactorEnabled() {
-        ensureRefactorEnabledState();
-
         mStatusBarNotificationPresenter.mVrMode = true;
 
         assertTrue("Vr mode should suppress interruptions", mVrModeCondition.shouldSuppress());
@@ -251,9 +256,8 @@
     }
 
     @Test
+    @DisableFlags(VisualInterruptionRefactor.FLAG_NAME)
     public void testSuppressInterruptions_statusBarAlertsDisabled_refactorDisabled() {
-        ensureRefactorDisabledState();
-
         when(mNotificationAlertsInteractor.areNotificationAlertsEnabled()).thenReturn(false);
 
         assertTrue("When alerts aren't enabled, interruptions are suppressed",
@@ -261,9 +265,8 @@
     }
 
     @Test
+    @EnableFlags(VisualInterruptionRefactor.FLAG_NAME)
     public void testSuppressInterruptions_statusBarAlertsDisabled_refactorEnabled() {
-        ensureRefactorEnabledState();
-
         when(mNotificationAlertsInteractor.areNotificationAlertsEnabled()).thenReturn(false);
 
         assertTrue("When alerts aren't enabled, interruptions are suppressed",
@@ -349,18 +352,6 @@
         mInterruptSuppressor = suppressorCaptor.getValue();
     }
 
-    private void ensureRefactorDisabledState() {
-        mSetFlagsRule.disableFlags(Flags.FLAG_VISUAL_INTERRUPTIONS_REFACTOR);
-        createPresenter();
-        verifyAndCaptureLegacySuppressor();
-    }
-
-    private void ensureRefactorEnabledState() {
-        mSetFlagsRule.enableFlags(Flags.FLAG_VISUAL_INTERRUPTIONS_REFACTOR);
-        createPresenter();
-        verifyAndCaptureSuppressors();
-    }
-
     private NotificationEntry createNotificationEntry() {
         return new NotificationEntryBuilder()
                 .setPkg("a")
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 17c2938..1cc611c 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
@@ -69,8 +69,8 @@
 import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
 import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.FakeCollapsedStatusBarViewBinder;
 import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.FakeCollapsedStatusBarViewModel;
-import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.ui.SystemBarUtilsState;
 import com.android.systemui.statusbar.window.StatusBarWindowStateController;
 import com.android.systemui.statusbar.window.StatusBarWindowStateListener;
 import com.android.systemui.util.CarrierConfigTracker;
@@ -717,7 +717,7 @@
                 mKeyguardUpdateMonitor,
                 mock(NotificationIconContainerStatusBarViewModel.class),
                 mock(ConfigurationState.class),
-                mock(ConfigurationController.class),
+                mock(SystemBarUtilsState.class),
                 mock(StatusBarNotificationIconViewStore.class),
                 mock(DemoModeController.class));
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt
index 09dc1e5..89842d6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt
@@ -16,9 +16,10 @@
 
 package com.android.systemui.statusbar.pipeline.shared.ui.viewmodel
 
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
 import androidx.test.filters.SmallTest
 import com.android.systemui.CoroutineTestScopeModule
-import com.android.systemui.Flags
 import com.android.systemui.SysUITestComponent
 import com.android.systemui.SysUITestModule
 import com.android.systemui.SysuiTestCase
@@ -29,6 +30,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.log.assertLogsWtf
 import com.android.systemui.runTest
 import com.android.systemui.statusbar.data.model.StatusBarMode
 import com.android.systemui.statusbar.data.repository.FakeStatusBarModeRepository
@@ -37,14 +39,15 @@
 import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository
 import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationsStore
 import com.android.systemui.statusbar.notification.shared.ActiveNotificationModel
+import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor
 import com.google.common.truth.Truth.assertThat
 import dagger.BindsInstance
 import dagger.Component
 import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.emptyFlow
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.UnconfinedTestDispatcher
-import org.junit.Before
 import org.junit.Test
 
 @SmallTest
@@ -79,11 +82,6 @@
                 testScope = CoroutineTestScopeModule(TestScope(UnconfinedTestDispatcher())),
             )
 
-    @Before
-    fun setUp() {
-        mSetFlagsRule.enableFlags(Flags.FLAG_NOTIFICATIONS_LIVE_DATA_STORE_REFACTOR)
-    }
-
     @Test
     fun isTransitioningFromLockscreenToOccluded_started_isTrue() =
         testComponent.runTest {
@@ -347,6 +345,7 @@
         }
 
     @Test
+    @EnableFlags(NotificationsLiveDataStoreRefactor.FLAG_NAME)
     fun areNotificationsLightsOut_lowProfileWithNotifications_true() =
         testComponent.runTest {
             statusBarModeRepository.defaultDisplay.statusBarMode.value =
@@ -360,6 +359,7 @@
         }
 
     @Test
+    @EnableFlags(NotificationsLiveDataStoreRefactor.FLAG_NAME)
     fun areNotificationsLightsOut_lowProfileWithoutNotifications_false() =
         testComponent.runTest {
             statusBarModeRepository.defaultDisplay.statusBarMode.value =
@@ -373,6 +373,7 @@
         }
 
     @Test
+    @EnableFlags(NotificationsLiveDataStoreRefactor.FLAG_NAME)
     fun areNotificationsLightsOut_defaultStatusBarModeWithoutNotifications_false() =
         testComponent.runTest {
             statusBarModeRepository.defaultDisplay.statusBarMode.value = StatusBarMode.TRANSPARENT
@@ -385,6 +386,7 @@
         }
 
     @Test
+    @EnableFlags(NotificationsLiveDataStoreRefactor.FLAG_NAME)
     fun areNotificationsLightsOut_defaultStatusBarModeWithNotifications_false() =
         testComponent.runTest {
             statusBarModeRepository.defaultDisplay.statusBarMode.value = StatusBarMode.TRANSPARENT
@@ -396,6 +398,16 @@
             assertThat(actual).isFalse()
         }
 
+    @Test
+    @DisableFlags(NotificationsLiveDataStoreRefactor.FLAG_NAME)
+    fun areNotificationsLightsOut_requiresFlagEnabled() =
+        testComponent.runTest {
+            assertLogsWtf {
+                val flow = underTest.areNotificationsLightsOut(DISPLAY_ID)
+                assertThat(flow).isEqualTo(emptyFlow<Boolean>())
+            }
+        }
+
     private fun activeNotificationsStore(notifications: List<ActiveNotificationModel>) =
         ActiveNotificationsStore.Builder()
             .apply { notifications.forEach(::addIndividualNotif) }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModelTest.kt
index 22dce3a..1bdf644 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModelTest.kt
@@ -21,6 +21,7 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.common.shared.model.ContentDescription.Companion.loadContentDescription
 import com.android.systemui.common.shared.model.Text
+import com.android.systemui.common.shared.model.Text.Companion.loadText
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.flags.FakeFeatureFlagsClassic
 import com.android.systemui.flags.Flags
@@ -355,14 +356,14 @@
 
             connectivityRepository.setEthernetConnected(default = true, validated = true)
 
-            assertThat(latest?.secondaryLabel).isNull()
-            assertThat(latest?.secondaryTitle)
-                .isEqualTo(ethernetIcon!!.contentDescription.toString())
+            assertThat(latest?.secondaryLabel.loadText(context))
+                .isEqualTo(ethernetIcon!!.contentDescription.loadContentDescription(context))
+            assertThat(latest?.secondaryTitle).isNull()
             assertThat(latest?.iconId).isEqualTo(R.drawable.stat_sys_ethernet_fully)
             assertThat(latest?.icon).isNull()
             assertThat(latest?.stateDescription).isNull()
             assertThat(latest?.contentDescription.loadContentDescription(context))
-                .isEqualTo(latest?.secondaryTitle)
+                .isEqualTo(latest?.secondaryLabel.loadText(context))
         }
 
     @Test
@@ -373,14 +374,14 @@
 
             connectivityRepository.setEthernetConnected(default = true, validated = false)
 
-            assertThat(latest?.secondaryLabel).isNull()
-            assertThat(latest?.secondaryTitle)
-                .isEqualTo(ethernetIcon!!.contentDescription.toString())
+            assertThat(latest?.secondaryLabel.loadText(context))
+                .isEqualTo(ethernetIcon!!.contentDescription.loadContentDescription(context))
+            assertThat(latest?.secondaryTitle).isNull()
             assertThat(latest?.iconId).isEqualTo(R.drawable.stat_sys_ethernet)
             assertThat(latest?.icon).isNull()
             assertThat(latest?.stateDescription).isNull()
             assertThat(latest?.contentDescription.loadContentDescription(context))
-                .isEqualTo(latest?.secondaryTitle)
+                .isEqualTo(latest?.secondaryLabel.loadText(context))
         }
 
     private fun setWifiNetworkWithHotspot(hotspot: WifiNetworkModel.HotspotDeviceType) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BaseHeadsUpManagerTest.java
similarity index 79%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BaseHeadsUpManagerTest.java
index 4f3f564..4c893e3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BaseHeadsUpManagerTest.java
@@ -19,6 +19,7 @@
 import static android.app.Notification.FLAG_FSI_REQUESTED_BUT_DENIED;
 
 import static com.android.systemui.dump.LogBufferHelperKt.logcatLogBuffer;
+import static com.android.systemui.util.concurrency.MockExecutorHandlerKt.mockExecutorHandler;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -34,7 +35,6 @@
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
-import static org.mockito.MockitoAnnotations.initMocks;
 
 import android.app.Notification;
 import android.app.PendingIntent;
@@ -42,7 +42,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Region;
-import android.os.Handler;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 
@@ -57,36 +56,51 @@
 import com.android.systemui.statusbar.AlertingNotificationManagerTest;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
+import com.android.systemui.util.concurrency.DelayableExecutor;
+import com.android.systemui.util.settings.GlobalSettings;
+import com.android.systemui.util.time.SystemClock;
 
-import org.junit.After;
-import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
-public class HeadsUpManagerTest extends AlertingNotificationManagerTest {
+public class BaseHeadsUpManagerTest extends AlertingNotificationManagerTest {
+    @Rule
+    public MockitoRule rule = MockitoJUnit.rule();
+
     private static final int TEST_TOUCH_ACCEPTANCE_TIME = 200;
     private static final int TEST_A11Y_AUTO_DISMISS_TIME = 1_000;
-    private static final int TEST_A11Y_TIMEOUT_TIME = 3_000;
 
     private UiEventLoggerFake mUiEventLoggerFake = new UiEventLoggerFake();
     private final HeadsUpManagerLogger mLogger = spy(new HeadsUpManagerLogger(logcatLogBuffer()));
     @Mock private AccessibilityManagerWrapper mAccessibilityMgr;
 
+    static {
+        assertThat(TEST_MINIMUM_DISPLAY_TIME).isLessThan(TEST_AUTO_DISMISS_TIME);
+        assertThat(TEST_AUTO_DISMISS_TIME).isLessThan(TEST_STICKY_AUTO_DISMISS_TIME);
+        assertThat(TEST_STICKY_AUTO_DISMISS_TIME).isLessThan(TEST_A11Y_AUTO_DISMISS_TIME);
+    }
+
     private final class TestableHeadsUpManager extends BaseHeadsUpManager {
         TestableHeadsUpManager(Context context,
                 HeadsUpManagerLogger logger,
-                Handler handler,
+                DelayableExecutor executor,
+                GlobalSettings globalSettings,
+                SystemClock systemClock,
                 AccessibilityManagerWrapper accessibilityManagerWrapper,
                 UiEventLogger uiEventLogger) {
-            super(context, logger, handler, accessibilityManagerWrapper, uiEventLogger);
+            super(context, logger, mockExecutorHandler(executor), globalSettings, systemClock,
+                    executor, accessibilityManagerWrapper, uiEventLogger);
             mTouchAcceptanceDelay = TEST_TOUCH_ACCEPTANCE_TIME;
             mMinimumDisplayTime = TEST_MINIMUM_DISPLAY_TIME;
-            mAutoDismissNotificationDecay = TEST_AUTO_DISMISS_TIME;
-            mStickyDisplayTime = TEST_STICKY_AUTO_DISMISS_TIME;
+            mAutoDismissTime = TEST_AUTO_DISMISS_TIME;
+            mStickyForSomeTimeAutoDismissTime = TEST_STICKY_AUTO_DISMISS_TIME;
         }
 
         // The following are only implemented by HeadsUpManagerPhone. If you need them, use that.
@@ -160,8 +174,8 @@
     }
 
     private BaseHeadsUpManager createHeadsUpManager() {
-        return new TestableHeadsUpManager(mContext, mLogger, mTestHandler, mAccessibilityMgr,
-                mUiEventLoggerFake);
+        return new TestableHeadsUpManager(mContext, mLogger, mExecutor, mGlobalSettings,
+                mSystemClock, mAccessibilityMgr, mUiEventLoggerFake);
     }
 
     @Override
@@ -211,30 +225,6 @@
     }
 
 
-    @Before
-    @Override
-    public void setUp() {
-        initMocks(this);
-        super.setUp();
-
-        assertThat(TEST_MINIMUM_DISPLAY_TIME).isLessThan(TEST_AUTO_DISMISS_TIME);
-        assertThat(TEST_AUTO_DISMISS_TIME).isLessThan(TEST_STICKY_AUTO_DISMISS_TIME);
-        assertThat(TEST_STICKY_AUTO_DISMISS_TIME).isLessThan(TEST_A11Y_AUTO_DISMISS_TIME);
-
-        assertThat(TEST_TOUCH_ACCEPTANCE_TIME + TEST_AUTO_DISMISS_TIME).isLessThan(
-                TEST_TIMEOUT_TIME);
-        assertThat(TEST_TOUCH_ACCEPTANCE_TIME + TEST_STICKY_AUTO_DISMISS_TIME).isLessThan(
-                TEST_TIMEOUT_TIME);
-        assertThat(TEST_TOUCH_ACCEPTANCE_TIME + TEST_A11Y_AUTO_DISMISS_TIME).isLessThan(
-                TEST_A11Y_TIMEOUT_TIME);
-    }
-
-    @After
-    @Override
-    public void tearDown() {
-        super.tearDown();
-    }
-
     @Test
     public void testHunRemovedLogging() {
         final BaseHeadsUpManager hum = createHeadsUpManager();
@@ -294,10 +284,9 @@
         useAccessibilityTimeout(false);
 
         hum.showNotification(entry);
+        mSystemClock.advanceTime(TEST_TOUCH_ACCEPTANCE_TIME / 2 + TEST_AUTO_DISMISS_TIME);
 
-        final int pastJustAutoDismissMillis =
-                TEST_TOUCH_ACCEPTANCE_TIME / 2 + TEST_AUTO_DISMISS_TIME;
-        verifyAlertingAtTime(hum, entry, true, pastJustAutoDismissMillis, "just auto dismiss");
+        assertTrue(hum.isAlerting(entry.getKey()));
     }
 
 
@@ -308,10 +297,10 @@
         useAccessibilityTimeout(false);
 
         hum.showNotification(entry);
+        mSystemClock.advanceTime(TEST_TOUCH_ACCEPTANCE_TIME
+                + (TEST_AUTO_DISMISS_TIME + TEST_A11Y_AUTO_DISMISS_TIME) / 2);
 
-        final int pastDefaultTimeoutMillis = TEST_TOUCH_ACCEPTANCE_TIME
-                + (TEST_AUTO_DISMISS_TIME + TEST_A11Y_AUTO_DISMISS_TIME) / 2;
-        verifyAlertingAtTime(hum, entry, false, pastDefaultTimeoutMillis, "default timeout");
+        assertFalse(hum.isAlerting(entry.getKey()));
     }
 
 
@@ -322,10 +311,10 @@
         useAccessibilityTimeout(false);
 
         hum.showNotification(entry);
+        mSystemClock.advanceTime(TEST_TOUCH_ACCEPTANCE_TIME
+                + (TEST_AUTO_DISMISS_TIME + TEST_STICKY_AUTO_DISMISS_TIME) / 2);
 
-        final int pastDefaultTimeoutMillis = TEST_TOUCH_ACCEPTANCE_TIME
-                + (TEST_AUTO_DISMISS_TIME + TEST_STICKY_AUTO_DISMISS_TIME) / 2;
-        verifyAlertingAtTime(hum, entry, true, pastDefaultTimeoutMillis, "default timeout");
+        assertTrue(hum.isAlerting(entry.getKey()));
     }
 
 
@@ -336,18 +325,9 @@
         useAccessibilityTimeout(false);
 
         hum.showNotification(entry);
+        mSystemClock.advanceTime(TEST_TOUCH_ACCEPTANCE_TIME + 2 * TEST_A11Y_AUTO_DISMISS_TIME);
 
-        final int pastLongestAutoDismissMillis =
-                TEST_TOUCH_ACCEPTANCE_TIME + 2 * TEST_A11Y_AUTO_DISMISS_TIME;
-        final Boolean[] wasAlerting = {null};
-        final Runnable checkAlerting =
-                () -> wasAlerting[0] = hum.isAlerting(entry.getKey());
-        mTestHandler.postDelayed(checkAlerting, pastLongestAutoDismissMillis);
-        TestableLooper.get(this).processMessages(1);
-
-        assertTrue("Should still be alerting past longest auto-dismiss", wasAlerting[0]);
-        assertTrue("Should still be alerting after processing",
-                hum.isAlerting(entry.getKey()));
+        assertTrue(hum.isAlerting(entry.getKey()));
     }
 
 
@@ -358,10 +338,10 @@
         useAccessibilityTimeout(true);
 
         hum.showNotification(entry);
+        mSystemClock.advanceTime(TEST_TOUCH_ACCEPTANCE_TIME
+                + (TEST_AUTO_DISMISS_TIME + TEST_A11Y_AUTO_DISMISS_TIME) / 2);
 
-        final int pastDefaultTimeoutMillis = TEST_TOUCH_ACCEPTANCE_TIME
-                + (TEST_AUTO_DISMISS_TIME + TEST_A11Y_AUTO_DISMISS_TIME) / 2;
-        verifyAlertingAtTime(hum, entry, true, pastDefaultTimeoutMillis, "default timeout");
+        assertTrue(hum.isAlerting(entry.getKey()));
     }
 
 
@@ -372,10 +352,10 @@
         useAccessibilityTimeout(true);
 
         hum.showNotification(entry);
+        mSystemClock.advanceTime(TEST_TOUCH_ACCEPTANCE_TIME
+                + (TEST_STICKY_AUTO_DISMISS_TIME + TEST_A11Y_AUTO_DISMISS_TIME) / 2);
 
-        final int pastStickyTimeoutMillis = TEST_TOUCH_ACCEPTANCE_TIME
-                + (TEST_STICKY_AUTO_DISMISS_TIME + TEST_A11Y_AUTO_DISMISS_TIME) / 2;
-        verifyAlertingAtTime(hum, entry, true, pastStickyTimeoutMillis, "sticky timeout");
+        assertTrue(hum.isAlerting(entry.getKey()));
     }
 
 
@@ -387,18 +367,14 @@
 
         hum.showNotification(entry);
 
-        // Try to remove but defer, since the notification has not been shown long enough.
         final boolean removedImmediately = hum.removeNotification(
-                entry.getKey(), false /* releaseImmediately */);
+                entry.getKey(), /* releaseImmediately = */ false);
+        assertFalse(removedImmediately);
+        assertTrue(hum.isAlerting(entry.getKey()));
 
-        assertFalse("HUN should not be removed before minimum display time", removedImmediately);
-        assertTrue("HUN should still be alerting before minimum display time",
-                hum.isAlerting(entry.getKey()));
+        mSystemClock.advanceTime((TEST_MINIMUM_DISPLAY_TIME + TEST_AUTO_DISMISS_TIME) / 2);
 
-        final int pastMinimumDisplayTimeMillis =
-                (TEST_MINIMUM_DISPLAY_TIME + TEST_AUTO_DISMISS_TIME) / 2;
-        verifyAlertingAtTime(hum, entry, false, pastMinimumDisplayTimeMillis,
-                "minimum display time");
+        assertFalse(hum.isAlerting(entry.getKey()));
     }
 
 
@@ -409,32 +385,13 @@
         useAccessibilityTimeout(false);
 
         hum.showNotification(entry);
+        mSystemClock.advanceTime((TEST_MINIMUM_DISPLAY_TIME + TEST_AUTO_DISMISS_TIME) / 2);
 
-        // After the minimum display time:
-        // 1. Check whether the notification is still alerting.
-        // 2. Try to remove it and check whether the remove succeeded.
-        // 3. Check whether it is still alerting after trying to remove it.
-        final Boolean[] livedPastMinimumDisplayTime = {null};
-        final Boolean[] removedAfterMinimumDisplayTime = {null};
-        final Boolean[] livedPastRemoveAfterMinimumDisplayTime = {null};
-        final Runnable pastMinimumDisplayTimeRunnable = () -> {
-            livedPastMinimumDisplayTime[0] = hum.isAlerting(entry.getKey());
-            removedAfterMinimumDisplayTime[0] = hum.removeNotification(
-                    entry.getKey(), /* releaseImmediately = */ false);
-            livedPastRemoveAfterMinimumDisplayTime[0] = hum.isAlerting(entry.getKey());
-        };
-        final int pastMinimumDisplayTimeMillis =
-                (TEST_MINIMUM_DISPLAY_TIME + TEST_AUTO_DISMISS_TIME) / 2;
-        mTestHandler.postDelayed(pastMinimumDisplayTimeRunnable, pastMinimumDisplayTimeMillis);
-        // Wait until the minimum display time has passed before attempting removal.
-        TestableLooper.get(this).processMessages(1);
+        assertTrue(hum.isAlerting(entry.getKey()));
 
-        assertTrue("HUN should live past minimum display time",
-                livedPastMinimumDisplayTime[0]);
-        assertTrue("HUN should be removed immediately past minimum display time",
-                removedAfterMinimumDisplayTime[0]);
-        assertFalse("HUN should not live after being removed past minimum display time",
-                livedPastRemoveAfterMinimumDisplayTime[0]);
+        final boolean removedImmediately = hum.removeNotification(
+                entry.getKey(), /* releaseImmediately = */ false);
+        assertTrue(removedImmediately);
         assertFalse(hum.isAlerting(entry.getKey()));
     }
 
@@ -446,10 +403,8 @@
 
         hum.showNotification(entry);
 
-        // Remove forcibly with releaseImmediately = true.
         final boolean removedImmediately = hum.removeNotification(
                 entry.getKey(), /* releaseImmediately = */ true);
-
         assertTrue(removedImmediately);
         assertFalse(hum.isAlerting(entry.getKey()));
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java
index 01dad38..479309c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java
@@ -153,6 +153,36 @@
     }
 
     @Test
+    public void testCanSkipLockScreen_updateCalledOnFacesCleared() {
+        verify(mKeyguardUpdateMonitor).registerCallback(mUpdateCallbackCaptor.capture());
+
+        // Cannot skip after there's a password/pin/pattern
+        when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true);
+        ((KeyguardStateControllerImpl) mKeyguardStateController).update(false /* alwaysUpdate */);
+        assertThat(mKeyguardStateController.canDismissLockScreen()).isFalse();
+
+        // Unless user is authenticated
+        when(mKeyguardUpdateMonitor.getUserCanSkipBouncer(anyInt())).thenReturn(true);
+        mUpdateCallbackCaptor.getValue().onFacesCleared();
+        assertThat(mKeyguardStateController.canDismissLockScreen()).isTrue();
+    }
+
+    @Test
+    public void testCanSkipLockScreen_updateCalledOnFingerprintssCleared() {
+        verify(mKeyguardUpdateMonitor).registerCallback(mUpdateCallbackCaptor.capture());
+
+        // Cannot skip after there's a password/pin/pattern
+        when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true);
+        ((KeyguardStateControllerImpl) mKeyguardStateController).update(false /* alwaysUpdate */);
+        assertThat(mKeyguardStateController.canDismissLockScreen()).isFalse();
+
+        // Unless user is authenticated
+        when(mKeyguardUpdateMonitor.getUserCanSkipBouncer(anyInt())).thenReturn(true);
+        mUpdateCallbackCaptor.getValue().onFingerprintsCleared();
+        assertThat(mKeyguardStateController.canDismissLockScreen()).isTrue();
+    }
+
+    @Test
     public void testIsUnlocked() {
         // Is unlocked whenever the keyguard is not showing
         assertThat(mKeyguardStateController.isShowing()).isFalse();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
index 1123688..b58a41c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.theme;
 
+import static android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE;
 import static android.util.TypedValue.TYPE_INT_COLOR_ARGB8;
 
 import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE;
@@ -90,6 +91,9 @@
 
     private static final int USER_SYSTEM = UserHandle.USER_SYSTEM;
     private static final int USER_SECONDARY = 10;
+    private static final UserHandle MANAGED_USER_HANDLE = UserHandle.of(100);
+    private static final UserHandle PRIVATE_USER_HANDLE = UserHandle.of(101);
+
     @Mock
     private JavaAdapter mJavaAdapter;
     @Mock
@@ -174,6 +178,14 @@
                                 Integer.toHexString(mColorScheme.getSeed() | 0xff000000)));
                 return overlay;
             }
+
+            @VisibleForTesting
+            protected boolean isPrivateProfile(UserHandle userHandle) {
+                if (userHandle.getIdentifier() == PRIVATE_USER_HANDLE.getIdentifier()) {
+                    return true;
+                }
+                return false;
+            }
         };
 
         mWakefulnessLifecycle.dispatchFinishedWakingUp();
@@ -675,7 +687,8 @@
     @Test
     public void onProfileAdded_setsTheme() {
         mBroadcastReceiver.getValue().onReceive(null,
-                new Intent(Intent.ACTION_MANAGED_PROFILE_ADDED));
+                new Intent(Intent.ACTION_PROFILE_ADDED)
+                        .putExtra(Intent.EXTRA_USER, MANAGED_USER_HANDLE));
         verify(mThemeOverlayApplier).applyCurrentUserOverlays(any(), any(), anyInt(), any());
     }
 
@@ -684,7 +697,8 @@
         reset(mDeviceProvisionedController);
         when(mUserManager.isManagedProfile(anyInt())).thenReturn(false);
         mBroadcastReceiver.getValue().onReceive(null,
-                new Intent(Intent.ACTION_MANAGED_PROFILE_ADDED));
+                new Intent(Intent.ACTION_PROFILE_ADDED)
+                        .putExtra(Intent.EXTRA_USER, MANAGED_USER_HANDLE));
         verify(mThemeOverlayApplier)
                 .applyCurrentUserOverlays(any(), any(), anyInt(), any());
     }
@@ -694,12 +708,26 @@
         reset(mDeviceProvisionedController);
         when(mUserManager.isManagedProfile(anyInt())).thenReturn(true);
         mBroadcastReceiver.getValue().onReceive(null,
-                new Intent(Intent.ACTION_MANAGED_PROFILE_ADDED));
+                new Intent(Intent.ACTION_PROFILE_ADDED)
+                        .putExtra(Intent.EXTRA_USER, MANAGED_USER_HANDLE));
         verify(mThemeOverlayApplier, never())
                 .applyCurrentUserOverlays(any(), any(), anyInt(), any());
     }
 
     @Test
+    public void onPrivateProfileAdded_ignoresUntilStartComplete() {
+        mSetFlagsRule.enableFlags(FLAG_ALLOW_PRIVATE_PROFILE);
+        reset(mDeviceProvisionedController);
+        when(mUserManager.isManagedProfile(anyInt())).thenReturn(false);
+        mBroadcastReceiver.getValue().onReceive(null,
+                (new Intent(Intent.ACTION_PROFILE_ADDED))
+                        .putExtra(Intent.EXTRA_USER, PRIVATE_USER_HANDLE));
+        verify(mThemeOverlayApplier, never())
+                .applyCurrentUserOverlays(any(), any(), anyInt(), any());
+    }
+
+
+    @Test
     public void onWallpaperColorsChanged_firstEventBeforeUserSetup_shouldBeAccepted() {
         // By default, on setup() we make this controller return that the user finished setup
         // wizard. This test on the other hand, is testing the setup flow.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/SelectedUserInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/SelectedUserInteractorTest.kt
index 60fe7d2..140e919 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/SelectedUserInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/SelectedUserInteractorTest.kt
@@ -2,9 +2,8 @@
 
 import android.content.pm.UserInfo
 import androidx.test.filters.SmallTest
+import com.android.systemui.Flags.FLAG_REFACTOR_GET_CURRENT_USER
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.flags.FakeFeatureFlagsClassic
-import com.android.systemui.flags.Flags
 import com.android.systemui.user.data.repository.FakeUserRepository
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.runBlocking
@@ -24,15 +23,12 @@
     @Before
     fun setUp() {
         userRepository.setUserInfos(USER_INFOS)
-        underTest =
-            SelectedUserInteractor(
-                userRepository,
-                FakeFeatureFlagsClassic().apply { set(Flags.REFACTOR_GETCURRENTUSER, true) }
-            )
+        underTest = SelectedUserInteractor(userRepository)
     }
 
     @Test
     fun getSelectedUserIdReturnsId() {
+        mSetFlagsRule.enableFlags(FLAG_REFACTOR_GET_CURRENT_USER)
         runBlocking { userRepository.setSelectedUserInfo(USER_INFOS[0]) }
 
         val actualId = underTest.getSelectedUserId()
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 8585d46..b217195 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -29,6 +29,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -97,6 +99,7 @@
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository;
 import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor;
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FakeFeatureFlags;
 import com.android.systemui.flags.FakeFeatureFlagsClassic;
@@ -119,6 +122,7 @@
 import com.android.systemui.scene.data.repository.SceneContainerRepository;
 import com.android.systemui.scene.domain.interactor.SceneInteractor;
 import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags;
+import com.android.systemui.scene.shared.flag.SceneContainerFlags;
 import com.android.systemui.scene.shared.logger.SceneLogger;
 import com.android.systemui.settings.FakeDisplayTracker;
 import com.android.systemui.settings.UserTracker;
@@ -343,6 +347,8 @@
     private Icon mAppBubbleIcon;
     @Mock
     private Display mDefaultDisplay;
+    @Mock
+    private SceneContainerFlags mSceneContainerFlags;
 
     private final SceneTestUtils mUtils = new SceneTestUtils(this);
     private final TestScope mTestScope = mUtils.getTestScope();
@@ -462,6 +468,10 @@
         ResourcesSplitShadeStateController splitShadeStateController =
                 new ResourcesSplitShadeStateController();
 
+        DeviceEntryUdfpsInteractor deviceEntryUdfpsInteractor =
+                mock(DeviceEntryUdfpsInteractor.class);
+        when(deviceEntryUdfpsInteractor.isUdfpsSupported()).thenReturn(emptyFlow());
+
         mShadeInteractor =
                 new ShadeInteractorImpl(
                         mTestScope.getBackgroundScope(),
@@ -478,7 +488,9 @@
                                 new SharedNotificationContainerInteractor(
                                         configurationRepository,
                                         mContext,
-                                        splitShadeStateController),
+                                        splitShadeStateController,
+                                        keyguardInteractor,
+                                        deviceEntryUdfpsInteractor),
                                 shadeRepository
                         )
                 );
@@ -503,7 +515,8 @@
                 () -> mShadeInteractor,
                 mShadeWindowLogger,
                 () -> mSelectedUserInteractor,
-                mUserTracker
+                mUserTracker,
+                mSceneContainerFlags
         );
         mNotificationShadeWindowController.fetchWindowRootView();
         mNotificationShadeWindowController.attach();
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/android/content/pm/LauncherAppsKosmos.kt
similarity index 69%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
copy to packages/SystemUI/tests/utils/src/android/content/pm/LauncherAppsKosmos.kt
index 8bb07d9..94fc1fc 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/android/content/pm/LauncherAppsKosmos.kt
@@ -14,10 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.systemui.deviceentry.data.repository
+package android.content.pm
 
 import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.util.mockito.mock
 
-var Kosmos.deviceEntryHapticsRepository: DeviceEntryHapticsRepository by
-    Kosmos.Fixture { fakeDeviceEntryHapticsRepository }
-val Kosmos.fakeDeviceEntryHapticsRepository by Kosmos.Fixture { FakeDeviceEntryHapticsRepository() }
+val Kosmos.launcherApps by Kosmos.Fixture { mock<LauncherApps>() }
diff --git a/packages/SystemUI/tests/utils/src/android/graphics/drawable/TestStubDrawable.kt b/packages/SystemUI/tests/utils/src/android/graphics/drawable/TestStubDrawable.kt
new file mode 100644
index 0000000..b88f302
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/android/graphics/drawable/TestStubDrawable.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.drawable
+
+import android.graphics.Canvas
+import android.graphics.ColorFilter
+import android.graphics.PixelFormat
+
+/**
+ * Stub drawable that does nothing. It's to be used in tests as a mock drawable and checked for the
+ * same instance
+ */
+class TestStubDrawable : Drawable() {
+
+    override fun draw(canvas: Canvas) = Unit
+    override fun setAlpha(alpha: Int) = Unit
+    override fun setColorFilter(colorFilter: ColorFilter?) = Unit
+    override fun getOpacity(): Int = PixelFormat.UNKNOWN
+
+    override fun equals(other: Any?): Boolean = this === other
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/data/repository/FakeColorCorrectionRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/data/repository/FakeColorCorrectionRepository.kt
new file mode 100644
index 0000000..607a4f3
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/data/repository/FakeColorCorrectionRepository.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.accessibility.data.repository
+
+import android.os.UserHandle
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+
+class FakeColorCorrectionRepository : ColorCorrectionRepository {
+    private val userMap = mutableMapOf<Int, MutableStateFlow<Boolean>>()
+
+    override fun isEnabled(userHandle: UserHandle): StateFlow<Boolean> {
+        return getFlow(userHandle.identifier)
+    }
+
+    override suspend fun setIsEnabled(isEnabled: Boolean, userHandle: UserHandle): Boolean {
+        getFlow(userHandle.identifier).value = isEnabled
+        return true
+    }
+
+    /** initializes the flow if already not */
+    private fun getFlow(userId: Int): MutableStateFlow<Boolean> {
+        return userMap.getOrPut(userId) { MutableStateFlow(false) }
+    }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt
index 4fdea97..7c5696c 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt
@@ -20,10 +20,10 @@
 import com.android.internal.widget.LockPatternView
 import com.android.internal.widget.LockscreenCredential
 import com.android.keyguard.KeyguardSecurityModel.SecurityMode
+import com.android.systemui.authentication.shared.model.AuthenticationLockoutModel
 import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.authentication.shared.model.AuthenticationPatternCoordinate
 import com.android.systemui.authentication.shared.model.AuthenticationResultModel
-import com.android.systemui.authentication.shared.model.AuthenticationThrottlingModel
 import com.android.systemui.dagger.SysUISingleton
 import dagger.Binds
 import dagger.Module
@@ -40,9 +40,6 @@
     private val currentTime: () -> Long,
 ) : AuthenticationRepository {
 
-    private val _isAutoConfirmFeatureEnabled = MutableStateFlow(false)
-    override val isAutoConfirmFeatureEnabled: StateFlow<Boolean> =
-        _isAutoConfirmFeatureEnabled.asStateFlow()
     override val authenticationChallengeResult = MutableSharedFlow<Boolean>()
 
     override val hintedPinLength: Int = HINTING_PIN_LENGTH
@@ -50,8 +47,13 @@
     private val _isPatternVisible = MutableStateFlow(true)
     override val isPatternVisible: StateFlow<Boolean> = _isPatternVisible.asStateFlow()
 
-    override val throttling: MutableStateFlow<AuthenticationThrottlingModel?> =
-        MutableStateFlow(null)
+    override val lockout: MutableStateFlow<AuthenticationLockoutModel?> = MutableStateFlow(null)
+
+    override val hasLockoutOccurred = MutableStateFlow(false)
+
+    private val _isAutoConfirmFeatureEnabled = MutableStateFlow(false)
+    override val isAutoConfirmFeatureEnabled: StateFlow<Boolean> =
+        _isAutoConfirmFeatureEnabled.asStateFlow()
 
     private val _authenticationMethod =
         MutableStateFlow<AuthenticationMethodModel>(DEFAULT_AUTHENTICATION_METHOD)
@@ -67,10 +69,12 @@
         _isPinEnhancedPrivacyEnabled.asStateFlow()
 
     private var failedAttemptCount = 0
-    private var throttlingEndTimestamp = 0L
+    private var lockoutEndTimestamp = 0L
     private var credentialOverride: List<Any>? = null
     private var securityMode: SecurityMode = DEFAULT_AUTHENTICATION_METHOD.toSecurityMode()
 
+    var lockoutStartedReportCount = 0
+
     override suspend fun getAuthenticationMethod(): AuthenticationMethodModel {
         return authenticationMethod.value
     }
@@ -89,6 +93,10 @@
         authenticationChallengeResult.emit(isSuccessful)
     }
 
+    override suspend fun reportLockoutStarted(durationMs: Int) {
+        lockoutStartedReportCount++
+    }
+
     override suspend fun getPinLength(): Int {
         return (credentialOverride ?: DEFAULT_PIN).size
     }
@@ -97,16 +105,19 @@
         return failedAttemptCount
     }
 
-    override suspend fun getThrottlingEndTimestamp(): Long {
-        return throttlingEndTimestamp
+    override suspend fun getLockoutEndTimestamp(): Long {
+        return lockoutEndTimestamp
     }
 
     fun setAutoConfirmFeatureEnabled(isEnabled: Boolean) {
         _isAutoConfirmFeatureEnabled.value = isEnabled
     }
 
-    override suspend fun setThrottleDuration(durationMs: Int) {
-        throttlingEndTimestamp = if (durationMs > 0) currentTime() + durationMs else 0
+    override suspend fun setLockoutDuration(durationMs: Int) {
+        lockoutEndTimestamp = if (durationMs > 0) currentTime() + durationMs else 0
+        if (durationMs > 0) {
+            hasLockoutOccurred.value = true
+        }
     }
 
     override suspend fun checkCredential(
@@ -125,17 +136,16 @@
                 else -> error("Unexpected credential type ${credential.type}!")
             }
 
-        return if (
-            isSuccessful || failedAttemptCount < MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING - 1
-        ) {
+        return if (isSuccessful || failedAttemptCount < MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT - 1) {
+            hasLockoutOccurred.value = false
             AuthenticationResultModel(
                 isSuccessful = isSuccessful,
-                throttleDurationMs = 0,
+                lockoutDurationMs = 0,
             )
         } else {
             AuthenticationResultModel(
                 isSuccessful = false,
-                throttleDurationMs = THROTTLE_DURATION_MS,
+                lockoutDurationMs = LOCKOUT_DURATION_MS,
             )
         }
     }
@@ -165,8 +175,9 @@
                 AuthenticationPatternCoordinate(0, 1),
                 AuthenticationPatternCoordinate(0, 2),
             )
-        const val MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING = 5
-        const val THROTTLE_DURATION_MS = 30000
+        const val MAX_FAILED_AUTH_TRIES_BEFORE_LOCKOUT = 5
+        const val LOCKOUT_DURATION_SECONDS = 30
+        const val LOCKOUT_DURATION_MS = LOCKOUT_DURATION_SECONDS * 1000
         const val HINTING_PIN_LENGTH = 6
         val DEFAULT_PIN = buildList { repeat(HINTING_PIN_LENGTH) { add(it + 1) } }
 
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeBiometricStatusRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeBiometricStatusRepository.kt
new file mode 100644
index 0000000..1c8bd3b
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeBiometricStatusRepository.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.biometrics.data.repository
+
+import com.android.systemui.biometrics.shared.model.AuthenticationReason
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+
+class FakeBiometricStatusRepository : BiometricStatusRepository {
+    private val _fingerprintAuthenticationReason =
+        MutableStateFlow<AuthenticationReason>(AuthenticationReason.NotRunning)
+    override val fingerprintAuthenticationReason: StateFlow<AuthenticationReason> =
+        _fingerprintAuthenticationReason.asStateFlow()
+
+    fun setFingerprintAuthenticationReason(reason: AuthenticationReason) {
+        _fingerprintAuthenticationReason.value = reason
+    }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/data/repository/FakeKeyguardBouncerRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/data/repository/FakeKeyguardBouncerRepository.kt
index f84481c..ff5179a 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/data/repository/FakeKeyguardBouncerRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/data/repository/FakeKeyguardBouncerRepository.kt
@@ -1,5 +1,6 @@
 package com.android.systemui.bouncer.data.repository
 
+import com.android.systemui.biometrics.shared.SideFpsControllerRefactor
 import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants
 import com.android.systemui.bouncer.shared.model.BouncerShowMessageModel
 import com.android.systemui.dagger.SysUISingleton
@@ -113,7 +114,9 @@
         _isBackButtonEnabled.value = isBackButtonEnabled
     }
 
+    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
     override fun setSideFpsShowing(isShowing: Boolean) {
+        SideFpsControllerRefactor.assertInLegacyMode()
         _sideFpsShowing.value = isShowing
     }
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalRepository.kt
index 2cb17b5..c85c27e 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalRepository.kt
@@ -1,19 +1,47 @@
 package com.android.systemui.communal.data.repository
 
 import com.android.systemui.communal.shared.model.CommunalSceneKey
+import com.android.systemui.communal.shared.model.ObservableCommunalTransitionState
+import com.android.systemui.dagger.qualifiers.Background
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.test.TestScope
 
 /** Fake implementation of [CommunalRepository]. */
+@OptIn(ExperimentalCoroutinesApi::class)
 class FakeCommunalRepository(
+    @Background applicationScope: CoroutineScope = TestScope(),
     override var isCommunalEnabled: Boolean = false,
     override val desiredScene: MutableStateFlow<CommunalSceneKey> =
-        MutableStateFlow(CommunalSceneKey.Blank)
+        MutableStateFlow(CommunalSceneKey.DEFAULT),
 ) : CommunalRepository {
     override fun setDesiredScene(desiredScene: CommunalSceneKey) {
         this.desiredScene.value = desiredScene
     }
 
+    private val defaultTransitionState =
+        ObservableCommunalTransitionState.Idle(CommunalSceneKey.DEFAULT)
+    private val _transitionState = MutableStateFlow<Flow<ObservableCommunalTransitionState>?>(null)
+    override val transitionState: StateFlow<ObservableCommunalTransitionState> =
+        _transitionState
+            .flatMapLatest { innerFlowOrNull -> innerFlowOrNull ?: flowOf(defaultTransitionState) }
+            .stateIn(
+                scope = applicationScope,
+                started = SharingStarted.Eagerly,
+                initialValue = defaultTransitionState,
+            )
+
+    override fun setTransitionState(transitionState: Flow<ObservableCommunalTransitionState>?) {
+        _transitionState.value = transitionState
+    }
+
     fun setIsCommunalEnabled(value: Boolean) {
         isCommunalEnabled = value
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/FakeDeviceEntryDataLayerModule.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/FakeDeviceEntryDataLayerModule.kt
index d97cb56..8ff04a63 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/FakeDeviceEntryDataLayerModule.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/FakeDeviceEntryDataLayerModule.kt
@@ -16,7 +16,6 @@
 package com.android.systemui.deviceentry.data
 
 import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepositoryModule
-import com.android.systemui.deviceentry.data.repository.FakeDeviceEntryHapticsRepositoryModule
 import com.android.systemui.deviceentry.data.repository.FakeDeviceEntryRepositoryModule
 import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepositoryModule
 import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFaceAuthRepositoryModule
@@ -29,7 +28,6 @@
         [
             FakeBiometricSettingsRepositoryModule::class,
             FakeDeviceEntryRepositoryModule::class,
-            FakeDeviceEntryHapticsRepositoryModule::class,
             FakeDeviceEntryFaceAuthRepositoryModule::class,
             FakeDeviceEntryFingerprintAuthRepositoryModule::class,
             FakeFingerprintPropertyRepositoryModule::class,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/FakeDeviceEntryHapticsRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/FakeDeviceEntryHapticsRepository.kt
deleted file mode 100644
index b29b67d..0000000
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/FakeDeviceEntryHapticsRepository.kt
+++ /dev/null
@@ -1,55 +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.deviceentry.data.repository
-
-import com.android.systemui.dagger.SysUISingleton
-import dagger.Binds
-import dagger.Module
-import javax.inject.Inject
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.asStateFlow
-
-/** Fake implementation of [DeviceEntryHapticsRepository] */
-@SysUISingleton
-class FakeDeviceEntryHapticsRepository @Inject constructor() : DeviceEntryHapticsRepository {
-    private var _successHapticRequest: MutableStateFlow<Boolean> = MutableStateFlow(false)
-    override val successHapticRequest: Flow<Boolean> = _successHapticRequest.asStateFlow()
-
-    private var _errorHapticRequest: MutableStateFlow<Boolean> = MutableStateFlow(false)
-    override val errorHapticRequest: Flow<Boolean> = _errorHapticRequest.asStateFlow()
-
-    override fun requestSuccessHaptic() {
-        _successHapticRequest.value = true
-    }
-
-    override fun handleSuccessHaptic() {
-        _successHapticRequest.value = false
-    }
-
-    override fun requestErrorHaptic() {
-        _errorHapticRequest.value = true
-    }
-
-    override fun handleErrorHaptic() {
-        _errorHapticRequest.value = false
-    }
-}
-
-@Module
-interface FakeDeviceEntryHapticsRepositoryModule {
-    @Binds fun bindFake(fake: FakeDeviceEntryHapticsRepository): DeviceEntryHapticsRepository
-}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/FakeDeviceEntryRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/FakeDeviceEntryRepository.kt
index ba70d46..6436a38 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/FakeDeviceEntryRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/FakeDeviceEntryRepository.kt
@@ -16,16 +16,24 @@
 package com.android.systemui.deviceentry.data.repository
 
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
 import dagger.Binds
 import dagger.Module
 import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableSharedFlow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asSharedFlow
 import kotlinx.coroutines.flow.asStateFlow
 
 /** Fake implementation of [DeviceEntryRepository] */
 @SysUISingleton
 class FakeDeviceEntryRepository @Inject constructor() : DeviceEntryRepository {
+    private val _enteringDeviceFromBiometricUnlock: MutableSharedFlow<BiometricUnlockSource> =
+        MutableSharedFlow()
+    override val enteringDeviceFromBiometricUnlock: Flow<BiometricUnlockSource> =
+        _enteringDeviceFromBiometricUnlock.asSharedFlow()
 
     private var isLockscreenEnabled = true
 
@@ -54,6 +62,10 @@
     fun setBypassEnabled(isBypassEnabled: Boolean) {
         _isBypassEnabled.value = isBypassEnabled
     }
+
+    suspend fun enteringDeviceFromBiometricUnlock(sourceType: BiometricUnlockSource) {
+        _enteringDeviceFromBiometricUnlock.emit(sourceType)
+    }
 }
 
 @Module
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricAuthInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricAuthInteractorKosmos.kt
new file mode 100644
index 0000000..1bd1056
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricAuthInteractorKosmos.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.deviceentry.domain.interactor
+
+import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
+import com.android.systemui.kosmos.Kosmos
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+val Kosmos.deviceEntryBiometricAuthInteractor by
+    Kosmos.Fixture {
+        DeviceEntryBiometricAuthInteractor(
+            biometricSettingsRepository = biometricSettingsRepository,
+            deviceEntryFaceAuthInteractor = deviceEntryFaceAuthInteractor,
+        )
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorKosmos.kt
similarity index 61%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorKosmos.kt
index 8bb07d9..d2dff78 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorKosmos.kt
@@ -14,10 +14,17 @@
  * limitations under the License.
  */
 
-package com.android.systemui.deviceentry.data.repository
+@file:OptIn(ExperimentalCoroutinesApi::class)
 
+package com.android.systemui.deviceentry.domain.interactor
+
+import com.android.systemui.keyguard.data.repository.deviceEntryFaceAuthRepository
 import com.android.systemui.kosmos.Kosmos
+import kotlinx.coroutines.ExperimentalCoroutinesApi
 
-var Kosmos.deviceEntryHapticsRepository: DeviceEntryHapticsRepository by
-    Kosmos.Fixture { fakeDeviceEntryHapticsRepository }
-val Kosmos.fakeDeviceEntryHapticsRepository by Kosmos.Fixture { FakeDeviceEntryHapticsRepository() }
+val Kosmos.deviceEntryFaceAuthInteractor by
+    Kosmos.Fixture {
+        DeviceEntryFaceAuthInteractor(
+            repository = deviceEntryFaceAuthRepository,
+        )
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFingerprintAuthInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFingerprintAuthInteractorKosmos.kt
new file mode 100644
index 0000000..66c6f86
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFingerprintAuthInteractorKosmos.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.deviceentry.domain.interactor
+
+import com.android.systemui.keyguard.data.repository.deviceEntryFingerprintAuthRepository
+import com.android.systemui.kosmos.Kosmos
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+val Kosmos.deviceEntryFingerprintAuthInteractor by
+    Kosmos.Fixture {
+        DeviceEntryFingerprintAuthInteractor(
+            repository = deviceEntryFingerprintAuthRepository,
+        )
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorKosmos.kt
index de6cacb..6bf527d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorKosmos.kt
@@ -20,7 +20,6 @@
 
 import com.android.keyguard.logging.biometricUnlockLogger
 import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository
-import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryHapticsRepository
 import com.android.systemui.keyevent.domain.interactor.keyEventInteractor
 import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
 import com.android.systemui.kosmos.Kosmos
@@ -31,7 +30,9 @@
 val Kosmos.deviceEntryHapticsInteractor by
     Kosmos.Fixture {
         DeviceEntryHapticsInteractor(
-            repository = fakeDeviceEntryHapticsRepository,
+            deviceEntryInteractor = deviceEntryInteractor,
+            deviceEntryFingerprintAuthInteractor = deviceEntryFingerprintAuthInteractor,
+            deviceEntryBiometricAuthInteractor = deviceEntryBiometricAuthInteractor,
             fingerprintPropertyRepository = fingerprintPropertyRepository,
             biometricSettingsRepository = biometricSettingsRepository,
             keyEventInteractor = keyEventInteractor,
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 e6b7f62..abadaf7 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
@@ -16,6 +16,45 @@
 
 package com.android.systemui.flags
 
+import android.content.res.mainResources
 import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.util.mockito.mock
 
-val Kosmos.featureFlagsClassic by Kosmos.Fixture { FakeFeatureFlagsClassic() }
+/**
+ * Main fixture for supplying a [FeatureFlagsClassic]. Should be used by other fixtures. Unless
+ * overridden in the test, this by default uses [fakeFeatureFlagsClassic].
+ */
+var Kosmos.featureFlagsClassic: FeatureFlagsClassic by Kosmos.Fixture { fakeFeatureFlagsClassic }
+
+/**
+ * Fixture supplying a shared [FakeFeatureFlagsClassic] instance. Can be accessed in tests in order
+ * to override flag values.
+ */
+val Kosmos.fakeFeatureFlagsClassic by Kosmos.Fixture { FakeFeatureFlagsClassic() }
+
+/**
+ * Fixture supplying a real [FeatureFlagsClassicRelease] instance, for use by tests that want to
+ * reflect the current state of the device in release builds (example: screenshot tests).
+ *
+ * By default, this fixture is unused; tests should override [featureFlagsClassic] in order to
+ * utilize this fixture:
+ * ```kotlin
+ *   val kosmos = Kosmos()
+ *   kosmos.featureFlagsClassic = kosmos.featureFlagsClassicRelease
+ * ```
+ */
+val Kosmos.featureFlagsClassicRelease by
+    Kosmos.Fixture {
+        FeatureFlagsClassicRelease(
+            /* resources = */ mainResources,
+            /* systemProperties = */ systemPropertiesHelper,
+            /* serverFlagReader = */ serverFlagReader,
+            /* allFlags = */ FlagsCommonModule.providesAllFlags(),
+            /* restarter = */ restarter,
+        )
+    }
+
+val Kosmos.systemPropertiesHelper by Kosmos.Fixture { SystemPropertiesHelper() }
+var Kosmos.serverFlagReader: ServerFlagReader by Kosmos.Fixture { serverFlagReaderFake }
+val Kosmos.serverFlagReaderFake by Kosmos.Fixture { ServerFlagReaderFake() }
+var Kosmos.restarter: Restarter by Kosmos.Fixture { mock() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDeviceEntryFaceAuthRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDeviceEntryFaceAuthRepository.kt
index e289083..a1b6587 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDeviceEntryFaceAuthRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDeviceEntryFaceAuthRepository.kt
@@ -31,7 +31,6 @@
 
 @SysUISingleton
 class FakeDeviceEntryFaceAuthRepository @Inject constructor() : DeviceEntryFaceAuthRepository {
-
     override val isAuthenticated = MutableStateFlow(false)
     override val canRunFaceAuth = MutableStateFlow(false)
     private val _authenticationStatus = MutableStateFlow<FaceAuthenticationStatus?>(null)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDeviceEntryFingerprintAuthRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDeviceEntryFingerprintAuthRepository.kt
index c9160ef..1d44929 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDeviceEntryFingerprintAuthRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDeviceEntryFingerprintAuthRepository.kt
@@ -54,6 +54,11 @@
     private var _authenticationStatus = MutableStateFlow<FingerprintAuthenticationStatus?>(null)
     override val authenticationStatus: Flow<FingerprintAuthenticationStatus>
         get() = _authenticationStatus.filterNotNull()
+
+    private var _shouldUpdateIndicatorVisibility = MutableStateFlow(false)
+    override val shouldUpdateIndicatorVisibility: Flow<Boolean>
+        get() = _shouldUpdateIndicatorVisibility
+
     fun setAuthenticationStatus(status: FingerprintAuthenticationStatus) {
         _authenticationStatus.value = status
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
index 0e7c662..4200f05 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
@@ -41,6 +41,10 @@
     private val _deferKeyguardDone: MutableSharedFlow<KeyguardDone> = MutableSharedFlow()
     override val keyguardDone: Flow<KeyguardDone> = _deferKeyguardDone
 
+    private val _keyguardDoneAnimationsFinished: MutableSharedFlow<Unit> =
+        MutableSharedFlow(extraBufferCapacity = 1)
+    override val keyguardDoneAnimationsFinished: Flow<Unit> = _keyguardDoneAnimationsFinished
+
     private val _clockShouldBeCentered = MutableStateFlow<Boolean>(true)
     override val clockShouldBeCentered: Flow<Boolean> = _clockShouldBeCentered
 
@@ -121,6 +125,8 @@
 
     override val lastRootViewTapPosition: MutableStateFlow<Point?> = MutableStateFlow(null)
 
+    override val ambientIndicationVisible: MutableStateFlow<Boolean> = MutableStateFlow(false)
+
     override fun setQuickSettingsVisible(isVisible: Boolean) {
         _isQuickSettingsVisible.value = isVisible
     }
@@ -174,6 +180,10 @@
         _deferKeyguardDone.emit(timing)
     }
 
+    override fun keyguardDoneAnimationsFinished() {
+        _keyguardDoneAnimationsFinished.tryEmit(Unit)
+    }
+
     override fun setClockShouldBeCentered(shouldBeCentered: Boolean) {
         _clockShouldBeCentered.value = shouldBeCentered
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorFactory.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorFactory.kt
index 3d8ae1e..3cabf0c 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorFactory.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorFactory.kt
@@ -27,8 +27,6 @@
 import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
 import com.android.systemui.bouncer.ui.BouncerView
 import com.android.systemui.classifier.FalsingCollector
-import com.android.systemui.flags.FakeFeatureFlagsClassic
-import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.DismissCallbackRegistry
 import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
@@ -57,12 +55,6 @@
         keyguardRepository: FakeKeyguardRepository = FakeKeyguardRepository(),
         bouncerRepository: FakeKeyguardBouncerRepository = FakeKeyguardBouncerRepository(),
         keyguardUpdateMonitor: KeyguardUpdateMonitor = mock(KeyguardUpdateMonitor::class.java),
-        featureFlags: FakeFeatureFlagsClassic =
-            FakeFeatureFlagsClassic().apply {
-                set(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT, true)
-                set(Flags.FULL_SCREEN_USER_SWITCHER, false)
-                set(Flags.REFACTOR_GETCURRENTUSER, true)
-            },
         powerRepository: FakePowerRepository = FakePowerRepository(),
         userRepository: FakeUserRepository = FakeUserRepository(),
     ): WithDependencies {
@@ -98,8 +90,7 @@
             PowerInteractorFactory.create(
                 repository = powerRepository,
             )
-        val selectedUserInteractor =
-            SelectedUserInteractor(repository = userRepository, flags = featureFlags)
+        val selectedUserInteractor = SelectedUserInteractor(repository = userRepository)
         return WithDependencies(
             trustRepository = trustRepository,
             keyguardRepository = keyguardRepository,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModelKosmos.kt
index 299262b..6557bcf 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModelKosmos.kt
@@ -16,7 +16,6 @@
 
 package com.android.systemui.keyguard.ui.viewmodel
 
-import com.android.systemui.deviceentry.domain.interactor.deviceEntryHapticsInteractor
 import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
 import com.android.systemui.deviceentry.domain.interactor.deviceEntryUdfpsInteractor
 import com.android.systemui.keyguard.domain.interactor.burnInInteractor
@@ -45,7 +44,6 @@
         shadeDependentFlows = shadeDependentFlows,
         sceneContainerFlags = sceneContainerFlags,
         keyguardViewController = { statusBarKeyguardViewManager },
-        deviceEntryHapticsInteractor = deviceEntryHapticsInteractor,
         deviceEntryInteractor = deviceEntryInteractor,
     )
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/log/LogAssert.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/log/LogAssert.kt
new file mode 100644
index 0000000..6ccb3bc
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/log/LogAssert.kt
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log
+
+import android.util.Log
+import android.util.Log.TerribleFailureHandler
+import junit.framework.Assert
+
+/**
+ * Assert that the given block makes a call to Log.wtf
+ *
+ * @return the details of the log
+ */
+fun assertLogsWtf(
+    message: String = "Expected Log.wtf to be called",
+    allowMultiple: Boolean = false,
+    loggingBlock: () -> Unit,
+): TerribleFailureLog {
+    var caught: TerribleFailureLog? = null
+    var count = 0
+    val newHandler = TerribleFailureHandler { tag, failure, system ->
+        if (caught == null) {
+            caught = TerribleFailureLog(tag, failure, system)
+        }
+        count++
+    }
+    val oldHandler = Log.setWtfHandler(newHandler)
+    try {
+        loggingBlock()
+    } finally {
+        Log.setWtfHandler(oldHandler)
+    }
+    Assert.assertNotNull(message, caught)
+    if (!allowMultiple && count != 1) {
+        Assert.fail("Unexpectedly caught Log.Wtf $count times; expected only 1.  First: $caught")
+    }
+    return caught!!
+}
+
+@JvmOverloads
+fun assertLogsWtf(
+    message: String = "Expected Log.wtf to be called",
+    allowMultiple: Boolean = false,
+    loggingRunnable: Runnable,
+): TerribleFailureLog =
+    assertLogsWtf(message = message, allowMultiple = allowMultiple) { loggingRunnable.run() }
+
+fun assertLogsWtfs(
+    message: String = "Expected Log.wtf to be called once or more",
+    loggingBlock: () -> Unit,
+): TerribleFailureLog = assertLogsWtf(message, allowMultiple = true, loggingBlock)
+
+@JvmOverloads
+fun assertLogsWtfs(
+    message: String = "Expected Log.wtf to be called once or more",
+    loggingRunnable: Runnable,
+): TerribleFailureLog = assertLogsWtfs(message) { loggingRunnable.run() }
+
+/** The data passed to [TerribleFailureHandler.onTerribleFailure] */
+data class TerribleFailureLog(
+    val tag: String,
+    val failure: Log.TerribleFailure,
+    val system: Boolean
+)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/QuickSettingsKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/QuickSettingsKosmos.kt
index 1cb2587..6332c1a 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/QuickSettingsKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/QuickSettingsKosmos.kt
@@ -19,9 +19,14 @@
 import com.android.internal.logging.testing.UiEventLoggerFake
 import com.android.systemui.InstanceIdSequenceFake
 import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.plugins.qs.QSFactory
+import com.android.systemui.qs.tiles.di.NewQSTileFactory
 
 val Kosmos.instanceIdSequenceFake: InstanceIdSequenceFake by
     Kosmos.Fixture { InstanceIdSequenceFake(0) }
 val Kosmos.uiEventLogger: UiEventLoggerFake by Kosmos.Fixture { UiEventLoggerFake() }
 val Kosmos.qsEventLogger: QsEventLoggerFake by
     Kosmos.Fixture { QsEventLoggerFake(uiEventLogger, instanceIdSequenceFake) }
+
+var Kosmos.newQSTileFactory by Kosmos.Fixture<NewQSTileFactory>()
+var Kosmos.qsTileFactory by Kosmos.Fixture<QSFactory>()
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/external/CustomTileStatePersisterKosmos.kt
similarity index 69%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/qs/external/CustomTileStatePersisterKosmos.kt
index 8bb07d9..f01e3aa 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/external/CustomTileStatePersisterKosmos.kt
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.android.systemui.deviceentry.data.repository
+package com.android.systemui.qs.external
 
 import com.android.systemui.kosmos.Kosmos
 
-var Kosmos.deviceEntryHapticsRepository: DeviceEntryHapticsRepository by
-    Kosmos.Fixture { fakeDeviceEntryHapticsRepository }
-val Kosmos.fakeDeviceEntryHapticsRepository by Kosmos.Fixture { FakeDeviceEntryHapticsRepository() }
+var Kosmos.customTileStatePersister: CustomTileStatePersister by
+    Kosmos.Fixture { fakeCustomTileStatePersister }
+val Kosmos.fakeCustomTileStatePersister by Kosmos.Fixture { FakeCustomTileStatePersister() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/external/TileLifecycleManagerFactoryKosmos.kt
similarity index 69%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/qs/external/TileLifecycleManagerFactoryKosmos.kt
index 8bb07d9..f8ce707 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/external/TileLifecycleManagerFactoryKosmos.kt
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-package com.android.systemui.deviceentry.data.repository
+package com.android.systemui.qs.external
 
 import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.util.mockito.mock
 
-var Kosmos.deviceEntryHapticsRepository: DeviceEntryHapticsRepository by
-    Kosmos.Fixture { fakeDeviceEntryHapticsRepository }
-val Kosmos.fakeDeviceEntryHapticsRepository by Kosmos.Fixture { FakeDeviceEntryHapticsRepository() }
+/** Returns mocks */
+var Kosmos.tileLifecycleManagerFactory: TileLifecycleManager.Factory by
+    Kosmos.Fixture { TileLifecycleManager.Factory { _, _ -> mock<TileLifecycleManager>() } }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/data/model/RestoreProcessorsKosmos.kt
similarity index 65%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/data/model/RestoreProcessorsKosmos.kt
index 8bb07d9..d93dd8d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/data/model/RestoreProcessorsKosmos.kt
@@ -14,10 +14,16 @@
  * limitations under the License.
  */
 
-package com.android.systemui.deviceentry.data.repository
+package com.android.systemui.qs.pipeline.data.model
 
 import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.qs.pipeline.data.restoreprocessors.WorkTileRestoreProcessor
 
-var Kosmos.deviceEntryHapticsRepository: DeviceEntryHapticsRepository by
-    Kosmos.Fixture { fakeDeviceEntryHapticsRepository }
-val Kosmos.fakeDeviceEntryHapticsRepository by Kosmos.Fixture { FakeDeviceEntryHapticsRepository() }
+val Kosmos.workTileRestoreProcessor by Kosmos.Fixture { WorkTileRestoreProcessor() }
+
+var Kosmos.restoreProcessors by
+    Kosmos.Fixture {
+        setOf(
+            workTileRestoreProcessor,
+        )
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/data/repository/QSPipelineRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/data/repository/QSPipelineRepositoryKosmos.kt
new file mode 100644
index 0000000..0091482
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/data/repository/QSPipelineRepositoryKosmos.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.pipeline.data.repository
+
+import com.android.systemui.kosmos.Kosmos
+
+val Kosmos.fakeTileSpecRepository by Kosmos.Fixture { FakeTileSpecRepository() }
+var Kosmos.tileSpecRepository: TileSpecRepository by Kosmos.Fixture { fakeTileSpecRepository }
+
+val Kosmos.fakeAutoAddRepository by Kosmos.Fixture { FakeAutoAddRepository() }
+var Kosmos.autoAddRepository: AutoAddRepository by Kosmos.Fixture { fakeAutoAddRepository }
+
+val Kosmos.fakeRestoreRepository by Kosmos.Fixture { FakeQSSettingsRestoredRepository() }
+var Kosmos.restoreRepository: QSSettingsRestoredRepository by
+    Kosmos.Fixture { fakeRestoreRepository }
+
+val Kosmos.fakeInstalledTilesRepository by
+    Kosmos.Fixture { FakeInstalledTilesComponentRepository() }
+var Kosmos.installedTilesRepository: InstalledTilesComponentRepository by
+    Kosmos.Fixture { fakeInstalledTilesRepository }
+
+val Kosmos.fakeCustomTileAddedRepository by Kosmos.Fixture { FakeCustomTileAddedRepository() }
+var Kosmos.customTileAddedRepository: CustomTileAddedRepository by
+    Kosmos.Fixture { fakeCustomTileAddedRepository }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/domain/autoaddable/AutoAddablesKosmos.kt
similarity index 63%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/domain/autoaddable/AutoAddablesKosmos.kt
index 8bb07d9..35f178b 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/domain/autoaddable/AutoAddablesKosmos.kt
@@ -14,10 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.systemui.deviceentry.data.repository
+package com.android.systemui.qs.pipeline.domain.autoaddable
 
 import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.qs.pipeline.data.model.workTileRestoreProcessor
+import com.android.systemui.settings.userTracker
 
-var Kosmos.deviceEntryHapticsRepository: DeviceEntryHapticsRepository by
-    Kosmos.Fixture { fakeDeviceEntryHapticsRepository }
-val Kosmos.fakeDeviceEntryHapticsRepository by Kosmos.Fixture { FakeDeviceEntryHapticsRepository() }
+val Kosmos.workTileAutoAddable by
+    Kosmos.Fixture { WorkTileAutoAddable(userTracker, workTileRestoreProcessor) }
+
+var Kosmos.autoAddables by Kosmos.Fixture { setOf(workTileAutoAddable) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/domain/autoaddable/FakeAutoAddable.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/domain/autoaddable/FakeAutoAddable.kt
index ebdd6fd..bf8f4da 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/domain/autoaddable/FakeAutoAddable.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/domain/autoaddable/FakeAutoAddable.kt
@@ -39,14 +39,18 @@
         return getFlow(userId).asStateFlow().filterNotNull()
     }
 
-    suspend fun sendRemoveSignal(userId: Int) {
+    fun sendRemoveSignal(userId: Int) {
         getFlow(userId).value = AutoAddSignal.Remove(spec)
     }
 
-    suspend fun sendAddSignal(userId: Int, position: Int = POSITION_AT_END) {
+    fun sendAddSignal(userId: Int, position: Int = POSITION_AT_END) {
         getFlow(userId).value = AutoAddSignal.Add(spec, position)
     }
 
+    fun sendRemoveTrackingSignal(userId: Int) {
+        getFlow(userId).value = AutoAddSignal.RemoveTracking(spec)
+    }
+
     override val description: String
         get() = "FakeAutoAddable($spec)"
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/domain/interactor/AutoAddInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/domain/interactor/AutoAddInteractorKosmos.kt
new file mode 100644
index 0000000..5e8471c
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/domain/interactor/AutoAddInteractorKosmos.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.pipeline.domain.interactor
+
+import com.android.systemui.dump.dumpManager
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.qs.pipeline.data.repository.autoAddRepository
+import com.android.systemui.qs.pipeline.domain.autoaddable.autoAddables
+import com.android.systemui.qs.pipeline.shared.logging.qsLogger
+
+val Kosmos.autoAddInteractor by
+    Kosmos.Fixture {
+        AutoAddInteractor(
+            autoAddables,
+            autoAddRepository,
+            dumpManager,
+            qsLogger,
+            applicationCoroutineScope,
+        )
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorKosmos.kt
new file mode 100644
index 0000000..67df563
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorKosmos.kt
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.pipeline.domain.interactor
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.kosmos.testDispatcher
+import com.android.systemui.qs.external.customTileStatePersister
+import com.android.systemui.qs.external.tileLifecycleManagerFactory
+import com.android.systemui.qs.newQSTileFactory
+import com.android.systemui.qs.pipeline.data.repository.customTileAddedRepository
+import com.android.systemui.qs.pipeline.data.repository.installedTilesRepository
+import com.android.systemui.qs.pipeline.data.repository.tileSpecRepository
+import com.android.systemui.qs.pipeline.shared.logging.qsLogger
+import com.android.systemui.qs.pipeline.shared.pipelineFlagsRepository
+import com.android.systemui.qs.qsTileFactory
+import com.android.systemui.settings.userTracker
+import com.android.systemui.user.data.repository.userRepository
+
+val Kosmos.currentTilesInteractor: CurrentTilesInteractor by
+    Kosmos.Fixture {
+        CurrentTilesInteractorImpl(
+            tileSpecRepository,
+            installedTilesRepository,
+            userRepository,
+            customTileStatePersister,
+            { newQSTileFactory },
+            qsTileFactory,
+            customTileAddedRepository,
+            tileLifecycleManagerFactory,
+            userTracker,
+            testDispatcher,
+            testDispatcher,
+            applicationCoroutineScope,
+            qsLogger,
+            pipelineFlagsRepository,
+        )
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/domain/interactor/RestoreReconciliationInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/domain/interactor/RestoreReconciliationInteractorKosmos.kt
new file mode 100644
index 0000000..55c23d4
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/domain/interactor/RestoreReconciliationInteractorKosmos.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.pipeline.domain.interactor
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.kosmos.testDispatcher
+import com.android.systemui.qs.pipeline.data.model.restoreProcessors
+import com.android.systemui.qs.pipeline.data.repository.autoAddRepository
+import com.android.systemui.qs.pipeline.data.repository.restoreRepository
+import com.android.systemui.qs.pipeline.data.repository.tileSpecRepository
+import com.android.systemui.qs.pipeline.shared.logging.qsLogger
+
+val Kosmos.restoreReconciliationInteractor by
+    Kosmos.Fixture {
+        RestoreReconciliationInteractor(
+            tileSpecRepository,
+            autoAddRepository,
+            restoreRepository,
+            restoreProcessors,
+            qsLogger,
+            applicationCoroutineScope,
+            testDispatcher,
+        )
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/shared/QSPipelineFlagRepositoryKosmos.kt
similarity index 69%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/shared/QSPipelineFlagRepositoryKosmos.kt
index 8bb07d9..961545a 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/shared/QSPipelineFlagRepositoryKosmos.kt
@@ -14,10 +14,8 @@
  * limitations under the License.
  */
 
-package com.android.systemui.deviceentry.data.repository
+package com.android.systemui.qs.pipeline.shared
 
 import com.android.systemui.kosmos.Kosmos
 
-var Kosmos.deviceEntryHapticsRepository: DeviceEntryHapticsRepository by
-    Kosmos.Fixture { fakeDeviceEntryHapticsRepository }
-val Kosmos.fakeDeviceEntryHapticsRepository by Kosmos.Fixture { FakeDeviceEntryHapticsRepository() }
+val Kosmos.pipelineFlagsRepository by Kosmos.Fixture { QSPipelineFlagsRepository() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/shared/logging/QSPipelineLoggerKosmos.kt
similarity index 69%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/shared/logging/QSPipelineLoggerKosmos.kt
index 8bb07d9..7d52f5d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/shared/logging/QSPipelineLoggerKosmos.kt
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.android.systemui.deviceentry.data.repository
+package com.android.systemui.qs.pipeline.shared.logging
 
 import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.util.mockito.mock
 
-var Kosmos.deviceEntryHapticsRepository: DeviceEntryHapticsRepository by
-    Kosmos.Fixture { fakeDeviceEntryHapticsRepository }
-val Kosmos.fakeDeviceEntryHapticsRepository by Kosmos.Fixture { FakeDeviceEntryHapticsRepository() }
+/** mock */
+var Kosmos.qsLogger: QSPipelineLogger by Kosmos.Fixture { mock<QSPipelineLogger>() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/colorcorrection/ColorCorrectionTileKosmos.kt
similarity index 68%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/colorcorrection/ColorCorrectionTileKosmos.kt
index 8bb07d9..0357036 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/colorcorrection/ColorCorrectionTileKosmos.kt
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-package com.android.systemui.deviceentry.data.repository
+package com.android.systemui.qs.tiles.impl.colorcorrection
 
+import com.android.systemui.accessibility.qs.QSAccessibilityModule
 import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.qs.qsEventLogger
 
-var Kosmos.deviceEntryHapticsRepository: DeviceEntryHapticsRepository by
-    Kosmos.Fixture { fakeDeviceEntryHapticsRepository }
-val Kosmos.fakeDeviceEntryHapticsRepository by Kosmos.Fixture { FakeDeviceEntryHapticsRepository() }
+val Kosmos.qsColorCorrectionTileConfig by
+    Kosmos.Fixture { QSAccessibilityModule.provideColorCorrectionTileConfig(qsEventLogger) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/custom/data/repository/FakeCustomTilePackageUpdatesRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/custom/data/repository/FakeCustomTilePackageUpdatesRepository.kt
index 8f972f5..18b3f47 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/custom/data/repository/FakeCustomTilePackageUpdatesRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/custom/data/repository/FakeCustomTilePackageUpdatesRepository.kt
@@ -16,17 +16,20 @@
 
 package com.android.systemui.qs.tiles.impl.custom.data.repository
 
+import android.os.UserHandle
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.map
 
 class FakeCustomTilePackageUpdatesRepository : CustomTilePackageUpdatesRepository {
 
-    private val mutablePackageChanges = MutableSharedFlow<Unit>()
+    private val mutablePackageChangesForUser = MutableSharedFlow<UserHandle>()
 
-    override val packageChanges: Flow<Unit>
-        get() = mutablePackageChanges
+    override fun getPackageChangesForUser(user: UserHandle): Flow<Unit> =
+        mutablePackageChangesForUser.filter { it == user }.map {}
 
-    suspend fun emitPackageChange() {
-        mutablePackageChanges.emit(Unit)
+    suspend fun emitPackageChange(user: UserHandle) {
+        mutablePackageChangesForUser.emit(user)
     }
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/saver/DataSaverTileKosmos.kt
similarity index 69%
rename from packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
rename to packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/saver/DataSaverTileKosmos.kt
index 8bb07d9..e9a394a 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/saver/DataSaverTileKosmos.kt
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-package com.android.systemui.deviceentry.data.repository
+package com.android.systemui.qs.tiles.impl.saver
 
 import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.qs.qsEventLogger
+import com.android.systemui.statusbar.connectivity.ConnectivityModule
 
-var Kosmos.deviceEntryHapticsRepository: DeviceEntryHapticsRepository by
-    Kosmos.Fixture { fakeDeviceEntryHapticsRepository }
-val Kosmos.fakeDeviceEntryHapticsRepository by Kosmos.Fixture { FakeDeviceEntryHapticsRepository() }
+val Kosmos.qsDataSaverTileConfig by
+    Kosmos.Fixture { ConnectivityModule.provideDataSaverTileConfig(qsEventLogger) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
index d78bcb9..0b41926 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
@@ -387,7 +387,7 @@
     }
 
     fun selectedUserInteractor(): SelectedUserInteractor {
-        return SelectedUserInteractor(userRepository, featureFlags)
+        return SelectedUserInteractor(userRepository)
     }
 
     fun bouncerActionButtonInteractor(
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt
index 7494ccf..2ca338a 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt
@@ -72,6 +72,7 @@
         onBeforeUserSwitching()
         onUserChanging()
         onUserChanged()
+        onProfileChanged()
     }
 
     fun onBeforeUserSwitching(userId: Int = _userId) {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/UserTrackerKosmos.kt
similarity index 69%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/settings/UserTrackerKosmos.kt
index 8bb07d9..ffa86ff 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/UserTrackerKosmos.kt
@@ -14,10 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.systemui.deviceentry.data.repository
+package com.android.systemui.settings
 
 import com.android.systemui.kosmos.Kosmos
 
-var Kosmos.deviceEntryHapticsRepository: DeviceEntryHapticsRepository by
-    Kosmos.Fixture { fakeDeviceEntryHapticsRepository }
-val Kosmos.fakeDeviceEntryHapticsRepository by Kosmos.Fixture { FakeDeviceEntryHapticsRepository() }
+val Kosmos.fakeUserTracker by Kosmos.Fixture { FakeUserTracker() }
+var Kosmos.userTracker: UserTracker by Kosmos.Fixture { fakeUserTracker }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/FakeShadeRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/FakeShadeRepository.kt
index 9c10848..f7005ab 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/FakeShadeRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/FakeShadeRepository.kt
@@ -18,21 +18,14 @@
 package com.android.systemui.shade.data.repository
 
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.shade.domain.model.ShadeModel
 import dagger.Binds
 import dagger.Module
 import javax.inject.Inject
-import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
 
 /** Fake implementation of [ShadeRepository] */
 @SysUISingleton
 class FakeShadeRepository @Inject constructor() : ShadeRepository {
-
-    private val _shadeModel = MutableStateFlow(ShadeModel())
-    override val shadeModel: Flow<ShadeModel> = _shadeModel
-
     private val _qsExpansion = MutableStateFlow(0f)
     override val qsExpansion = _qsExpansion
 
@@ -114,10 +107,6 @@
         _legacyIsClosing.value = isClosing
     }
 
-    fun setShadeModel(model: ShadeModel) {
-        _shadeModel.value = model
-    }
-
     override fun setQsExpansion(qsExpansion: Float) {
         _qsExpansion.value = qsExpansion
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/smartspace/data/repository/FakeSmartspaceRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/smartspace/data/repository/FakeSmartspaceRepository.kt
index c8013ef..862e52d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/smartspace/data/repository/FakeSmartspaceRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/smartspace/data/repository/FakeSmartspaceRepository.kt
@@ -10,12 +10,12 @@
 
     override val isSmartspaceRemoteViewsEnabled = smartspaceRemoteViewsEnabled
 
-    private val _lockscreenSmartspaceTargets: MutableStateFlow<List<SmartspaceTarget>> =
+    private val _communalSmartspaceTargets: MutableStateFlow<List<SmartspaceTarget>> =
         MutableStateFlow(emptyList())
-    override val lockscreenSmartspaceTargets: Flow<List<SmartspaceTarget>> =
-        _lockscreenSmartspaceTargets
+    override val communalSmartspaceTargets: Flow<List<SmartspaceTarget>> =
+        _communalSmartspaceTargets
 
-    fun setLockscreenSmartspaceTargets(targets: List<SmartspaceTarget>) {
-        _lockscreenSmartspaceTargets.value = targets
+    fun setCommunalSmartspaceTargets(targets: List<SmartspaceTarget>) {
+        _communalSmartspaceTargets.value = targets
     }
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/NotifPipelineKosmos.kt
similarity index 69%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/NotifPipelineKosmos.kt
index 8bb07d9..a48b270 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/NotifPipelineKosmos.kt
@@ -14,10 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.systemui.deviceentry.data.repository
+package com.android.systemui.statusbar.notification.collection
 
 import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.util.mockito.mock
 
-var Kosmos.deviceEntryHapticsRepository: DeviceEntryHapticsRepository by
-    Kosmos.Fixture { fakeDeviceEntryHapticsRepository }
-val Kosmos.fakeDeviceEntryHapticsRepository by Kosmos.Fixture { FakeDeviceEntryHapticsRepository() }
+var Kosmos.notifPipeline by Kosmos.Fixture { mock<NotifPipeline>() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/notifcollection/CommonNotifCollectionKosmos.kt
similarity index 69%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/notifcollection/CommonNotifCollectionKosmos.kt
index 8bb07d9..f00538e 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/notifcollection/CommonNotifCollectionKosmos.kt
@@ -14,10 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.systemui.deviceentry.data.repository
+package com.android.systemui.statusbar.notification.collection.notifcollection
 
 import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.statusbar.notification.collection.notifPipeline
 
-var Kosmos.deviceEntryHapticsRepository: DeviceEntryHapticsRepository by
-    Kosmos.Fixture { fakeDeviceEntryHapticsRepository }
-val Kosmos.fakeDeviceEntryHapticsRepository by Kosmos.Fixture { FakeDeviceEntryHapticsRepository() }
+var Kosmos.commonNotifCollection by Kosmos.Fixture { notifPipeline }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/provider/SectionStyleProviderKosmos.kt
similarity index 69%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/provider/SectionStyleProviderKosmos.kt
index 8bb07d9..e7c4085 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/provider/SectionStyleProviderKosmos.kt
@@ -14,10 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.systemui.deviceentry.data.repository
+package com.android.systemui.statusbar.notification.collection.provider
 
 import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.util.mockito.mock
 
-var Kosmos.deviceEntryHapticsRepository: DeviceEntryHapticsRepository by
-    Kosmos.Fixture { fakeDeviceEntryHapticsRepository }
-val Kosmos.fakeDeviceEntryHapticsRepository by Kosmos.Fixture { FakeDeviceEntryHapticsRepository() }
+var Kosmos.sectionStyleProvider: SectionStyleProvider by Kosmos.Fixture { mock() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationListInteractorKosmos.kt
similarity index 60%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationListInteractorKosmos.kt
index 8bb07d9..f7acae9 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationListInteractorKosmos.kt
@@ -14,10 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.systemui.deviceentry.data.repository
+package com.android.systemui.statusbar.notification.domain.interactor
 
 import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.statusbar.notification.collection.provider.sectionStyleProvider
+import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository
 
-var Kosmos.deviceEntryHapticsRepository: DeviceEntryHapticsRepository by
-    Kosmos.Fixture { fakeDeviceEntryHapticsRepository }
-val Kosmos.fakeDeviceEntryHapticsRepository by Kosmos.Fixture { FakeDeviceEntryHapticsRepository() }
+val Kosmos.renderNotificationListInteractor by
+    Kosmos.Fixture {
+        RenderNotificationListInteractor(activeNotificationListRepository, sectionStyleProvider)
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/icon/IconBuilderKosmos.kt
similarity index 69%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/icon/IconBuilderKosmos.kt
index 8bb07d9..4535652 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/icon/IconBuilderKosmos.kt
@@ -14,10 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.systemui.deviceentry.data.repository
+package com.android.systemui.statusbar.notification.icon
 
+import android.content.applicationContext
 import com.android.systemui.kosmos.Kosmos
 
-var Kosmos.deviceEntryHapticsRepository: DeviceEntryHapticsRepository by
-    Kosmos.Fixture { fakeDeviceEntryHapticsRepository }
-val Kosmos.fakeDeviceEntryHapticsRepository by Kosmos.Fixture { FakeDeviceEntryHapticsRepository() }
+val Kosmos.iconBuilder by Kosmos.Fixture { IconBuilder(applicationContext) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/icon/IconManagerKosmos.kt
similarity index 68%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/icon/IconManagerKosmos.kt
index 8bb07d9..d3a8e0c 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/icon/IconManagerKosmos.kt
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-package com.android.systemui.deviceentry.data.repository
+package com.android.systemui.statusbar.notification.icon
 
+import android.content.pm.launcherApps
 import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.statusbar.notification.collection.notifcollection.commonNotifCollection
 
-var Kosmos.deviceEntryHapticsRepository: DeviceEntryHapticsRepository by
-    Kosmos.Fixture { fakeDeviceEntryHapticsRepository }
-val Kosmos.fakeDeviceEntryHapticsRepository by Kosmos.Fixture { FakeDeviceEntryHapticsRepository() }
+val Kosmos.iconManager by
+    Kosmos.Fixture { IconManager(commonNotifCollection, launcherApps, iconBuilder) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractorKosmos.kt
index 3403227..13d577b 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractorKosmos.kt
@@ -18,6 +18,8 @@
 
 import android.content.applicationContext
 import com.android.systemui.common.ui.data.repository.configurationRepository
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryUdfpsInteractor
+import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.statusbar.policy.splitShadeStateController
 
@@ -27,5 +29,7 @@
             configurationRepository = configurationRepository,
             context = applicationContext,
             splitShadeStateController = splitShadeStateController,
+            keyguardInteractor = keyguardInteractor,
+            deviceEntryUdfpsInteractor = deviceEntryUdfpsInteractor,
         )
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationListViewBinderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationListViewBinderKosmos.kt
index 75e5aeaf..ca5b401 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationListViewBinderKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationListViewBinderKosmos.kt
@@ -26,18 +26,18 @@
 import com.android.systemui.statusbar.notification.icon.ui.viewbinder.statusBarIconViewBindingFailureTracker
 import com.android.systemui.statusbar.notification.stack.ui.viewmodel.notificationListViewModel
 import com.android.systemui.statusbar.phone.notificationIconAreaController
-import com.android.systemui.statusbar.policy.configurationController
+import com.android.systemui.statusbar.ui.systemBarUtilsState
 
 val Kosmos.notificationListViewBinder by Fixture {
     NotificationListViewBinder(
         viewModel = notificationListViewModel,
         backgroundDispatcher = testDispatcher,
         configuration = configurationState,
-        configurationController = configurationController,
         falsingManager = falsingManager,
         iconAreaController = notificationIconAreaController,
         iconViewBindingFailureTracker = statusBarIconViewBindingFailureTracker,
         metricsLogger = metricsLogger,
         shelfIconViewStore = shelfNotificationIconViewStore,
+        systemBarUtilsState = systemBarUtilsState,
     )
 }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsLottieViewWrapper.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/ui/FakeSystemBarUtilsProxy.kt
similarity index 66%
copy from packages/SystemUI/src/com/android/systemui/biometrics/SideFpsLottieViewWrapper.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/ui/FakeSystemBarUtilsProxy.kt
index e98f6db..d38baba 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsLottieViewWrapper.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/ui/FakeSystemBarUtilsProxy.kt
@@ -13,12 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.systemui.biometrics
 
-import android.content.Context
-import android.util.AttributeSet
-import com.android.systemui.util.wrapper.LottieViewWrapper
+package com.android.systemui.statusbar.ui
 
-class SideFpsLottieViewWrapper
-@JvmOverloads
-constructor(context: Context, attrs: AttributeSet? = null) : LottieViewWrapper(context, attrs)
+class FakeSystemBarUtilsProxy(private var statusBarHeight: Int) : SystemBarUtilsProxy {
+    override fun getStatusBarHeight(): Int = statusBarHeight
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/ui/SystemBarUtilsProxyKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/ui/SystemBarUtilsProxyKosmos.kt
new file mode 100644
index 0000000..f24037d
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/ui/SystemBarUtilsProxyKosmos.kt
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.ui
+
+import android.content.applicationContext
+import android.content.res.mainResources
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.res.R
+
+/**
+ * Main fixture for supplying a [SystemBarUtilsProxy]. Should be used by other fixtures. Unless
+ * overridden in the test, this by default uses [fakeSystemBarUtilsProxy].
+ */
+var Kosmos.systemBarUtilsProxy: SystemBarUtilsProxy by Fixture { fakeSystemBarUtilsProxy }
+
+/**
+ * Fixture supplying a real [SystemBarUtilsProxyImpl] instance, for use by tests that want to use
+ * the real device logic to determine system bar properties. Note this this real instance does *not*
+ * support Robolectric tests; by opting in, you are explicitly opting-out of using Robolectric.
+ *
+ * By default, this fixture is unused; tests should override [systemBarUtilsProxy] in order to
+ * utilize this fixture:
+ * ```kotlin
+ *   val kosmos = Kosmos()
+ *   kosmos.systemBarUtilsProxy = kosmos.systemBarUtilsProxyImpl
+ * ```
+ */
+val Kosmos.systemBarUtilsProxyImpl by Fixture { SystemBarUtilsProxyImpl(applicationContext) }
+
+/**
+ * Fixture supplying a shared [FakeSystemBarUtilsProxy] instance. Can be accessed or overridden in
+ * tests in order to provide custom results.
+ */
+var Kosmos.fakeSystemBarUtilsProxy by Fixture {
+    FakeSystemBarUtilsProxy(mainResources.getDimensionPixelSize(R.dimen.status_bar_height))
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/ui/SystemBarUtilsStateKosmos.kt
similarity index 69%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/ui/SystemBarUtilsStateKosmos.kt
index 8bb07d9..e208add 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/DeviceEntryHapticsRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/ui/SystemBarUtilsStateKosmos.kt
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.android.systemui.deviceentry.data.repository
+package com.android.systemui.statusbar.ui
 
 import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.statusbar.policy.configurationController
 
-var Kosmos.deviceEntryHapticsRepository: DeviceEntryHapticsRepository by
-    Kosmos.Fixture { fakeDeviceEntryHapticsRepository }
-val Kosmos.fakeDeviceEntryHapticsRepository by Kosmos.Fixture { FakeDeviceEntryHapticsRepository() }
+val Kosmos.systemBarUtilsState by
+    Kosmos.Fixture { SystemBarUtilsState(configurationController, systemBarUtilsProxy) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/user/domain/interactor/SelectedUserInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/user/domain/interactor/SelectedUserInteractorKosmos.kt
index 427f92a..89672f1 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/user/domain/interactor/SelectedUserInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/user/domain/interactor/SelectedUserInteractorKosmos.kt
@@ -16,9 +16,7 @@
 
 package com.android.systemui.user.domain.interactor
 
-import com.android.systemui.flags.featureFlagsClassic
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.user.data.repository.userRepository
 
-val Kosmos.selectedUserInteractor by
-    Kosmos.Fixture { SelectedUserInteractor(userRepository, featureFlagsClassic) }
+val Kosmos.selectedUserInteractor by Kosmos.Fixture { SelectedUserInteractor(userRepository) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeDataSaverController.java b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeDataSaverController.java
index 886722e..bade848 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeDataSaverController.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeDataSaverController.java
@@ -19,19 +19,38 @@
 import com.android.systemui.statusbar.policy.DataSaverController;
 import com.android.systemui.statusbar.policy.DataSaverController.Listener;
 
+import java.util.ArrayList;
+import java.util.List;
+
 public class FakeDataSaverController extends BaseLeakChecker<Listener> implements DataSaverController {
 
+    private boolean mIsEnabled = false;
+    private List<Listener> mListeners = new ArrayList<>();
+
     public FakeDataSaverController(LeakCheck test) {
         super(test, "datasaver");
     }
 
     @Override
     public boolean isDataSaverEnabled() {
-        return false;
+        return mIsEnabled;
     }
 
     @Override
     public void setDataSaverEnabled(boolean enabled) {
+        mIsEnabled = enabled;
+        for (Listener listener: mListeners) {
+            listener.onDataSaverChanged(enabled);
+        }
+    }
 
+    @Override
+    public void addCallback(Listener listener) {
+        mListeners.add(listener);
+    }
+
+    @Override
+    public void removeCallback(Listener listener) {
+        mListeners.remove(listener);
     }
 }
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values-sw600dp/config.xml b/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values-sw600dp/config.xml
deleted file mode 100644
index be1f081..0000000
--- a/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values-sw600dp/config.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * Copyright (c) 2023, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
--->
-<resources>
-    <!-- If true, attach the navigation bar to the app during app transition -->
-    <bool name="config_attachNavBarToAppDuringTransition">false</bool>
-</resources>
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values-sw600dp/config.xml b/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values-sw600dp/config.xml
deleted file mode 100644
index be1f081..0000000
--- a/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values-sw600dp/config.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * Copyright (c) 2023, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
--->
-<resources>
-    <!-- If true, attach the navigation bar to the app during app transition -->
-    <bool name="config_attachNavBarToAppDuringTransition">false</bool>
-</resources>
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values-sw600dp/config.xml b/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values-sw600dp/config.xml
deleted file mode 100644
index be1f081..0000000
--- a/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values-sw600dp/config.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * Copyright (c) 2023, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
--->
-<resources>
-    <!-- If true, attach the navigation bar to the app during app transition -->
-    <bool name="config_attachNavBarToAppDuringTransition">false</bool>
-</resources>
diff --git a/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java b/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java
index b315f4a..7fcef9c 100644
--- a/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java
+++ b/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java
@@ -76,6 +76,7 @@
 import android.view.Surface;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.camera.extensions.impl.AutoImageCaptureExtenderImpl;
 import androidx.camera.extensions.impl.AutoPreviewExtenderImpl;
 import androidx.camera.extensions.impl.BeautyImageCaptureExtenderImpl;
@@ -94,6 +95,7 @@
 import androidx.camera.extensions.impl.PreviewExtenderImpl.ProcessorType;
 import androidx.camera.extensions.impl.PreviewImageProcessorImpl;
 import androidx.camera.extensions.impl.ProcessResultImpl;
+import androidx.camera.extensions.impl.ProcessorImpl;
 import androidx.camera.extensions.impl.RequestUpdateProcessorImpl;
 import androidx.camera.extensions.impl.advanced.AdvancedExtenderImpl;
 import androidx.camera.extensions.impl.advanced.AutoAdvancedExtenderImpl;
@@ -101,6 +103,7 @@
 import androidx.camera.extensions.impl.advanced.BokehAdvancedExtenderImpl;
 import androidx.camera.extensions.impl.advanced.Camera2OutputConfigImpl;
 import androidx.camera.extensions.impl.advanced.Camera2SessionConfigImpl;
+import androidx.camera.extensions.impl.advanced.EyesFreeVideographyAdvancedExtenderImpl;
 import androidx.camera.extensions.impl.advanced.HdrAdvancedExtenderImpl;
 import androidx.camera.extensions.impl.advanced.ImageProcessorImpl;
 import androidx.camera.extensions.impl.advanced.ImageReaderOutputConfigImpl;
@@ -112,6 +115,8 @@
 import androidx.camera.extensions.impl.advanced.SessionProcessorImpl;
 import androidx.camera.extensions.impl.advanced.SurfaceOutputConfigImpl;
 
+import com.android.internal.camera.flags.Flags;
+
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -135,22 +140,28 @@
     private static final String RESULTS_VERSION_PREFIX = "1.3";
     // Support for various latency improvements
     private static final String LATENCY_VERSION_PREFIX = "1.4";
-    private static final String[] ADVANCED_VERSION_PREFIXES = {LATENCY_VERSION_PREFIX,
-            ADVANCED_VERSION_PREFIX, RESULTS_VERSION_PREFIX };
-    private static final String[] SUPPORTED_VERSION_PREFIXES = {LATENCY_VERSION_PREFIX,
-            RESULTS_VERSION_PREFIX, ADVANCED_VERSION_PREFIX, "1.1", NON_INIT_VERSION_PREFIX};
+    private static final String EFV_VERSION_PREFIX = "1.5";
+    private static final String[] ADVANCED_VERSION_PREFIXES = {EFV_VERSION_PREFIX,
+            LATENCY_VERSION_PREFIX, ADVANCED_VERSION_PREFIX, RESULTS_VERSION_PREFIX };
+    private static final String[] SUPPORTED_VERSION_PREFIXES = {EFV_VERSION_PREFIX,
+            LATENCY_VERSION_PREFIX, RESULTS_VERSION_PREFIX, ADVANCED_VERSION_PREFIX, "1.1",
+            NON_INIT_VERSION_PREFIX};
     private static final boolean EXTENSIONS_PRESENT = checkForExtensions();
     private static final String EXTENSIONS_VERSION = EXTENSIONS_PRESENT ?
             (new ExtensionVersionImpl()).checkApiVersion(LATEST_VERSION) : null;
     private static final boolean ESTIMATED_LATENCY_API_SUPPORTED = checkForLatencyAPI();
     private static final boolean LATENCY_IMPROVEMENTS_SUPPORTED = EXTENSIONS_PRESENT &&
-            (EXTENSIONS_VERSION.startsWith(LATENCY_VERSION_PREFIX));
+            (EXTENSIONS_VERSION.startsWith(LATENCY_VERSION_PREFIX) ||
+                    (EXTENSIONS_VERSION.startsWith(EFV_VERSION_PREFIX)));
+    private static final boolean EFV_SUPPORTED = EXTENSIONS_PRESENT &&
+            (EXTENSIONS_VERSION.startsWith(EFV_VERSION_PREFIX));
     private static final boolean ADVANCED_API_SUPPORTED = checkForAdvancedAPI();
     private static final boolean INIT_API_SUPPORTED = EXTENSIONS_PRESENT &&
             (!EXTENSIONS_VERSION.startsWith(NON_INIT_VERSION_PREFIX));
     private static final boolean RESULT_API_SUPPORTED = EXTENSIONS_PRESENT &&
             (EXTENSIONS_VERSION.startsWith(RESULTS_VERSION_PREFIX) ||
-            EXTENSIONS_VERSION.startsWith(LATENCY_VERSION_PREFIX));
+            EXTENSIONS_VERSION.startsWith(LATENCY_VERSION_PREFIX) ||
+            EXTENSIONS_VERSION.startsWith(EFV_VERSION_PREFIX));
 
     private HashMap<String, Long> mMetadataVendorIdMap = new HashMap<>();
     private CameraManager mCameraManager;
@@ -509,6 +520,167 @@
      */
     public static Pair<PreviewExtenderImpl, ImageCaptureExtenderImpl> initializeExtension(
             int extensionType) {
+        if (Flags.concertMode()) {
+            if (extensionType == CameraExtensionCharacteristics.EXTENSION_EYES_FREE_VIDEOGRAPHY) {
+                // Basic extensions are deprecated starting with extension version 1.5
+                return new Pair<>(new PreviewExtenderImpl() {
+                    @Override
+                    public boolean isExtensionAvailable(String cameraId,
+                            CameraCharacteristics cameraCharacteristics) {
+                        return false;
+                    }
+
+                    @Override
+                    public void init(String cameraId, CameraCharacteristics cameraCharacteristics) {
+
+                    }
+
+                    @Override
+                    public androidx.camera.extensions.impl.CaptureStageImpl getCaptureStage() {
+                        return null;
+                    }
+
+                    @Override
+                    public ProcessorType getProcessorType() {
+                        return null;
+                    }
+
+                    @Override
+                    public ProcessorImpl getProcessor() {
+                        return null;
+                    }
+
+                    @Nullable
+                    @Override
+                    public List<Pair<Integer, Size[]>> getSupportedResolutions() {
+                        return null;
+                    }
+
+                    @Override
+                    public void onInit(String cameraId, CameraCharacteristics cameraCharacteristics,
+                            Context context) { }
+
+                    @Override
+                    public void onDeInit() { }
+
+                    @Override
+                    public androidx.camera.extensions.impl.CaptureStageImpl onPresetSession() {
+                        return null;
+                    }
+
+                    @Override
+                    public androidx.camera.extensions.impl.CaptureStageImpl onEnableSession() {
+                        return null;
+                    }
+
+                    @Override
+                    public androidx.camera.extensions.impl.CaptureStageImpl onDisableSession() {
+                        return null;
+                    }
+
+                    @Override
+                    public int onSessionType() {
+                        return 0;
+                    }
+                }, new ImageCaptureExtenderImpl() {
+                    @Override
+                    public boolean isExtensionAvailable(String cameraId,
+                            CameraCharacteristics cameraCharacteristics) {
+                        return false;
+                    }
+
+                    @Override
+                    public void init(String cameraId,
+                            CameraCharacteristics cameraCharacteristics) { }
+
+                    @Override
+                    public CaptureProcessorImpl getCaptureProcessor() {
+                        return null;
+                    }
+
+                    @Override
+                    public
+                    List<androidx.camera.extensions.impl.CaptureStageImpl> getCaptureStages() {
+                        return null;
+                    }
+
+                    @Override
+                    public int getMaxCaptureStage() {
+                        return 0;
+                    }
+
+                    @Override
+                    public List<Pair<Integer, Size[]>> getSupportedResolutions() {
+                        return null;
+                    }
+
+                    @Override
+                    public List<Pair<Integer, Size[]>> getSupportedPostviewResolutions(
+                            Size captureSize) {
+                        return null;
+                    }
+
+                    @Override
+                    public Range<Long> getEstimatedCaptureLatencyRange(
+                            Size captureOutputSize) {
+                        return null;
+                    }
+
+                    @Override
+                    public List<CaptureRequest.Key> getAvailableCaptureRequestKeys() {
+                        return null;
+                    }
+
+                    @Override
+                    public List<CaptureResult.Key> getAvailableCaptureResultKeys() {
+                        return null;
+                    }
+
+                    @Override
+                    public boolean isCaptureProcessProgressAvailable() {
+                        return false;
+                    }
+
+                    @Override
+                    public Pair<Long, Long> getRealtimeCaptureLatency() {
+                        return null;
+                    }
+
+                    @Override
+                    public boolean isPostviewAvailable() {
+                        return false;
+                    }
+
+                    @Override
+                    public void onInit(String cameraId,
+                            CameraCharacteristics cameraCharacteristics, Context context) { }
+
+                    @Override
+                    public void onDeInit() { }
+
+                    @Override
+                    public androidx.camera.extensions.impl.CaptureStageImpl onPresetSession() {
+                        return null;
+                    }
+
+                    @Override
+                    public androidx.camera.extensions.impl.CaptureStageImpl onEnableSession() {
+                        return null;
+                    }
+
+                    @Override
+                    public androidx.camera.extensions.impl.CaptureStageImpl onDisableSession() {
+                        return null;
+                    }
+
+                    @Override
+                    public int onSessionType() {
+                        return 0;
+                    }
+                });
+            }
+        }
+
         switch (extensionType) {
             case CameraExtensionCharacteristics.EXTENSION_AUTOMATIC:
                 return new Pair<>(new AutoPreviewExtenderImpl(),
@@ -533,6 +705,82 @@
      * @hide
      */
     public static AdvancedExtenderImpl initializeAdvancedExtensionImpl(int extensionType) {
+        if (Flags.concertMode()) {
+            if (extensionType == CameraExtensionCharacteristics.EXTENSION_EYES_FREE_VIDEOGRAPHY) {
+                if (EFV_SUPPORTED) {
+                    return new EyesFreeVideographyAdvancedExtenderImpl();
+                } else {
+                    return new AdvancedExtenderImpl() {
+                        @Override
+                        public boolean isExtensionAvailable(String cameraId,
+                                Map<String, CameraCharacteristics> characteristicsMap) {
+                            return false;
+                        }
+
+                        @Override
+                        public void init(String cameraId,
+                                Map<String, CameraCharacteristics> characteristicsMap) {
+
+                        }
+
+                        @Override
+                        public Range<Long> getEstimatedCaptureLatencyRange(String cameraId,
+                                Size captureOutputSize, int imageFormat) {
+                            return null;
+                        }
+
+                        @Override
+                        public Map<Integer, List<Size>> getSupportedPreviewOutputResolutions(
+                                String cameraId) {
+                            return null;
+                        }
+
+                        @Override
+                        public Map<Integer, List<Size>> getSupportedCaptureOutputResolutions(
+                                String cameraId) {
+                            return null;
+                        }
+
+                        @Override
+                        public Map<Integer, List<Size>> getSupportedPostviewResolutions(
+                                Size captureSize) {
+                            return null;
+                        }
+
+                        @Override
+                        public List<Size> getSupportedYuvAnalysisResolutions(String cameraId) {
+                            return null;
+                        }
+
+                        @Override
+                        public SessionProcessorImpl createSessionProcessor() {
+                            return null;
+                        }
+
+                        @Override
+                        public List<CaptureRequest.Key> getAvailableCaptureRequestKeys() {
+                            return null;
+                        }
+
+                        @Override
+                        public List<CaptureResult.Key> getAvailableCaptureResultKeys() {
+                            return null;
+                        }
+
+                        @Override
+                        public boolean isCaptureProcessProgressAvailable() {
+                            return false;
+                        }
+
+                        @Override
+                        public boolean isPostviewAvailable() {
+                            return false;
+                        }
+                    };
+                }
+            }
+        }
+
         switch (extensionType) {
             case CameraExtensionCharacteristics.EXTENSION_AUTOMATIC:
                 return new AutoAdvancedExtenderImpl();
diff --git a/ravenwood/api-maintainers.md b/ravenwood/api-maintainers.md
index 30e899c..d84cb67 100644
--- a/ravenwood/api-maintainers.md
+++ b/ravenwood/api-maintainers.md
@@ -71,3 +71,24 @@
 The “replace” strategy described above is quite powerful, and can be used in creative ways to sidestep tricky underlying dependencies that aren’t ready yet.
 
 For example, consider a constructor or static initializer that relies on unsupported functionality from another team.  By factoring the unsupported logic into a dedicated method, that method can then be replaced under Ravenwood to offer baseline functionality.
+
+## Strategies for JNI
+
+At the moment, JNI isn't yet supported under Ravenwood, but you may still want to support APIs that are partially implemented with JNI.  The current approach is to use the “replace” strategy to offer a pure-Java alternative implementation for any JNI-provided logic.
+
+Since this approach requires potentially complex re-implementation, it should only be considered for core infrastructure that is critical to unblocking widespread testing use-cases.  Other less-common usages of JNI should instead wait for offical JNI support in the Ravenwood environment.
+
+When a pure-Java implementation grows too large or complex to host within the original class, the `@RavenwoodNativeSubstitutionClass` annotation can be used to host it in a separate source file:
+
+```
+@RavenwoodKeepWholeClass
+@RavenwoodNativeSubstitutionClass("com.android.hoststubgen.nativesubstitution.MyComplexClass_host")
+public class MyComplexClass {
+    private static native void nativeDoThing(long nativePtr);
+...
+
+public class MyComplexClass_host {
+    public static void nativeDoThing(long nativePtr) {
+        // ...
+    }
+```
diff --git a/ravenwood/framework-minus-apex-ravenwood-policies.txt b/ravenwood/framework-minus-apex-ravenwood-policies.txt
index 6a6ae38..f5e4af5 100644
--- a/ravenwood/framework-minus-apex-ravenwood-policies.txt
+++ b/ravenwood/framework-minus-apex-ravenwood-policies.txt
@@ -3,6 +3,9 @@
 # Keep all AIDL interfaces
 class :aidl stubclass
 
+# Keep all feature flag implementations
+class :feature_flags stubclass
+
 # Collections
 class android.util.ArrayMap stubclass
 class android.util.ArraySet stubclass
@@ -74,6 +77,7 @@
 class android.util.proto.WireTypeMismatchException stubclass
 
 # Misc
+class android.util.BackupUtils stubclass
 class android.util.Dumpable stubclass
 class android.util.DebugUtils stubclass
 class android.util.MathUtils stubclass
@@ -81,15 +85,11 @@
 class android.util.UtilConfig stubclass
 
 # Internals
-class com.android.internal.util.FastMath stubclass
-class com.android.internal.util.FastPrintWriter stubclass
-class com.android.internal.util.GrowingArrayUtils stubclass
-class com.android.internal.util.LineBreakBufferedWriter stubclass
-class com.android.internal.util.Parcelling stubclass
+class com.android.internal.util.FileRotator stubclass
+class com.android.internal.util.HexDump stubclass
+class com.android.internal.util.MessageUtils stubclass
 class com.android.internal.util.Preconditions stubclass
-class com.android.internal.util.StringPool stubclass
-
-class com.android.internal.os.SomeArgs stubclass
+class com.android.internal.util.TokenBucket stubclass
 
 # Parcel
 class android.os.ParcelFormatException stubclass
diff --git a/ravenwood/junit-src/android/platform/test/annotations/IgnoreUnderRavenwood.java b/ravenwood/junit-src/android/platform/test/annotations/IgnoreUnderRavenwood.java
index edb0442..916dd59 100644
--- a/ravenwood/junit-src/android/platform/test/annotations/IgnoreUnderRavenwood.java
+++ b/ravenwood/junit-src/android/platform/test/annotations/IgnoreUnderRavenwood.java
@@ -36,7 +36,7 @@
  *
  * @hide
  */
-@Target(ElementType.METHOD)
+@Target({ElementType.METHOD, ElementType.TYPE})
 @Retention(RetentionPolicy.RUNTIME)
 public @interface IgnoreUnderRavenwood {
     /**
diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java
index 9db5b98..513c095 100644
--- a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java
+++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java
@@ -16,6 +16,8 @@
 
 package android.platform.test.ravenwood;
 
+import static org.junit.Assert.fail;
+
 import android.platform.test.annotations.IgnoreUnderRavenwood;
 
 import org.junit.Assume;
@@ -36,6 +38,15 @@
 
     private static final boolean IS_UNDER_RAVENWOOD = RavenwoodRuleImpl.isUnderRavenwood();
 
+    /**
+     * When probing is enabled, all tests will be unconditionally run under Ravenwood to detect
+     * cases where a test is able to pass despite being marked as {@code IgnoreUnderRavenwood}.
+     *
+     * This is typically helpful for internal maintainers discovering tests that had previously
+     * been ignored, but now have enough Ravenwood-supported functionality to be enabled.
+     */
+    private static final boolean ENABLE_PROBE_IGNORED = false; // DO NOT SUBMIT WITH TRUE
+
     private static final int SYSTEM_UID = 1000;
     private static final int NOBODY_UID = 9999;
     private static final int FIRST_APPLICATION_UID = 10000;
@@ -93,27 +104,80 @@
     /**
      * Return if the current process is running under a Ravenwood test environment.
      */
-    public boolean isUnderRavenwood() {
+    public static boolean isUnderRavenwood() {
         return IS_UNDER_RAVENWOOD;
     }
 
+    /**
+     * Test if the given {@link Description} has been marked with an {@link IgnoreUnderRavenwood}
+     * annotation, either at the method or class level.
+     */
+    private static boolean hasIgnoreUnderRavenwoodAnnotation(Description description) {
+        if (description.getTestClass().getAnnotation(IgnoreUnderRavenwood.class) != null) {
+            return true;
+        } else if (description.getAnnotation(IgnoreUnderRavenwood.class) != null) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
     @Override
     public Statement apply(Statement base, Description description) {
+        if (ENABLE_PROBE_IGNORED) {
+            return applyProbeIgnored(base, description);
+        } else {
+            return applyDefault(base, description);
+        }
+    }
+
+    /**
+     * Run the given {@link Statement} with no special treatment.
+     */
+    private Statement applyDefault(Statement base, Description description) {
         return new Statement() {
             @Override
             public void evaluate() throws Throwable {
-                if (description.getAnnotation(IgnoreUnderRavenwood.class) != null) {
+                if (hasIgnoreUnderRavenwoodAnnotation(description)) {
                     Assume.assumeFalse(IS_UNDER_RAVENWOOD);
                 }
-                if (IS_UNDER_RAVENWOOD) {
-                    RavenwoodRuleImpl.init(RavenwoodRule.this);
-                }
+
+                RavenwoodRuleImpl.init(RavenwoodRule.this);
                 try {
                     base.evaluate();
                 } finally {
-                    if (IS_UNDER_RAVENWOOD) {
-                        RavenwoodRuleImpl.reset(RavenwoodRule.this);
+                    RavenwoodRuleImpl.reset(RavenwoodRule.this);
+                }
+            }
+        };
+    }
+
+    /**
+     * Run the given {@link Statement} with probing enabled. All tests will be unconditionally
+     * run under Ravenwood to detect cases where a test is able to pass despite being marked as
+     * {@code IgnoreUnderRavenwood}.
+     */
+    private Statement applyProbeIgnored(Statement base, Description description) {
+        return new Statement() {
+            @Override
+            public void evaluate() throws Throwable {
+                RavenwoodRuleImpl.init(RavenwoodRule.this);
+                try {
+                    base.evaluate();
+                } catch (Throwable t) {
+                    if (hasIgnoreUnderRavenwoodAnnotation(description)) {
+                        // This failure is expected, so eat the exception and report the
+                        // assumption failure that test authors expect
+                        Assume.assumeFalse(IS_UNDER_RAVENWOOD);
                     }
+                    throw t;
+                } finally {
+                    RavenwoodRuleImpl.reset(RavenwoodRule.this);
+                }
+
+                if (hasIgnoreUnderRavenwoodAnnotation(description) && IS_UNDER_RAVENWOOD) {
+                    fail("Test was annotated with IgnoreUnderRavenwood, but it actually "
+                            + "passed under Ravenwood; consider removing the annotation");
                 }
             }
         };
diff --git a/ravenwood/junit-stub-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java b/ravenwood/junit-stub-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java
index fb71e9d..0ff6a1a 100644
--- a/ravenwood/junit-stub-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java
+++ b/ravenwood/junit-stub-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java
@@ -22,12 +22,10 @@
     }
 
     public static void init(RavenwoodRule rule) {
-        // Must be provided by impl to reference runtime internals
-        throw new UnsupportedOperationException();
+        // No-op when running on a real device
     }
 
     public static void reset(RavenwoodRule rule) {
-        // Must be provided by impl to reference runtime internals
-        throw new UnsupportedOperationException();
+        // No-op when running on a real device
     }
 }
diff --git a/ravenwood/ravenwood-annotation-allowed-classes.txt b/ravenwood/ravenwood-annotation-allowed-classes.txt
index 468b7c9..13908f1 100644
--- a/ravenwood/ravenwood-annotation-allowed-classes.txt
+++ b/ravenwood/ravenwood-annotation-allowed-classes.txt
@@ -1,19 +1,47 @@
 # Only classes listed here can use the Ravenwood annotations.
 
 com.android.internal.util.ArrayUtils
+com.android.internal.os.BatteryStatsHistory
+com.android.internal.os.BatteryStatsHistory$TraceDelegate
+com.android.internal.os.BatteryStatsHistory$VarintParceler
+com.android.internal.os.BatteryStatsHistoryIterator
+com.android.internal.os.Clock
+com.android.internal.os.LongArrayMultiStateCounter
+com.android.internal.os.LongArrayMultiStateCounter$LongArrayContainer
+com.android.internal.os.MonotonicClock
+com.android.internal.os.PowerStats
+com.android.internal.os.PowerStats$Descriptor
 
 android.util.AtomicFile
 android.util.DataUnit
+android.util.DayOfMonthCursor
+android.util.DumpableContainer
 android.util.EventLog
 android.util.IntArray
+android.util.KeyValueListParser
 android.util.LongArray
+android.util.LongArrayQueue
+android.util.LongSparseLongArray
 android.util.LruCache
+android.util.MonthDisplayHelper
+android.util.RecurrenceRule
+android.util.RotationUtils
 android.util.Slog
+android.util.SparseDoubleArray
+android.util.SparseSetArray
 android.util.TimeUtils
 android.util.Xml
 
+android.os.BatteryConsumer
+android.os.BatteryStats$HistoryItem
+android.os.BatteryStats$HistoryStepDetails
+android.os.BatteryStats$HistoryTag
+android.os.BatteryStats$ProcessStateChange
 android.os.Binder
 android.os.Binder$IdentitySupplier
+android.os.Broadcaster
+android.os.BundleMerger
+android.os.ConditionVariable
 android.os.FileUtils
 android.os.FileUtils$MemoryPipe
 android.os.Handler
@@ -23,12 +51,15 @@
 android.os.Looper
 android.os.Message
 android.os.MessageQueue
+android.os.PackageTagsList
 android.os.Parcel
 android.os.Parcelable
 android.os.Process
 android.os.SystemClock
 android.os.ThreadLocalWorkSource
+android.os.TimestampedValue
 android.os.UserHandle
+android.os.WorkSource
 
 android.content.ClipData
 android.content.ClipData$Item
@@ -78,4 +109,48 @@
 android.graphics.Rect
 android.graphics.RectF
 
+android.content.ContentProvider
+
 com.android.server.LocalServices
+
+com.android.internal.util.BitUtils
+com.android.internal.util.BitwiseInputStream
+com.android.internal.util.BitwiseOutputStream
+com.android.internal.util.CallbackRegistry
+com.android.internal.util.DumpableContainer
+com.android.internal.util.dump.DumpableContainerImpl
+com.android.internal.util.DumpUtils
+com.android.internal.util.FastMath
+com.android.internal.util.FastPrintWriter
+com.android.internal.util.FileRotator
+com.android.internal.util.GrowingArrayUtils
+com.android.internal.util.HeavyHitterSketch
+com.android.internal.util.LineBreakBufferedWriter
+com.android.internal.util.ObjectUtils
+com.android.internal.util.Parcelling
+com.android.internal.util.ParseUtils
+com.android.internal.util.ProcFileReader
+com.android.internal.util.QuickSelect
+com.android.internal.util.RingBuffer
+com.android.internal.util.StringPool
+
+com.android.internal.os.BinderCallHeavyHitterWatcher
+com.android.internal.os.BinderDeathDispatcher
+com.android.internal.os.BinderfsStatsReader
+com.android.internal.os.BinderLatencyBuckets
+com.android.internal.os.CachedDeviceState
+com.android.internal.os.Clock
+com.android.internal.os.CpuScalingPolicies
+com.android.internal.os.CpuScalingPolicyReader
+com.android.internal.os.KernelCpuThreadReader
+com.android.internal.os.LoggingPrintStream
+com.android.internal.os.LooperStats
+com.android.internal.os.MonotonicClock
+com.android.internal.os.ProcLocksReader
+com.android.internal.os.ProcStatsUtil
+com.android.internal.os.SomeArgs
+com.android.internal.os.StoragedUidIoStatsReader
+
+com.google.android.collect.Lists
+com.google.android.collect.Maps
+com.google.android.collect.Sets
diff --git a/ravenwood/test-authors.md b/ravenwood/test-authors.md
index 5adef53..5df827f 100644
--- a/ravenwood/test-authors.md
+++ b/ravenwood/test-authors.md
@@ -71,10 +71,10 @@
 Once you’ve defined your test, you can use typical commands to execute it locally:
 
 ```
-$ atest MyTestsRavenwood
+$ atest --host MyTestsRavenwood
 ```
 
-> **Note:** There's a known bug where `atest` currently requires a connected device to run Ravenwood tests, but that device isn't used for testing.
+> **Note:** There's a known bug #312525698 where `atest` currently requires a connected device to run Ravenwood tests, but that device isn't used for testing. Using the `--host` argument above is a way to bypass this requirement until the bug is fixed.
 
 You can also run your new tests automatically via `TEST_MAPPING` rules like this:
 
@@ -89,11 +89,34 @@
 }
 ```
 
+> **Note:** There's a known bug #308854804 where `TEST_MAPPING` is not being applied, so we're currently planning to run all Ravenwood tests unconditionally in presubmit for changes to `frameworks/base/` and `cts/` until there is a better path forward.
+
+## Strategies for feature flags
+
+Ravenwood supports writing tests against logic that uses feature flags through the existing `SetFlagsRule` infrastructure maintained by the feature flagging team:
+
+```
+import android.platform.test.flag.junit.SetFlagsRule;
+
+@RunWith(AndroidJUnit4.class)
+public class MyCodeTest {
+    @Rule
+    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
+    @Test
+    public void testEnabled() {
+        mSetFlagsRule.enableFlags(Flags.FLAG_MY_FLAG);
+        // verify test logic that depends on flag being enabled
+    }
+```
+
+This naturally composes together well with any `RavenwoodRule` that your test may need.
+
 ## Strategies for migration/bivalent tests
 
-Ravenwood aims to support tests that are written in a “bivalent” way, where the same test code can run on both a real Android device and under a Ravenwood environment.
+Ravenwood aims to support tests that are written in a “bivalent” way, where the same test code can be dual-compiled to run on both a real Android device and under a Ravenwood environment.
 
-In situations where a test method depends on API functionality not yet available under Ravenwood, we provide an annotation to quietly “ignore” that test under Ravenwood, while continuing to validate that test on real devices.  Please note that your test must declare a `RavenwoodRule` for the annotation to take effect.
+In situations where a test method depends on API functionality not yet available under Ravenwood, we provide an annotation to quietly “ignore” that test under Ravenwood, while continuing to validate that test on real devices.  The annotation can be applied to either individual methods or to an entire test class.  Please note that your test class must declare a `RavenwoodRule` for the annotation to take effect.
 
 Test authors are encouraged to provide a `blockedBy` or `reason` argument to help future maintainers understand why a test is being ignored, and under what conditions it might be supported in the future.
 
@@ -116,11 +139,39 @@
 }
 ```
 
+At the moment, the `android.content.res.Resources` subsystem isn't yet supported under Ravenwood, but you may still want to dual-compile test suites that depend on references to resources.  Below is a strategy for supporting dual-compiliation, where you can "borrow" the generated resource symbols from your traditional `android_test` target:
+
+```
+android_test {
+    name: "MyTestsDevice",
+    resource_dirs: ["res"],
+...
+
+android_ravenwood_test {
+    name: "MyTestsRavenwood",
+    srcs: [
+        ":MyTestsDevice{.aapt.srcjar}",
+...
+```
+
 ## Strategies for unsupported APIs
 
 As you write tests against Ravenwood, you’ll likely discover API dependencies that aren’t supported yet.  Here’s a few strategies that can help you make progress:
 
-* Your code-under-test may benefit from subtle dependency refactoring to reduce coupling.  (For example, providing a specific `File` argument instead of deriving it internally from a `Context`.)
+* Your code-under-test may benefit from subtle dependency refactoring to reduce coupling.  (For example, providing a specific `File` argument instead of deriving paths internally from a `Context` or `Environment`.)
+    * One common use-case is providing a directory for your test to store temporary files, which can easily be accomplished using the `Files.createTempDirectory()` API which works on both physical devices and under Ravenwood:
+
+```
+import java.nio.file.Files;
+
+@RunWith(AndroidJUnit4.class)
+public class MyTest {
+    @Before
+    public void setUp() throws Exception {
+        File tempDir = Files.createTempDirectory("MyTest").toFile();
+...
+```
+
 * Although mocking code that your team doesn’t own is a generally discouraged testing practice, it can be a valuable pressure relief valve when a dependency isn’t yet supported.
 
 ## Strategies for debugging test development
diff --git a/services/accessibility/Android.bp b/services/accessibility/Android.bp
index e9bb763..e2488a5 100644
--- a/services/accessibility/Android.bp
+++ b/services/accessibility/Android.bp
@@ -19,6 +19,9 @@
     defaults: [
         "platform_service_defaults",
     ],
+    lint: {
+        error_checks: ["MissingPermissionAnnotation"],
+    },
     srcs: [
         ":services.accessibility-sources",
         "//frameworks/base/packages/SettingsLib/RestrictedLockUtils:SettingsLibRestrictedLockUtilsSrc",
@@ -32,6 +35,22 @@
     ],
 }
 
+java_library_static {
+    name: "AccessibilityGestureUtils",
+    srcs: [
+        "java/**/gestures/GestureMatcher.java",
+        "java/**/gestures/GestureManifold.java",
+        "java/**/gestures/MultiFingerMultiTap.java",
+        "java/**/gestures/TouchState.java",
+    ],
+    static_libs: [
+        "services.accessibility",
+    ],
+    libs: [
+        "androidx.annotation_annotation",
+    ],
+}
+
 aconfig_declarations {
     name: "com_android_server_accessibility_flags",
     package: "com.android.server.accessibility",
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index 7187895..1d73843 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -118,6 +118,7 @@
  * This class represents an accessibility client - either an AccessibilityService or a UiAutomation.
  * It is responsible for behavior common to both types of clients.
  */
+@SuppressWarnings("MissingPermissionAnnotation")
 abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServiceConnection.Stub
         implements ServiceConnection, IBinder.DeathRecipient, KeyEventDispatcher.KeyEventFilter,
         FingerprintGestureDispatcher.FingerprintGestureClient {
@@ -209,6 +210,7 @@
     final ComponentName mComponentName;
 
     int mGenericMotionEventSources;
+    int mObservedMotionEventSources;
 
     // the events pending events to be dispatched to this service
     final SparseArray<AccessibilityEvent> mPendingEvents = new SparseArray<>();
@@ -397,6 +399,19 @@
         mNotificationTimeout = info.notificationTimeout;
         mIsDefault = (info.flags & DEFAULT) != 0;
         mGenericMotionEventSources = info.getMotionEventSources();
+        if (android.view.accessibility.Flags.motionEventObserving()) {
+            if (mContext.checkCallingOrSelfPermission(
+                            android.Manifest.permission.ACCESSIBILITY_MOTION_EVENT_OBSERVING)
+                    == PackageManager.PERMISSION_GRANTED) {
+                mObservedMotionEventSources = info.getObservedMotionEventSources();
+            } else {
+                Slog.e(
+                        LOG_TAG,
+                        "Observing motion events requires"
+                            + " android.Manifest.permission.ACCESSIBILITY_MOTION_EVENT_OBSERVING.");
+                mObservedMotionEventSources = 0;
+            }
+        }
 
         if (supportsFlagForNotImportantViews(info)) {
             if ((info.flags & AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0) {
@@ -1599,7 +1614,7 @@
             final int displayId = displays[i].getDisplayId();
             onDisplayRemoved(displayId);
         }
-        if (Flags.cleanupA11yOverlays()) {
+        if (com.android.server.accessibility.Flags.cleanupA11yOverlays()) {
             detachAllOverlays();
         }
     }
@@ -1848,8 +1863,14 @@
     }
 
     public void notifyGesture(AccessibilityGestureEvent gestureEvent) {
-        mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_GESTURE,
-                gestureEvent).sendToTarget();
+        if (android.view.accessibility.Flags.copyEventsForGestureDetection()) {
+            // We will use this event async, so copy it because it contains MotionEvents.
+            mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_GESTURE,
+                    gestureEvent.copyForAsync()).sendToTarget();
+        } else {
+            mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_GESTURE,
+                    gestureEvent).sendToTarget();
+        }
     }
 
     public void notifySystemActionsChangedLocked() {
@@ -1913,6 +1934,7 @@
         return (mGenericMotionEventSources & eventSourceWithoutClass) != 0;
     }
 
+
     /**
      * Called by the invocation handler to notify the service that the
      * state of magnification has changed.
@@ -2323,9 +2345,13 @@
             final int type = message.what;
             switch (type) {
                 case MSG_ON_GESTURE: {
-                    notifyGestureInternal((AccessibilityGestureEvent) message.obj);
+                    if (message.obj instanceof AccessibilityGestureEvent gesture) {
+                        notifyGestureInternal(gesture);
+                        if (android.view.accessibility.Flags.copyEventsForGestureDetection()) {
+                            gesture.recycle();
+                        }
+                    }
                 } break;
-
                 case MSG_CLEAR_ACCESSIBILITY_CACHE: {
                     notifyClearAccessibilityCacheInternal();
                 } break;
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
index 6cac6a4..abcd8e2 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -57,6 +57,7 @@
  *
  * NOTE: This class has to be created and poked only from the main thread.
  */
+@SuppressWarnings("MissingPermissionAnnotation")
 class AccessibilityInputFilter extends InputFilter implements EventStreamTransformation {
 
     private static final String TAG = AccessibilityInputFilter.class.getSimpleName();
@@ -198,6 +199,7 @@
     // State tracking for generic MotionEvents is display-agnostic so we only need one.
     private GenericMotionEventStreamState mGenericMotionEventStreamState;
     private int mCombinedGenericMotionEventSources = 0;
+    private int mCombinedMotionEventObservedSources = 0;
 
     private EventStreamState mKeyboardStreamState;
 
@@ -525,16 +527,33 @@
         }
 
         if ((mEnabledFeatures & FLAG_FEATURE_INTERCEPT_GENERIC_MOTION_EVENTS) != 0) {
-            addFirstEventHandler(displayId, new BaseEventStreamTransformation() {
-                @Override
-                public void onMotionEvent(MotionEvent event, MotionEvent rawEvent,
-                        int policyFlags) {
-                    if (!anyServiceWantsGenericMotionEvent(rawEvent)
-                            || !mAms.sendMotionEventToListeningServices(rawEvent)) {
-                        super.onMotionEvent(event, rawEvent, policyFlags);
-                    }
-                }
-            });
+            addFirstEventHandler(
+                    displayId,
+                    new BaseEventStreamTransformation() {
+                        @Override
+                        public void onMotionEvent(
+                                MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+                            boolean passAlongEvent = true;
+                            if (anyServiceWantsGenericMotionEvent(event)) {
+                                // Some service wants this event, so try to deliver it to at least
+                                // one service.
+                                if (mAms.sendMotionEventToListeningServices(event)) {
+                                    // A service accepted this event, so prevent it from passing
+                                    // down the stream by default.
+                                    passAlongEvent = false;
+                                }
+                                // However, if a service is observing these events instead of
+                                // consuming them then ensure
+                                // it is always passed along to the next stage of the event stream.
+                                if (anyServiceWantsToObserveMotionEvent(event)) {
+                                    passAlongEvent = true;
+                                }
+                            }
+                            if (passAlongEvent) {
+                                super.onMotionEvent(event, rawEvent, policyFlags);
+                            }
+                        }
+                    });
         }
 
         if ((mEnabledFeatures & FLAG_FEATURE_CONTROL_SCREEN_MAGNIFIER) != 0
@@ -542,15 +561,14 @@
                 || ((mEnabledFeatures & FLAG_FEATURE_MAGNIFICATION_TWO_FINGER_TRIPLE_TAP) != 0)
                 || ((mEnabledFeatures & FLAG_FEATURE_TRIGGERED_SCREEN_MAGNIFIER) != 0)) {
             final MagnificationGestureHandler magnificationGestureHandler =
-                    createMagnificationGestureHandler(displayId,
-                            displayContext);
+                    createMagnificationGestureHandler(displayId, displayContext);
             addFirstEventHandler(displayId, magnificationGestureHandler);
             mMagnificationGestureHandler.put(displayId, magnificationGestureHandler);
         }
 
         if ((mEnabledFeatures & FLAG_FEATURE_INJECT_MOTION_EVENTS) != 0) {
-            MotionEventInjector injector = new MotionEventInjector(
-                    mContext.getMainLooper(), mAms.getTraceManager());
+            MotionEventInjector injector =
+                    new MotionEventInjector(mContext.getMainLooper(), mAms.getTraceManager());
             addFirstEventHandler(displayId, injector);
             mMotionEventInjectors.put(displayId, injector);
         }
@@ -923,6 +941,20 @@
         }
     }
 
+    private boolean anyServiceWantsToObserveMotionEvent(MotionEvent event) {
+        // Disable SOURCE_TOUCHSCREEN generic event interception if any service is performing
+        // touch exploration.
+        if (event.isFromSource(InputDevice.SOURCE_TOUCHSCREEN)
+                && (mEnabledFeatures & FLAG_FEATURE_TOUCH_EXPLORATION) != 0) {
+            return false;
+        }
+        final int eventSourceWithoutClass = event.getSource() & ~InputDevice.SOURCE_CLASS_MASK;
+        return (mCombinedGenericMotionEventSources
+                        & mCombinedMotionEventObservedSources
+                        & eventSourceWithoutClass)
+                != 0;
+    }
+
     private boolean anyServiceWantsGenericMotionEvent(MotionEvent event) {
         // Disable SOURCE_TOUCHSCREEN generic event interception if any service is performing
         // touch exploration.
@@ -938,6 +970,10 @@
         mCombinedGenericMotionEventSources = sources;
     }
 
+    public void setCombinedMotionEventObservedSources(int sources) {
+        mCombinedMotionEventObservedSources = sources;
+    }
+
     /**
      * Keeps state of streams of events from all keyboard devices.
      */
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 440e996..3d8d7b7 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -195,6 +195,7 @@
  * event dispatch for {@link AccessibilityEvent}s generated across all processes
  * on the device. Events are dispatched to {@link AccessibilityService}s.
  */
+@SuppressWarnings("MissingPermissionAnnotation")
 public class AccessibilityManagerService extends IAccessibilityManager.Stub
         implements AbstractAccessibilityServiceConnection.SystemSupport,
         AccessibilityUserState.ServiceInfoChangeListener,
@@ -2825,8 +2826,10 @@
                 flags |= AccessibilityInputFilter.FLAG_FEATURE_INJECT_MOTION_EVENTS;
             }
             int combinedGenericMotionEventSources = 0;
+            int combinedMotionEventObservedSources = 0;
             for (AccessibilityServiceConnection connection : userState.mBoundServices) {
                 combinedGenericMotionEventSources |= connection.mGenericMotionEventSources;
+                combinedMotionEventObservedSources |= connection.mObservedMotionEventSources;
             }
             if (combinedGenericMotionEventSources != 0) {
                 flags |= AccessibilityInputFilter.FLAG_FEATURE_INTERCEPT_GENERIC_MOTION_EVENTS;
@@ -2845,6 +2848,8 @@
                 mInputFilter.setUserAndEnabledFeatures(userState.mUserId, flags);
                 mInputFilter.setCombinedGenericMotionEventSources(
                         combinedGenericMotionEventSources);
+                mInputFilter.setCombinedMotionEventObservedSources(
+                        combinedMotionEventObservedSources);
             } else {
                 if (mHasInputFilter) {
                     mHasInputFilter = false;
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
index 40ca694..5ebe161 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
@@ -65,6 +65,7 @@
  * passed to the service it represents as soon it is bound. It also serves as the
  * connection for the service.
  */
+@SuppressWarnings("MissingPermissionAnnotation")
 class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnection {
     private static final String LOG_TAG = "AccessibilityServiceConnection";
 
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityTraceManager.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityTraceManager.java
index 307b555..8471061 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityTraceManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityTraceManager.java
@@ -224,7 +224,7 @@
         pw.println("            IAccessibilityInteractionConnectionCallback");
         pw.println("            IRemoteMagnificationAnimationCallback");
         pw.println("            IMagnificationConnection");
-        pw.println("            IWindowMagnificationConnectionCallback");
+        pw.println("            IMagnificationConnectionCallback");
         pw.println("            WindowManagerInternal");
         pw.println("            WindowsForAccessibilityCallback");
         pw.println("            MagnificationCallbacks");
diff --git a/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java b/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java
index a525e7c..b119d7d 100644
--- a/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java
+++ b/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java
@@ -34,6 +34,7 @@
  * If we are stripping and/or replacing the actions from a window, we need to intercept the
  * nodes heading back to the service and swap out the actions.
  */
+@SuppressWarnings("MissingPermissionAnnotation")
 public class ActionReplacingCallback extends IAccessibilityInteractionConnectionCallback.Stub {
     private static final boolean DEBUG = false;
     private static final String LOG_TAG = "ActionReplacingCallback";
diff --git a/services/accessibility/java/com/android/server/accessibility/FingerprintGestureDispatcher.java b/services/accessibility/java/com/android/server/accessibility/FingerprintGestureDispatcher.java
index c9ec16e..e10e87c 100644
--- a/services/accessibility/java/com/android/server/accessibility/FingerprintGestureDispatcher.java
+++ b/services/accessibility/java/com/android/server/accessibility/FingerprintGestureDispatcher.java
@@ -33,6 +33,7 @@
 /**
  * Encapsulate fingerprint gesture logic
  */
+@SuppressWarnings("MissingPermissionAnnotation")
 public class FingerprintGestureDispatcher extends IFingerprintClientActiveCallback.Stub
         implements Handler.Callback{
     private static final int MSG_REGISTER = 1;
diff --git a/services/accessibility/java/com/android/server/accessibility/ProxyAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/ProxyAccessibilityServiceConnection.java
index ab01fc3..6aa4702 100644
--- a/services/accessibility/java/com/android/server/accessibility/ProxyAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/ProxyAccessibilityServiceConnection.java
@@ -64,6 +64,7 @@
  *
  * TODO(241429275): Initialize this when a proxy is registered.
  */
+@SuppressWarnings("MissingPermissionAnnotation")
 public class ProxyAccessibilityServiceConnection extends AccessibilityServiceConnection {
     private static final String LOG_TAG = "ProxyAccessibilityServiceConnection";
 
diff --git a/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java b/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java
index 53c629a..f69104d 100644
--- a/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java
@@ -245,6 +245,7 @@
         }
     }
 
+    @SuppressWarnings("MissingPermissionAnnotation")
     private class UiAutomationService extends AbstractAccessibilityServiceConnection {
         private final Handler mMainHandler;
 
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java b/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java
index 903a071..e54f0c1 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java
@@ -82,7 +82,7 @@
  * detector. Gesture matchers are tied to a single gesture. It calls listener callback functions
  * when a gesture starts or completes.
  */
-class GestureManifold implements GestureMatcher.StateChangeListener {
+public class GestureManifold implements GestureMatcher.StateChangeListener {
 
     private static final String LOG_TAG = "GestureManifold";
 
@@ -111,7 +111,7 @@
     // Shared state information.
     private TouchState mState;
 
-    GestureManifold(Context context, Listener listener, TouchState state, Handler handler) {
+    public GestureManifold(Context context, Listener listener, TouchState state, Handler handler) {
         mContext = context;
         mHandler = handler;
         mListener = listener;
@@ -222,7 +222,7 @@
      * @return True if the event has been appropriately handled by the gesture manifold and related
      *     callback functions, false if it should be handled further by the calling function.
      */
-    boolean onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+    public boolean onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
         if (mState.isClear()) {
             if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
                 // Validity safeguard: if touch state is clear, then matchers should always be clear
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/GestureMatcher.java b/services/accessibility/java/com/android/server/accessibility/gestures/GestureMatcher.java
index 6e2fc69..3668eef 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/GestureMatcher.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/GestureMatcher.java
@@ -328,13 +328,21 @@
                                 + getStateSymbolicName(mTargetState));
             }
             mHandler.removeCallbacks(this);
+            recycleEvent();
         }
 
         public void post(
                 int state, long delay, MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+            // Recycle the old event first if necessary, to handle duplicate calls to post.
+            recycleEvent();
             mTargetState = state;
-            mEvent = event;
-            mRawEvent = rawEvent;
+            if (android.view.accessibility.Flags.copyEventsForGestureDetection()) {
+                mEvent = event.copy();
+                mRawEvent = rawEvent.copy();
+            } else {
+                mEvent = event;
+                mRawEvent = rawEvent;
+            }
             mPolicyFlags = policyFlags;
             mHandler.postDelayed(this, delay);
             if (DEBUG) {
@@ -367,6 +375,19 @@
                                 + getStateSymbolicName(mTargetState));
             }
             setState(mTargetState, mEvent, mRawEvent, mPolicyFlags);
+            recycleEvent();
+        }
+
+        private void recycleEvent() {
+            if (android.view.accessibility.Flags.copyEventsForGestureDetection()) {
+                if (mEvent == null || mRawEvent == null) {
+                    return;
+                }
+                mEvent.recycle();
+                mRawEvent.recycle();
+                mEvent = null;
+                mRawEvent = null;
+            }
         }
     }
 
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
index f55ecb0..baae1d93 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
@@ -861,6 +861,7 @@
     }
 
     final class DetectingStateWithMultiFinger extends DetectingState {
+        private static final int TWO_FINGER_GESTURE_MAX_TAPS = 2;
         // A flag set to true when two fingers have touched down.
         // Used to indicate what next finger action should be.
         private boolean mIsTwoFingerCountReached = false;
@@ -917,7 +918,8 @@
                     mHandler.removeMessages(MESSAGE_TRANSITION_TO_DELEGATING_STATE);
 
                     if (event.getPointerCount() == 2) {
-                        if (isMultiFingerMultiTapTriggered(/* targetTapCount= */ 2, event)) {
+                        if (isMultiFingerMultiTapTriggered(
+                                TWO_FINGER_GESTURE_MAX_TAPS - 1, event)) {
                             // 3tap and hold
                             afterLongTapTimeoutTransitionToDraggingState(event);
                         } else {
@@ -962,7 +964,8 @@
                         // (which is a rare combo to be used aside from magnification)
                         if (isMultiTapTriggered(2 /* taps */) && event.getPointerCount() == 1) {
                             transitionToViewportDraggingStateAndClear(event);
-                        } else if (isMultiFingerMultiTapTriggered(/* targetTapCount= */ 2, event)
+                        } else if (isMultiFingerMultiTapTriggered(
+                                TWO_FINGER_GESTURE_MAX_TAPS - 1, event)
                                 && event.getPointerCount() == 2) {
                             transitionToViewportDraggingStateAndClear(event);
                         } else if (isActivated() && event.getPointerCount() == 2) {
@@ -981,17 +984,22 @@
                                 transitionToDelegatingStateAndClear();
                             }
                             transitToSinglePanningStateAndClear();
-                        } else {
+                        } else if (!mIsTwoFingerCountReached) {
+                            // If it is a two-finger gesture, do not transition to the
+                            // delegating state to ensure the reachability of
+                            // the two-finger triple tap (triggerable with ACTION_UP)
                             transitionToDelegatingStateAndClear();
                         }
                     } else if (isActivated() && pointerDownValid(mSecondPointerDownLocation)
                             && distanceClosestPointerToPoint(
-                            mSecondPointerDownLocation, /* move */ event) > mSwipeMinDistance
-                            // If mCompleteTapCount is not zero, it means that it is a multi tap
-                            // gesture. So, we should not transit to the PanningScalingState.
-                            && mCompletedTapCount == 0) {
+                            mSecondPointerDownLocation, /* move */ event) > mSwipeMinDistance) {
                         // Second pointer is swiping, so transit to PanningScalingState
-                        transitToPanningScalingStateAndClear();
+                        // Delay an ACTION_MOVE for tap timeout to ensure it is not trigger from
+                        // multi finger multi tap
+                        storePointerDownLocation(mSecondPointerDownLocation, event);
+                        mHandler.sendEmptyMessageDelayed(
+                                MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE,
+                                ViewConfiguration.getTapTimeout());
                     }
                 }
                 break;
@@ -1004,7 +1012,7 @@
                             mDisplayId, event.getX(), event.getY())) {
                         transitionToDelegatingStateAndClear();
 
-                    } else if (isMultiFingerMultiTapTriggered(/* targetTapCount= */ 3, event)) {
+                    } else if (isMultiFingerMultiTapTriggered(TWO_FINGER_GESTURE_MAX_TAPS, event)) {
                         // Placing multiple fingers before a single finger, because achieving a
                         // multi finger multi tap also means achieving a single finger triple tap
                         onTripleTap(event);
@@ -1046,7 +1054,7 @@
                 mIsTwoFingerCountReached = false;
             }
 
-            if (mDetectTwoFingerTripleTap && mCompletedTapCount > 2) {
+            if (mDetectTwoFingerTripleTap && mCompletedTapCount > TWO_FINGER_GESTURE_MAX_TAPS - 1) {
                 final boolean enabled = !isActivated();
                 mMagnificationLogger.logMagnificationTwoFingerTripleTap(enabled);
             }
@@ -1070,7 +1078,7 @@
             // Only log the 3tap and hold event
             if (!shortcutTriggered) {
                 final boolean enabled = !isActivated();
-                if (mCompletedTapCount == 2) {
+                if (mCompletedTapCount == TWO_FINGER_GESTURE_MAX_TAPS - 1) {
                     // Two finger triple tap and hold
                     mMagnificationLogger.logMagnificationTwoFingerTripleTap(enabled);
                 } else {
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationConnectionManager.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationConnectionManager.java
index eff6488..e11c36a 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationConnectionManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationConnectionManager.java
@@ -17,7 +17,7 @@
 package com.android.server.accessibility.magnification;
 
 import static android.accessibilityservice.AccessibilityTrace.FLAGS_MAGNIFICATION_CONNECTION;
-import static android.accessibilityservice.AccessibilityTrace.FLAGS_WINDOW_MAGNIFICATION_CONNECTION_CALLBACK;
+import static android.accessibilityservice.AccessibilityTrace.FLAGS_MAGNIFICATION_CONNECTION_CALLBACK;
 import static android.view.accessibility.MagnificationAnimationCallback.STUB_ANIMATION_CALLBACK;
 
 import static com.android.server.accessibility.AccessibilityManagerService.INVALID_SERVICE_ID;
@@ -43,7 +43,7 @@
 import android.util.SparseBooleanArray;
 import android.view.MotionEvent;
 import android.view.accessibility.IMagnificationConnection;
-import android.view.accessibility.IWindowMagnificationConnectionCallback;
+import android.view.accessibility.IMagnificationConnectionCallback;
 import android.view.accessibility.MagnificationAnimationCallback;
 
 import com.android.internal.accessibility.common.MagnificationConstants;
@@ -922,16 +922,17 @@
         disableWindowMagnification(displayId, true);
     }
 
-    private class ConnectionCallback extends IWindowMagnificationConnectionCallback.Stub implements
+    @SuppressWarnings("MissingPermissionAnnotation")
+    private class ConnectionCallback extends IMagnificationConnectionCallback.Stub implements
             IBinder.DeathRecipient {
         private boolean mExpiredDeathRecipient = false;
 
         @Override
         public void onWindowMagnifierBoundsChanged(int displayId, Rect bounds) {
             if (mTrace.isA11yTracingEnabledForTypes(
-                    FLAGS_WINDOW_MAGNIFICATION_CONNECTION_CALLBACK)) {
+                    FLAGS_MAGNIFICATION_CONNECTION_CALLBACK)) {
                 mTrace.logTrace(TAG + "ConnectionCallback.onWindowMagnifierBoundsChanged",
-                        FLAGS_WINDOW_MAGNIFICATION_CONNECTION_CALLBACK,
+                        FLAGS_MAGNIFICATION_CONNECTION_CALLBACK,
                         "displayId=" + displayId + ";bounds=" + bounds);
             }
             synchronized (mLock) {
@@ -951,9 +952,9 @@
         public void onChangeMagnificationMode(int displayId, int magnificationMode)
                 throws RemoteException {
             if (mTrace.isA11yTracingEnabledForTypes(
-                    FLAGS_WINDOW_MAGNIFICATION_CONNECTION_CALLBACK)) {
+                    FLAGS_MAGNIFICATION_CONNECTION_CALLBACK)) {
                 mTrace.logTrace(TAG + "ConnectionCallback.onChangeMagnificationMode",
-                        FLAGS_WINDOW_MAGNIFICATION_CONNECTION_CALLBACK,
+                        FLAGS_MAGNIFICATION_CONNECTION_CALLBACK,
                         "displayId=" + displayId + ";mode=" + magnificationMode);
             }
             mCallback.onChangeMagnificationMode(displayId, magnificationMode);
@@ -962,9 +963,9 @@
         @Override
         public void onSourceBoundsChanged(int displayId, Rect sourceBounds) {
             if (mTrace.isA11yTracingEnabledForTypes(
-                    FLAGS_WINDOW_MAGNIFICATION_CONNECTION_CALLBACK)) {
+                    FLAGS_MAGNIFICATION_CONNECTION_CALLBACK)) {
                 mTrace.logTrace(TAG + "ConnectionCallback.onSourceBoundsChanged",
-                        FLAGS_WINDOW_MAGNIFICATION_CONNECTION_CALLBACK,
+                        FLAGS_MAGNIFICATION_CONNECTION_CALLBACK,
                         "displayId=" + displayId + ";source=" + sourceBounds);
             }
             synchronized (mLock) {
@@ -980,9 +981,9 @@
         @Override
         public void onPerformScaleAction(int displayId, float scale, boolean updatePersistence) {
             if (mTrace.isA11yTracingEnabledForTypes(
-                    FLAGS_WINDOW_MAGNIFICATION_CONNECTION_CALLBACK)) {
+                    FLAGS_MAGNIFICATION_CONNECTION_CALLBACK)) {
                 mTrace.logTrace(TAG + "ConnectionCallback.onPerformScaleAction",
-                        FLAGS_WINDOW_MAGNIFICATION_CONNECTION_CALLBACK,
+                        FLAGS_MAGNIFICATION_CONNECTION_CALLBACK,
                         "displayId=" + displayId + ";scale=" + scale
                                 + ";updatePersistence=" + updatePersistence);
             }
@@ -992,9 +993,9 @@
         @Override
         public void onAccessibilityActionPerformed(int displayId) {
             if (mTrace.isA11yTracingEnabledForTypes(
-                    FLAGS_WINDOW_MAGNIFICATION_CONNECTION_CALLBACK)) {
+                    FLAGS_MAGNIFICATION_CONNECTION_CALLBACK)) {
                 mTrace.logTrace(TAG + "ConnectionCallback.onAccessibilityActionPerformed",
-                        FLAGS_WINDOW_MAGNIFICATION_CONNECTION_CALLBACK,
+                        FLAGS_MAGNIFICATION_CONNECTION_CALLBACK,
                         "displayId=" + displayId);
             }
             mCallback.onAccessibilityActionPerformed(displayId);
@@ -1003,9 +1004,9 @@
         @Override
         public void onMove(int displayId) {
             if (mTrace.isA11yTracingEnabledForTypes(
-                    FLAGS_WINDOW_MAGNIFICATION_CONNECTION_CALLBACK)) {
+                    FLAGS_MAGNIFICATION_CONNECTION_CALLBACK)) {
                 mTrace.logTrace(TAG + "ConnectionCallback.onMove",
-                        FLAGS_WINDOW_MAGNIFICATION_CONNECTION_CALLBACK,
+                        FLAGS_MAGNIFICATION_CONNECTION_CALLBACK,
                         "displayId=" + displayId);
             }
             setTrackingTypingFocusEnabled(displayId, false);
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationConnectionWrapper.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationConnectionWrapper.java
index d7098a7..db5b313 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationConnectionWrapper.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationConnectionWrapper.java
@@ -17,8 +17,8 @@
 package com.android.server.accessibility.magnification;
 
 import static android.accessibilityservice.AccessibilityTrace.FLAGS_MAGNIFICATION_CONNECTION;
+import static android.accessibilityservice.AccessibilityTrace.FLAGS_MAGNIFICATION_CONNECTION_CALLBACK;
 import static android.accessibilityservice.AccessibilityTrace.FLAGS_REMOTE_MAGNIFICATION_ANIMATION_CALLBACK;
-import static android.accessibilityservice.AccessibilityTrace.FLAGS_WINDOW_MAGNIFICATION_CONNECTION_CALLBACK;
 import static android.os.IBinder.DeathRecipient;
 
 import android.annotation.NonNull;
@@ -26,8 +26,8 @@
 import android.os.RemoteException;
 import android.util.Slog;
 import android.view.accessibility.IMagnificationConnection;
+import android.view.accessibility.IMagnificationConnectionCallback;
 import android.view.accessibility.IRemoteMagnificationAnimationCallback;
-import android.view.accessibility.IWindowMagnificationConnectionCallback;
 import android.view.accessibility.MagnificationAnimationCallback;
 
 import com.android.server.accessibility.AccessibilityTraceManager;
@@ -217,13 +217,13 @@
         return true;
     }
 
-    boolean setConnectionCallback(IWindowMagnificationConnectionCallback connectionCallback) {
+    boolean setConnectionCallback(IMagnificationConnectionCallback connectionCallback) {
         if (mTrace.isA11yTracingEnabledForTypes(
                 FLAGS_MAGNIFICATION_CONNECTION
-                | FLAGS_WINDOW_MAGNIFICATION_CONNECTION_CALLBACK)) {
+                | FLAGS_MAGNIFICATION_CONNECTION_CALLBACK)) {
             mTrace.logTrace(TAG + ".setConnectionCallback",
                     FLAGS_MAGNIFICATION_CONNECTION
-                    | FLAGS_WINDOW_MAGNIFICATION_CONNECTION_CALLBACK,
+                    | FLAGS_MAGNIFICATION_CONNECTION_CALLBACK,
                     "callback=" + connectionCallback);
         }
         try {
@@ -246,6 +246,7 @@
         return new RemoteAnimationCallback(callback, trace);
     }
 
+    @SuppressWarnings("MissingPermissionAnnotation")
     private static class RemoteAnimationCallback extends
             IRemoteMagnificationAnimationCallback.Stub {
         private final MagnificationAnimationCallback mCallback;
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
index 73c267a..75d01f5 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
@@ -481,10 +481,10 @@
 
                 if (mDetectTwoFingerTripleTap) {
                     mGestureMatchers.add(new MultiFingerMultiTap(context, /* fingers= */ 2,
-                            /* taps= */ 3, MagnificationGestureMatcher.GESTURE_TRIPLE_TAP,
+                            /* taps= */ 2, MagnificationGestureMatcher.GESTURE_TRIPLE_TAP,
                             null));
                     mGestureMatchers.add(new MultiFingerMultiTapAndHold(context, /* fingers= */ 2,
-                            /* taps= */ 3, MagnificationGestureMatcher.GESTURE_TRIPLE_TAP_AND_HOLD,
+                            /* taps= */ 2, MagnificationGestureMatcher.GESTURE_TRIPLE_TAP_AND_HOLD,
                             null));
                 }
 
diff --git a/services/autofill/bugfixes.aconfig b/services/autofill/bugfixes.aconfig
index ab678d9..b5130a1 100644
--- a/services/autofill/bugfixes.aconfig
+++ b/services/autofill/bugfixes.aconfig
@@ -27,3 +27,10 @@
   description: "Mitigation for view state reset to empty causing no save dialog to show issue"
   bug: "297976948"
 }
+
+flag {
+  name: "include_invisible_view_group_in_assist_structure"
+  namespace: "autofill"
+  description: "Mitigation for autofill providers miscalculating view visibility"
+  bug: "291795358"
+}
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index cce596b..487b66c 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -93,9 +93,7 @@
 import android.os.PowerWhitelistManager;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
-import android.os.ResultReceiver;
 import android.os.ServiceManager;
-import android.os.ShellCallback;
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -1064,13 +1062,14 @@
         }
 
         @Override
-        public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
-                String[] args, ShellCallback callback, ResultReceiver resultReceiver)
-                throws RemoteException {
-            new CompanionDeviceShellCommand(CompanionDeviceManagerService.this, mAssociationStore,
-                    mDevicePresenceMonitor, mTransportManager, mSystemDataTransferProcessor,
-                    mAssociationRequestsProcessor)
-                    .exec(this, in, out, err, args, callback, resultReceiver);
+        public int handleShellCommand(@NonNull ParcelFileDescriptor in,
+                @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err,
+                @NonNull String[] args) {
+            return new CompanionDeviceShellCommand(CompanionDeviceManagerService.this,
+                    mAssociationStore, mDevicePresenceMonitor, mTransportManager,
+                    mSystemDataTransferProcessor, mAssociationRequestsProcessor)
+                    .exec(this, in.getFileDescriptor(), out.getFileDescriptor(),
+                            err.getFileDescriptor(), args);
         }
 
         @Override
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java b/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java
index 23e7ce6..9fdf5c2 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java
@@ -92,9 +92,10 @@
                     int userId = getNextIntArgRequired();
                     String packageName = getNextArgRequired();
                     String address = getNextArgRequired();
+                    String deviceProfile = getNextArg();
                     final MacAddress macAddress = MacAddress.fromString(address);
                     mService.createNewAssociation(userId, packageName, macAddress,
-                            null, null, false);
+                            null, deviceProfile, false);
                 }
                 break;
 
@@ -350,7 +351,7 @@
         pw.println("      Print this help text.");
         pw.println("  list USER_ID");
         pw.println("      List all Associations for a user.");
-        pw.println("  associate USER_ID PACKAGE MAC_ADDRESS");
+        pw.println("  associate USER_ID PACKAGE MAC_ADDRESS [DEVICE_PROFILE]");
         pw.println("      Create a new Association.");
         pw.println("  disassociate USER_ID PACKAGE MAC_ADDRESS");
         pw.println("      Remove an existing Association.");
diff --git a/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java b/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java
index f648f09..df74770 100644
--- a/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java
+++ b/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java
@@ -274,9 +274,7 @@
     }
 
     private boolean isSecureTransportEnabled() {
-        boolean enabled = !Build.IS_DEBUGGABLE || mSecureTransportEnabled;
-
-        return enabled;
+        return mSecureTransportEnabled;
     }
 
     private void addMessageListenersToTransport(Transport transport) {
diff --git a/services/companion/java/com/android/server/companion/virtual/InputController.java b/services/companion/java/com/android/server/companion/virtual/InputController.java
index c111ec3..1f89e57b 100644
--- a/services/companion/java/com/android/server/companion/virtual/InputController.java
+++ b/services/companion/java/com/android/server/companion/virtual/InputController.java
@@ -253,13 +253,8 @@
         mInputManagerInternal.setDisplayEligibilityForPointerCapture(displayId, isEligible);
     }
 
-    void setLocalIme(int displayId) {
-        // WM throws a SecurityException if the display is untrusted.
-        if ((mDisplayManagerInternal.getDisplayInfo(displayId).flags & Display.FLAG_TRUSTED)
-                == Display.FLAG_TRUSTED) {
-            mWindowManager.setDisplayImePolicy(displayId,
-                    WindowManager.DISPLAY_IME_POLICY_LOCAL);
-        }
+    void setDisplayImePolicy(int displayId, @WindowManager.DisplayImePolicy int policy) {
+        mWindowManager.setDisplayImePolicy(displayId, policy);
     }
 
     @GuardedBy("mLock")
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 45d7314..58aa2c3 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
@@ -104,6 +104,7 @@
 import com.android.server.companion.virtual.GenericWindowPolicyController.RunningAppsChangedListener;
 import com.android.server.companion.virtual.audio.VirtualAudioController;
 import com.android.server.companion.virtual.camera.VirtualCameraController;
+import com.android.server.inputmethod.InputMethodManagerInternal;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -352,6 +353,14 @@
             flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED;
         }
         mBaseVirtualDisplayFlags = flags;
+
+        if (Flags.vdmCustomIme() && mParams.getInputMethodComponent() != null) {
+            final String imeId = mParams.getInputMethodComponent().flattenToShortString();
+            Slog.d(TAG, "Setting custom input method " + imeId + " as default for virtual device "
+                    + deviceId);
+            InputMethodManagerInternal.get().setVirtualDeviceInputMethodForAllUsers(
+                    mDeviceId, imeId);
+        }
     }
 
     @VisibleForTesting
@@ -556,6 +565,12 @@
                 mCameraAccessController.stopObservingIfNeeded();
             }
 
+            // Clear any previously set custom IME components.
+            if (Flags.vdmCustomIme() && mParams.getInputMethodComponent() != null) {
+                InputMethodManagerInternal.get().setVirtualDeviceInputMethodForAllUsers(
+                        mDeviceId, null);
+            }
+
             mInputController.close();
             mSensorController.close();
         } finally {
@@ -884,6 +899,24 @@
 
     @Override // Binder call
     @EnforcePermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
+    public void setDisplayImePolicy(int displayId, @WindowManager.DisplayImePolicy int policy) {
+        super.setDisplayImePolicy_enforcePermission();
+        synchronized (mVirtualDeviceLock) {
+            if (!mVirtualDisplays.contains(displayId)) {
+                throw new SecurityException("Display ID " + displayId
+                        + " not found for this virtual device");
+            }
+        }
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            mInputController.setDisplayImePolicy(displayId, policy);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    @Override // Binder call
+    @EnforcePermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
     @Nullable
     public List<VirtualSensor> getVirtualSensorList() {
         super.getVirtualSensorList_enforcePermission();
@@ -1080,7 +1113,12 @@
             mInputController.setPointerAcceleration(1f, displayId);
             mInputController.setDisplayEligibilityForPointerCapture(/* isEligible= */ false,
                     displayId);
-            mInputController.setLocalIme(displayId);
+            // WM throws a SecurityException if the display is untrusted.
+            if ((mDisplayManagerInternal.getDisplayInfo(displayId).flags & Display.FLAG_TRUSTED)
+                    == Display.FLAG_TRUSTED) {
+                mInputController.setDisplayImePolicy(displayId,
+                        WindowManager.DISPLAY_IME_POLICY_LOCAL);
+            }
         } finally {
             Binder.restoreCallingIdentity(token);
         }
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
index 9b78ed4..0d5cdcb 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
@@ -439,6 +439,12 @@
             if (associationInfo == null) {
                 throw new IllegalArgumentException("No association with ID " + associationId);
             }
+            if (!VIRTUAL_DEVICE_COMPANION_DEVICE_PROFILES
+                    .contains(associationInfo.getDeviceProfile())
+                    && Flags.persistentDeviceIdApi()) {
+                throw new IllegalArgumentException("Unsupported CDM Association device profile "
+                        + associationInfo.getDeviceProfile() + " for virtual device creation.");
+            }
             Objects.requireNonNull(params);
             Objects.requireNonNull(activityListener);
             Objects.requireNonNull(soundEffectListener);
@@ -455,7 +461,7 @@
                     cameraAccessController, mPendingTrampolineCallback, activityListener,
                     soundEffectListener, runningAppsChangedCallback, params);
             if (Flags.expressMetrics()) {
-                Counter.logIncrement("virtual_devices.virtual_devices_created_count");
+                Counter.logIncrement("virtual_devices.value_virtual_devices_created_count");
             }
 
             synchronized (mVirtualDeviceManagerLock) {
@@ -859,6 +865,11 @@
         }
 
         @Override
+        public boolean isValidVirtualDeviceId(int deviceId) {
+            return mImpl.isValidVirtualDeviceId(deviceId);
+        }
+
+        @Override
         public @Nullable String getPersistentIdForDevice(int deviceId) {
             if (deviceId == Context.DEVICE_ID_DEFAULT) {
                 return VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT;
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
index 34787a3..145303d 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -554,6 +554,10 @@
             if (mMaster.debug) Slog.d(mTag, "onActivityEvent(): no remote service");
             return;
         }
+        if (mRemoteService.getServiceInterface() == null) {
+            if (mMaster.debug) Slog.d(mTag, "onActivityEvent(): remote service is dead or unbound");
+            return;
+        }
         final ActivityEvent event = new ActivityEvent(activityId, componentName, type);
 
         if (mMaster.verbose) Slog.v(mTag, "onActivityEvent(): " + event);
diff --git a/services/core/Android.bp b/services/core/Android.bp
index b4cf34e..f5a80d8 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -166,7 +166,7 @@
         "android.hardware.health-V1.0-java", // HIDL
         "android.hardware.health-V2.0-java", // HIDL
         "android.hardware.health-V2.1-java", // HIDL
-        "android.hardware.health-V2-java", // AIDL
+        "android.hardware.health-V3-java", // AIDL
         "android.hardware.health-translate-java",
         "android.hardware.light-V1-java",
         "android.hardware.security.rkp-V3-java",
@@ -200,6 +200,7 @@
         "notification_flags_lib",
         "biometrics_flags_lib",
         "am_flags_lib",
+        "com_android_systemui_shared_flags_lib",
         "com_android_wm_shell_flags_lib",
         "com.android.server.utils_aconfig-java",
         "service-jobscheduler-deviceidle.flags-aconfig-java",
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index 31c9348..136692e 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -222,6 +222,14 @@
             int callingUid);
 
     /**
+     * Like {@link #getInstalledApplications}, but allows the fetching of apps
+     * cross user.
+     */
+    public abstract List<ApplicationInfo> getInstalledApplicationsCrossUser(
+            @PackageManager.ApplicationInfoFlagsBits long flags, @UserIdInt int userId,
+            int callingUid);
+
+    /**
      * Retrieve launcher extras for a suspended package provided to the system in
      * {@link PackageManager#setPackagesSuspended(String[], boolean, PersistableBundle,
      * PersistableBundle, String)}.
@@ -1418,14 +1426,19 @@
 
     /**
      * Checks if package is quarantined for a specific user.
+     *
+     * @throws PackageManager.NameNotFoundException if the package is not found
      */
-    public abstract boolean isPackageQuarantined(@NonNull String packageName,
-            @UserIdInt int userId);
+    public abstract boolean isPackageQuarantined(@NonNull String packageName, @UserIdInt int userId)
+            throws PackageManager.NameNotFoundException;
 
     /**
      * Checks if package is stopped for a specific user.
+     *
+     * @throws PackageManager.NameNotFoundException if the package is not found
      */
-    public abstract boolean isPackageStopped(@NonNull String packageName, @UserIdInt int userId);
+    public abstract boolean isPackageStopped(@NonNull String packageName, @UserIdInt int userId)
+            throws PackageManager.NameNotFoundException;
 
     /**
      * Sends the PACKAGE_RESTARTED broadcast.
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index e9d4d76..5a44ac8 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -17,6 +17,8 @@
 package com.android.server;
 
 import static android.os.Flags.stateOfHealthPublic;
+import static android.os.Flags.batteryServiceSupportCurrentAdbCommand;
+
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import static com.android.server.health.Utils.copyV1Battery;
 
@@ -166,6 +168,7 @@
     private int mLowBatteryCloseWarningLevel;
     private int mBatteryNearlyFullLevel;
     private int mShutdownBatteryTemperature;
+    private boolean mShutdownIfNoPower;
 
     private static String sSystemUiPackage;
 
@@ -230,6 +233,8 @@
                 com.android.internal.R.integer.config_lowBatteryCloseWarningBump);
         mShutdownBatteryTemperature = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_shutdownBatteryTemperature);
+        mShutdownIfNoPower = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_shutdownIfNoPower);
         sSystemUiPackage = mContext.getResources().getString(
                 com.android.internal.R.string.config_systemUi);
 
@@ -391,6 +396,9 @@
         if (mHealthInfo.batteryCapacityLevel != BatteryCapacityLevel.UNSUPPORTED) {
             return (mHealthInfo.batteryCapacityLevel == BatteryCapacityLevel.CRITICAL);
         }
+        if (!mShutdownIfNoPower) {
+            return false;
+        }
         if (mHealthInfo.batteryLevel > 0) {
             return false;
         }
@@ -920,9 +928,12 @@
         pw.println("Battery service (battery) commands:");
         pw.println("  help");
         pw.println("    Print this help text.");
-        pw.println("  get [-f] [ac|usb|wireless|dock|status|level|temp|present|counter|invalid]");
-        pw.println("  set [-f] "
-                + "[ac|usb|wireless|dock|status|level|temp|present|counter|invalid] <value>");
+        String getSetOptions = "ac|usb|wireless|dock|status|level|temp|present|counter|invalid";
+        if (batteryServiceSupportCurrentAdbCommand()) {
+            getSetOptions += "|current_now|current_average";
+        }
+        pw.println("  get [-f] [" + getSetOptions + "]");
+        pw.println("  set [-f] [" + getSetOptions + "] <value>");
         pw.println("    Force a battery property value, freezing battery state.");
         pw.println("    -f: force a battery change broadcast be sent, prints new sequence.");
         pw.println("  unplug [-f]");
@@ -963,6 +974,7 @@
                 unplugBattery(/* forceUpdate= */ (opts & OPTION_FORCE_UPDATE) != 0, pw);
             } break;
             case "get": {
+                final int opts = parseOptions(shell);
                 final String key = shell.getNextArg();
                 if (key == null) {
                     pw.println("No property specified");
@@ -994,6 +1006,22 @@
                     case "counter":
                         pw.println(mHealthInfo.batteryChargeCounterUah);
                         break;
+                    case "current_now":
+                        if (batteryServiceSupportCurrentAdbCommand()) {
+                            if ((opts & OPTION_FORCE_UPDATE) != 0) {
+                                updateHealthInfo();
+                            }
+                            pw.println(mHealthInfo.batteryCurrentMicroamps);
+                        }
+                        break;
+                    case "current_average":
+                        if (batteryServiceSupportCurrentAdbCommand()) {
+                            if ((opts & OPTION_FORCE_UPDATE) != 0) {
+                                updateHealthInfo();
+                            }
+                            pw.println(mHealthInfo.batteryCurrentAverageMicroamps);
+                        }
+                        break;
                     case "temp":
                         pw.println(mHealthInfo.batteryTemperatureTenthsCelsius);
                         break;
@@ -1051,6 +1079,16 @@
                         case "counter":
                             mHealthInfo.batteryChargeCounterUah = Integer.parseInt(value);
                             break;
+                        case "current_now":
+                            if (batteryServiceSupportCurrentAdbCommand()) {
+                                mHealthInfo.batteryCurrentMicroamps = Integer.parseInt(value);
+                            }
+                            break;
+                        case "current_average":
+                            if (batteryServiceSupportCurrentAdbCommand()) {
+                                mHealthInfo.batteryCurrentAverageMicroamps =
+                                        Integer.parseInt(value);
+                            }
                         case "temp":
                             mHealthInfo.batteryTemperatureTenthsCelsius = Integer.parseInt(value);
                             break;
@@ -1094,6 +1132,14 @@
         return 0;
     }
 
+    private void updateHealthInfo() {
+        try {
+            mHealthServiceWrapper.scheduleUpdate();
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Unable to update health service data.", e);
+        }
+    }
+
     private void setChargerAcOnline(boolean online, boolean forceUpdate) {
         if (!mUpdatesStopped) {
             copyV1Battery(mLastHealthInfo, mHealthInfo);
diff --git a/services/core/java/com/android/server/BootReceiver.java b/services/core/java/com/android/server/BootReceiver.java
index 9f279b1..329aac6 100644
--- a/services/core/java/com/android/server/BootReceiver.java
+++ b/services/core/java/com/android/server/BootReceiver.java
@@ -48,6 +48,8 @@
 import com.android.modules.utils.TypedXmlPullParser;
 import com.android.modules.utils.TypedXmlSerializer;
 import com.android.server.am.DropboxRateLimiter;
+import com.android.server.os.TombstoneProtos;
+import com.android.server.os.TombstoneProtos.Tombstone;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -60,11 +62,14 @@
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.attribute.PosixFilePermissions;
+import java.util.AbstractMap;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.Map;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 
 /**
  * Performs a number of miscellaneous, non-system-critical actions
@@ -332,12 +337,12 @@
      *
      * @param ctx Context
      * @param tombstone path to the tombstone
-     * @param proto whether the tombstone is stored as proto
+     * @param tombstoneProto the parsed proto tombstone
      * @param processName the name of the process corresponding to the tombstone
      * @param tmpFileLock the lock for reading/writing tmp files
      */
     public static void addTombstoneToDropBox(
-                Context ctx, File tombstone, boolean proto, String processName,
+                Context ctx, File tombstone, Tombstone tombstoneProto, String processName,
                 ReentrantLock tmpFileLock) {
         final DropBoxManager db = ctx.getSystemService(DropBoxManager.class);
         if (db == null) {
@@ -347,31 +352,33 @@
 
         // Check if we should rate limit and abort early if needed.
         DropboxRateLimiter.RateLimitResult rateLimitResult =
-                sDropboxRateLimiter.shouldRateLimit(
-                        proto ? TAG_TOMBSTONE_PROTO_WITH_HEADERS : TAG_TOMBSTONE, processName);
+                sDropboxRateLimiter.shouldRateLimit(TAG_TOMBSTONE_PROTO_WITH_HEADERS, processName);
         if (rateLimitResult.shouldRateLimit()) return;
 
         HashMap<String, Long> timestamps = readTimestamps();
         try {
-            if (proto) {
-                if (recordFileTimestamp(tombstone, timestamps)) {
-                    // We need to attach the count indicating the number of dropped dropbox entries
-                    // due to rate limiting. Do this by enclosing the proto tombsstone in a
-                    // container proto that has the dropped entry count and the proto tombstone as
-                    // bytes (to avoid the complexity of reading and writing nested protos).
-                    tmpFileLock.lock();
-                    try {
-                        addAugmentedProtoToDropbox(tombstone, db, rateLimitResult);
-                    } finally {
-                        tmpFileLock.unlock();
-                    }
+            // Remove the memory data from the proto.
+            Tombstone tombstoneProtoWithoutMemory = removeMemoryFromTombstone(tombstoneProto);
+
+            final byte[] tombstoneBytes = tombstoneProtoWithoutMemory.toByteArray();
+
+            // Use JNI to call the c++ proto to text converter and add the headers to the tombstone.
+            String tombstoneWithoutMemory = new StringBuilder(getBootHeadersToLogAndUpdate())
+                    .append(rateLimitResult.createHeader())
+                    .append(getTombstoneText(tombstoneBytes))
+                    .toString();
+
+            // Add the tombstone without memory data to dropbox.
+            db.addText(TAG_TOMBSTONE, tombstoneWithoutMemory);
+
+            // Add the tombstone proto to dropbox.
+            if (recordFileTimestamp(tombstone, timestamps)) {
+                tmpFileLock.lock();
+                try {
+                    addAugmentedProtoToDropbox(tombstone, tombstoneBytes, db, rateLimitResult);
+                } finally {
+                    tmpFileLock.unlock();
                 }
-            } else {
-                // Add the header indicating how many events have been dropped due to rate limiting.
-                final String headers = getBootHeadersToLogAndUpdate()
-                        + rateLimitResult.createHeader();
-                addFileToDropBox(db, timestamps, headers, tombstone.getPath(), LOG_SIZE,
-                                 TAG_TOMBSTONE);
             }
         } catch (IOException e) {
             Slog.e(TAG, "Can't log tombstone", e);
@@ -380,11 +387,8 @@
     }
 
     private static void addAugmentedProtoToDropbox(
-                File tombstone, DropBoxManager db,
+                File tombstone, byte[] tombstoneBytes, DropBoxManager db,
                 DropboxRateLimiter.RateLimitResult rateLimitResult) throws IOException {
-        // Read the proto tombstone file as bytes.
-        final byte[] tombstoneBytes = Files.readAllBytes(tombstone.toPath());
-
         final File tombstoneProtoWithHeaders = File.createTempFile(
                 tombstone.getName(), ".tmp", TOMBSTONE_TMP_DIR);
         Files.setPosixFilePermissions(
@@ -417,6 +421,8 @@
         }
     }
 
+    private static native String getTombstoneText(byte[] tombstoneBytes);
+
     private static void addLastkToDropBox(
             DropBoxManager db, HashMap<String, Long> timestamps,
             String headers, String footers, String filename, int maxSize,
@@ -434,6 +440,31 @@
         addFileWithFootersToDropBox(db, timestamps, headers, footers, filename, maxSize, tag);
     }
 
+    /** Removes memory information from the Tombstone proto. */
+    @VisibleForTesting
+    public static Tombstone removeMemoryFromTombstone(Tombstone tombstoneProto) {
+        Tombstone.Builder tombstoneBuilder = tombstoneProto.toBuilder()
+                .clearMemoryMappings()
+                .clearThreads()
+                .putAllThreads(tombstoneProto.getThreadsMap().entrySet()
+                        .stream()
+                        .map(BootReceiver::clearMemoryDump)
+                        .collect(Collectors.toMap(e->e.getKey(), e->e.getValue())));
+
+        if (tombstoneProto.hasSignalInfo()) {
+            tombstoneBuilder.setSignalInfo(
+                    tombstoneProto.getSignalInfo().toBuilder().clearFaultAdjacentMetadata());
+        }
+
+        return tombstoneBuilder.build();
+    }
+
+    private static AbstractMap.SimpleEntry<Integer, TombstoneProtos.Thread> clearMemoryDump(
+            Map.Entry<Integer, TombstoneProtos.Thread> e) {
+        return new AbstractMap.SimpleEntry<Integer, TombstoneProtos.Thread>(
+            e.getKey(), e.getValue().toBuilder().clearMemoryDump().build());
+    }
+
     private static void addFileToDropBox(
             DropBoxManager db, HashMap<String, Long> timestamps,
             String headers, String filename, int maxSize, String tag) throws IOException {
diff --git a/services/core/java/com/android/server/TEST_MAPPING b/services/core/java/com/android/server/TEST_MAPPING
index 708da19..5e9d1cb 100644
--- a/services/core/java/com/android/server/TEST_MAPPING
+++ b/services/core/java/com/android/server/TEST_MAPPING
@@ -110,6 +110,9 @@
         },
         {
             "name": "FrameworksNetTests"
+        },
+        {
+            "name": "CtsSuspendAppsTestCases"
         }
     ],
     "presubmit-large": [
@@ -150,9 +153,6 @@
             "name": "CtsPackageManagerTestCases"
         },
         {
-            "name": "CtsSuspendAppsTestCases"
-        },
-        {
             "name": "FrameworksServicesTests",
             "options": [
                 {
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index 4bb9f4f..c436c72 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -127,6 +127,7 @@
         "/system/bin/mediaserver",
         "/system/bin/netd",
         "/system/bin/sdcard",
+        "/system/bin/servicemanager",
         "/system/bin/surfaceflinger",
         "/system/bin/vold",
         "media.extractor", // system/bin/mediaextractor
diff --git a/services/core/java/com/android/server/adb/AdbDebuggingManager.java b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
index 3280afdf..627a62e 100644
--- a/services/core/java/com/android/server/adb/AdbDebuggingManager.java
+++ b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
@@ -42,6 +42,7 @@
 import android.debug.AdbNotifications;
 import android.debug.AdbProtoEnums;
 import android.debug.AdbTransportType;
+import android.debug.IAdbTransport;
 import android.debug.PairDevice;
 import android.net.ConnectivityManager;
 import android.net.LocalSocket;
@@ -66,6 +67,7 @@
 import android.os.UserManager;
 import android.provider.Settings;
 import android.service.adb.AdbDebuggingManagerProto;
+import android.text.TextUtils;
 import android.util.AtomicFile;
 import android.util.Base64;
 import android.util.Slog;
@@ -679,16 +681,17 @@
                             return;
                         }
 
-                        // Check for network change
-                        String bssid = wifiInfo.getBSSID();
-                        if (bssid == null || bssid.isEmpty()) {
-                            Slog.e(TAG, "Unable to get the wifi ap's BSSID. Disabling adbwifi.");
-                            Settings.Global.putInt(mContentResolver,
-                                    Settings.Global.ADB_WIFI_ENABLED, 0);
-                            return;
-                        }
                         synchronized (mAdbConnectionInfo) {
-                            if (!bssid.equals(mAdbConnectionInfo.getBSSID())) {
+                            // Check for network change
+                            final String bssid = wifiInfo.getBSSID();
+                            if (TextUtils.isEmpty(bssid)) {
+                                Slog.e(TAG,
+                                        "Unable to get the wifi ap's BSSID. Disabling adbwifi.");
+                                Settings.Global.putInt(mContentResolver,
+                                        Settings.Global.ADB_WIFI_ENABLED, 0);
+                                return;
+                            }
+                            if (!TextUtils.equals(bssid, mAdbConnectionInfo.getBSSID())) {
                                 Slog.i(TAG, "Detected wifi network change. Disabling adbwifi.");
                                 Settings.Global.putInt(mContentResolver,
                                         Settings.Global.ADB_WIFI_ENABLED, 0);
@@ -1397,7 +1400,7 @@
             }
 
             String bssid = wifiInfo.getBSSID();
-            if (bssid == null || bssid.isEmpty()) {
+            if (TextUtils.isEmpty(bssid)) {
                 Slog.e(TAG, "Unable to get the wifi ap's BSSID.");
                 return null;
             }
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 7191684..df8f17a 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -5175,6 +5175,8 @@
             return null;
         }
 
+        final long startTimeNs = SystemClock.elapsedRealtimeNanos();
+
         if (DEBUG_SERVICE) {
             Slog.v(TAG_SERVICE, "Bringing up " + r + " " + r.intent + " fg=" + r.fgRequired);
         }
@@ -5333,9 +5335,14 @@
                 bringDownServiceLocked(r, enqueueOomAdj);
                 return msg;
             }
+            mAm.mProcessList.getAppStartInfoTracker().handleProcessServiceStart(startTimeNs, app, r,
+                    hostingRecord, true);
             if (isolated) {
                 r.isolationHostProc = app;
             }
+        } else {
+            mAm.mProcessList.getAppStartInfoTracker().handleProcessServiceStart(startTimeNs, app, r,
+                    hostingRecord, false);
         }
 
         if (r.fgRequired) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 3e533a6..2ee39c57 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -421,6 +421,7 @@
 import com.android.internal.os.TimeoutRecord;
 import com.android.internal.os.TransferPipe;
 import com.android.internal.os.Zygote;
+import com.android.internal.pm.pkg.parsing.ParsingPackageUtils;
 import com.android.internal.policy.AttributeCache;
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.internal.util.ArrayUtils;
@@ -468,7 +469,6 @@
 import com.android.server.pm.permission.PermissionManagerServiceInternal;
 import com.android.server.pm.pkg.AndroidPackage;
 import com.android.server.pm.pkg.SELinuxUtil;
-import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
 import com.android.server.pm.snapshot.PackageDataSnapshot;
 import com.android.server.power.stats.BatteryStatsImpl;
 import com.android.server.sdksandbox.SdkSandboxManagerLocal;
@@ -1103,9 +1103,51 @@
 
     private final ActivityMetricsLaunchObserver mActivityLaunchObserver =
             new ActivityMetricsLaunchObserver() {
+
         @Override
-        public void onActivityLaunched(long id, ComponentName name, int temperature) {
+        public void onIntentStarted(@NonNull Intent intent, long timestampNanos) {
+            synchronized (this) {
+                mProcessList.getAppStartInfoTracker().onIntentStarted(intent, timestampNanos);
+            }
+        }
+
+        @Override
+        public void onIntentFailed(long id) {
+            mProcessList.getAppStartInfoTracker().onIntentFailed(id);
+        }
+
+        @Override
+        public void onActivityLaunched(long id, ComponentName name, int temperature, int userId) {
             mAppProfiler.onActivityLaunched();
+            synchronized (ActivityManagerService.this) {
+                ProcessRecord record = null;
+                try {
+                    record = getProcessRecordLocked(name.getPackageName(), mContext
+                            .getPackageManager().getPackageUidAsUser(name.getPackageName(), 0,
+                            userId));
+                } catch (NameNotFoundException nnfe) {
+                    // Ignore, record will be lost.
+                }
+                mProcessList.getAppStartInfoTracker().onActivityLaunched(id, name, temperature,
+                        record);
+            }
+        }
+
+        @Override
+        public void onActivityLaunchCancelled(long id) {
+            mProcessList.getAppStartInfoTracker().onActivityLaunchCancelled(id);
+        }
+
+        @Override
+        public void onActivityLaunchFinished(long id, ComponentName name, long timestampNanos,
+                int launchMode) {
+            mProcessList.getAppStartInfoTracker().onActivityLaunchFinished(id, name,
+                    timestampNanos, launchMode);
+        }
+
+        @Override
+        public void onReportFullyDrawn(long id, long timestampNanos) {
+            mProcessList.getAppStartInfoTracker().onReportFullyDrawn(id, timestampNanos);
         }
     };
 
@@ -4488,13 +4530,13 @@
     @GuardedBy("this")
     private void attachApplicationLocked(@NonNull IApplicationThread thread,
             int pid, int callingUid, long startSeq) {
-
         // Find the application record that is being attached...  either via
         // the pid if we are running in multiple processes, or just pull the
         // next app record if we are emulating process with anonymous threads.
         ProcessRecord app;
         long startTime = SystemClock.uptimeMillis();
         long bindApplicationTimeMillis;
+        long bindApplicationTimeNanos;
         if (pid != MY_PID && pid >= 0) {
             synchronized (mPidsSelfLocked) {
                 app = mPidsSelfLocked.get(pid);
@@ -4698,6 +4740,7 @@
 
             checkTime(startTime, "attachApplicationLocked: immediately before bindApplication");
             bindApplicationTimeMillis = SystemClock.uptimeMillis();
+            bindApplicationTimeNanos = SystemClock.elapsedRealtimeNanos();
             mAtmInternal.preBindApplication(app.getWindowProcessController());
             final ActiveInstrumentation instr2 = app.getActiveInstrumentation();
             if (mPlatformCompat != null) {
@@ -4754,6 +4797,8 @@
             }
 
             app.setBindApplicationTime(bindApplicationTimeMillis);
+            mProcessList.getAppStartInfoTracker()
+                    .reportBindApplicationTimeNanos(app, bindApplicationTimeNanos);
 
             // Make app active after binding application or client may be running requests (e.g
             // starting activities) before it is ready.
@@ -9799,12 +9844,12 @@
             final int uid = enforceDumpPermissionForPackage(packageName, userId, callingUid,
                         "getHistoricalProcessStartReasons");
             if (uid != INVALID_UID) {
-                mProcessList.mAppStartInfoTracker.getStartInfo(
+                mProcessList.getAppStartInfoTracker().getStartInfo(
                         packageName, userId, callingPid, maxNum, results);
             }
         } else {
             // If no package name is given, use the caller's uid as the filter uid.
-            mProcessList.mAppStartInfoTracker.getStartInfo(
+            mProcessList.getAppStartInfoTracker().getStartInfo(
                     packageName, callingUid, callingPid, maxNum, results);
         }
         return new ParceledListSlice<ApplicationStartInfo>(results);
@@ -9822,7 +9867,7 @@
         }
 
         final int callingUid = Binder.getCallingUid();
-        mProcessList.mAppStartInfoTracker.addStartInfoCompleteListener(listener, callingUid);
+        mProcessList.getAppStartInfoTracker().addStartInfoCompleteListener(listener, callingUid);
     }
 
 
@@ -9836,7 +9881,7 @@
         }
 
         final int callingUid = Binder.getCallingUid();
-        mProcessList.mAppStartInfoTracker.clearStartInfoCompleteListener(callingUid, true);
+        mProcessList.getAppStartInfoTracker().clearStartInfoCompleteListener(callingUid, true);
     }
 
     @Override
@@ -10138,7 +10183,7 @@
             pw.println();
             if (dumpAll) {
                 pw.println("-------------------------------------------------------------------------------");
-                mProcessList.mAppStartInfoTracker.dumpHistoryProcessStartInfo(pw, dumpPackage);
+                mProcessList.getAppStartInfoTracker().dumpHistoryProcessStartInfo(pw, dumpPackage);
                 pw.println("-------------------------------------------------------------------------------");
                 mProcessList.mAppExitInfoTracker.dumpHistoryProcessExitInfo(pw, dumpPackage);
             }
@@ -10541,7 +10586,7 @@
                     dumpPackage = args[opti];
                     opti++;
                 }
-                mProcessList.mAppStartInfoTracker.dumpHistoryProcessStartInfo(pw, dumpPackage);
+                mProcessList.getAppStartInfoTracker().dumpHistoryProcessStartInfo(pw, dumpPackage);
             } else if ("exit-info".equals(cmd)) {
                 if (opti < args.length) {
                     dumpPackage = args[opti];
@@ -11972,6 +12017,7 @@
         boolean dumpSwapPss;
         boolean dumpProto;
         boolean mDumpPrivateDirty;
+        boolean mDumpAllocatorStats;
     }
 
     @NeverCompile // Avoid size overhead of debugging code.
@@ -11991,6 +12037,7 @@
         opts.dumpSwapPss = false;
         opts.dumpProto = asProto;
         opts.mDumpPrivateDirty = false;
+        opts.mDumpAllocatorStats = false;
 
         int opti = 0;
         while (opti < args.length) {
@@ -12027,7 +12074,8 @@
                 opts.isCheckinRequest = true;
             } else if ("--proto".equals(opt)) {
                 opts.dumpProto = true;
-
+            } else if ("--logstats".equals(opt)) {
+                opts.mDumpAllocatorStats = true;
             } else if ("-h".equals(opt)) {
                 pw.println("meminfo dump options: [-a] [-d] [-c] [-s] [--oom] [process]");
                 pw.println("  -a: include all available information for each process.");
@@ -12238,7 +12286,8 @@
                             try {
                                 thread.dumpMemInfo(tp.getWriteFd(),
                                         mi, opts.isCheckinRequest, opts.dumpFullDetails,
-                                        opts.dumpDalvik, opts.dumpSummaryOnly, opts.dumpUnreachable, innerArgs);
+                                        opts.dumpDalvik, opts.dumpSummaryOnly, opts.dumpUnreachable,
+                                        opts.mDumpAllocatorStats, innerArgs);
                                 tp.go(fd, opts.dumpUnreachable ? 30000 : 5000);
                             } finally {
                                 tp.kill();
@@ -13827,6 +13876,7 @@
     // activity manager to announce its creation.
     public boolean bindBackupAgent(String packageName, int backupMode, int targetUserId,
             @BackupDestination int backupDestination) {
+        long startTimeNs = SystemClock.elapsedRealtimeNanos();
         if (DEBUG_BACKUP) {
             Slog.v(TAG, "bindBackupAgent: app=" + packageName + " mode=" + backupMode
                     + " targetUserId=" + targetUserId + " callingUid = " + Binder.getCallingUid()
@@ -13902,15 +13952,20 @@
                             ? new ComponentName(app.packageName, app.backupAgentName)
                             : new ComponentName("android", "FullBackupAgent");
 
-            // startProcessLocked() returns existing proc's record if it's already running
-            ProcessRecord proc = startProcessLocked(app.processName, app,
-                    false, 0,
-                    new HostingRecord(HostingRecord.HOSTING_TYPE_BACKUP, hostingName),
-                    ZYGOTE_POLICY_FLAG_SYSTEM_PROCESS, false, false);
+            ProcessRecord proc = getProcessRecordLocked(app.processName, app.uid);
+            boolean isProcessStarted = proc != null;
+            if (!isProcessStarted) {
+                proc = startProcessLocked(app.processName, app,
+                  false, 0,
+                  new HostingRecord(HostingRecord.HOSTING_TYPE_BACKUP, hostingName),
+                  ZYGOTE_POLICY_FLAG_SYSTEM_PROCESS, false, false);
+            }
             if (proc == null) {
                 Slog.e(TAG, "Unable to start backup agent process " + r);
                 return false;
             }
+            mProcessList.getAppStartInfoTracker().handleProcessBackupStart(startTimeNs, proc, r,
+                    !isProcessStarted);
 
             // If the app is a regular app (uid >= 10000) and not the system server or phone
             // process, etc, then mark it as being in full backup so that certain calls to the
@@ -17510,6 +17565,8 @@
      *         other {@code ActivityManager#USER_OP_*} codes for failure.
      *
      */
+    // TODO(b/302662311): Add javadoc changes corresponding to the user property that allows
+    // delayed locking behavior once the private space flag is finalized.
     @Override
     public int stopUserWithDelayedLocking(final int userId, boolean force,
             final IStopUserCallback callback) {
@@ -18735,8 +18792,12 @@
                     // If the process is known as top app, set a hint so when the process is
                     // started, the top priority can be applied immediately to avoid cpu being
                     // preempted by other processes before attaching the process of top app.
-                    startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */,
-                            new HostingRecord(hostingType, hostingName, isTop),
+                    final long startTimeNs = SystemClock.elapsedRealtimeNanos();
+                    HostingRecord hostingRecord =
+                            new HostingRecord(hostingType, hostingName, isTop);
+                    ProcessRecord rec = getProcessRecordLocked(processName, info.uid);
+                    ProcessRecord app = startProcessLocked(processName, info, knownToBeDead,
+                            0 /* intentFlags */, hostingRecord,
                             ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE, false /* allowWhileBooting */,
                             false /* isolated */);
                 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index f3b2ef3..ae0cd65 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -1362,7 +1362,7 @@
             }
             userId = user.id;
         }
-        mInternal.mProcessList.mAppStartInfoTracker
+        mInternal.mProcessList.getAppStartInfoTracker()
                 .clearHistoryProcessStartInfo(packageName, userId);
         return 0;
     }
diff --git a/services/core/java/com/android/server/am/AppStartInfoTracker.java b/services/core/java/com/android/server/am/AppStartInfoTracker.java
index edca74f..82e554e 100644
--- a/services/core/java/com/android/server/am/AppStartInfoTracker.java
+++ b/services/core/java/com/android/server/am/AppStartInfoTracker.java
@@ -22,11 +22,12 @@
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 
-import android.app.ActivityOptions;
+import android.annotation.NonNull;
 import android.app.ApplicationStartInfo;
 import android.app.Flags;
 import android.app.IApplicationStartInfoCompleteListener;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -138,6 +139,15 @@
     /** The path to the historical proc start info file, persisted in the storage. */
     @VisibleForTesting File mProcStartInfoFile;
 
+
+    /**
+     * Temporary list of records that have not been completed.
+     *
+     * Key is timestamp of launch from {@link #ActivityMetricsLaunchObserver}.
+     */
+    @GuardedBy("mLock")
+    private ArrayMap<Long, ApplicationStartInfo> mInProgRecords = new ArrayMap<>();
+
     AppStartInfoTracker() {
         mCallbacks = new SparseArray<>();
         mData = new ProcessMap<AppStartInfoContainer>();
@@ -174,68 +184,99 @@
         });
     }
 
-    void handleProcessColdStarted(long startTimeNs, HostingRecord hostingRecord,
-            ProcessRecord app) {
-        synchronized (mLock) {
-            if (!mEnabled) {
-                return;
-            }
-            ApplicationStartInfo start = new ApplicationStartInfo();
-            addBaseFieldsFromProcessRecord(start, app);
-            start.setStartupState(ApplicationStartInfo.STARTUP_STATE_STARTED);
-            start.addStartupTimestamp(
-                    ApplicationStartInfo.START_TIMESTAMP_LAUNCH, startTimeNs);
-            start.addStartupTimestamp(
-                    ApplicationStartInfo.START_TIMESTAMP_FORK, app.getStartElapsedTime());
-            start.setStartType(ApplicationStartInfo.START_TYPE_COLD);
-            start.setReason(ApplicationStartInfo.START_REASON_OTHER);
-            addStartInfoLocked(start);
-        }
-    }
-
-    public void handleProcessActivityWarmOrHotStarted(long startTimeNs,
-            ActivityOptions activityOptions, Intent intent) {
+    void onIntentStarted(@NonNull Intent intent, long timestampNanos) {
         synchronized (mLock) {
             if (!mEnabled) {
                 return;
             }
             ApplicationStartInfo start = new ApplicationStartInfo();
             start.setStartupState(ApplicationStartInfo.STARTUP_STATE_STARTED);
-            start.addStartupTimestamp(
-                    ApplicationStartInfo.START_TIMESTAMP_LAUNCH, startTimeNs);
             start.setIntent(intent);
-            start.setReason(ApplicationStartInfo.START_REASON_LAUNCHER);
-            if (activityOptions != null) {
-                start.setProcessName(activityOptions.getPackageName());
-            }
-            start.setStartType(ApplicationStartInfo.START_TYPE_WARM);
+            start.setStartType(ApplicationStartInfo.START_TYPE_UNSET);
+            start.addStartupTimestamp(ApplicationStartInfo.START_TIMESTAMP_LAUNCH, timestampNanos);
             if (intent != null && intent.getCategories() != null
                     && intent.getCategories().contains(Intent.CATEGORY_LAUNCHER)) {
                 start.setReason(ApplicationStartInfo.START_REASON_LAUNCHER);
             } else {
                 start.setReason(ApplicationStartInfo.START_REASON_START_ACTIVITY);
             }
-            addStartInfoLocked(start);
+            mInProgRecords.put(timestampNanos, start);
         }
     }
 
-    public void handleProcessActivityStartedFromRecents(long startTimeNs,
-            ActivityOptions activityOptions) {
+    void onIntentFailed(long id) {
         synchronized (mLock) {
             if (!mEnabled) {
                 return;
             }
-            ApplicationStartInfo start = new ApplicationStartInfo();
-            start.setStartupState(ApplicationStartInfo.STARTUP_STATE_STARTED);
-            start.addStartupTimestamp(
-                    ApplicationStartInfo.START_TIMESTAMP_LAUNCH, startTimeNs);
-            if (activityOptions != null) {
-                start.setIntent(activityOptions.getResultData());
-                start.setProcessName(activityOptions.getPackageName());
+            if (!mInProgRecords.containsKey(id)) {
+                return;
             }
-            start.setReason(ApplicationStartInfo.START_REASON_LAUNCHER_RECENTS);
-            start.setStartType(ApplicationStartInfo.START_TYPE_WARM);
-            addStartInfoLocked(start);
+            mInProgRecords.get(id).setStartupState(ApplicationStartInfo.STARTUP_STATE_ERROR);
+            mInProgRecords.remove(id);
+        }
+    }
+
+    void onActivityLaunched(long id, ComponentName name, long temperature, ProcessRecord app) {
+        synchronized (mLock) {
+            if (!mEnabled) {
+                return;
+            }
+            if (!mInProgRecords.containsKey(id)) {
+                return;
+            }
+            if (app != null) {
+                ApplicationStartInfo info = mInProgRecords.get(id);
+                info.setStartType((int) temperature);
+                addBaseFieldsFromProcessRecord(info, app);
+                addStartInfoLocked(info);
+            } else {
+                mInProgRecords.remove(id);
+            }
+        }
+    }
+
+    void onActivityLaunchCancelled(long id) {
+        synchronized (mLock) {
+            if (!mEnabled) {
+                return;
+            }
+            if (!mInProgRecords.containsKey(id)) {
+                return;
+            }
+            ApplicationStartInfo info = mInProgRecords.get(id);
+            info.setStartupState(ApplicationStartInfo.STARTUP_STATE_ERROR);
+            mInProgRecords.remove(id);
+        }
+    }
+
+    void onActivityLaunchFinished(long id, ComponentName name, long timestampNanos,
+            int launchMode) {
+        synchronized (mLock) {
+            if (!mEnabled) {
+                return;
+            }
+            if (!mInProgRecords.containsKey(id)) {
+                return;
+            }
+            ApplicationStartInfo info = mInProgRecords.get(id);
+            info.setStartupState(ApplicationStartInfo.STARTUP_STATE_FIRST_FRAME_DRAWN);
+            info.setLaunchMode(launchMode);
+        }
+    }
+
+    void onReportFullyDrawn(long id, long timestampNanos) {
+        synchronized (mLock) {
+            if (!mEnabled) {
+                return;
+            }
+            if (!mInProgRecords.containsKey(id)) {
+                return;
+            }
+            ApplicationStartInfo info = mInProgRecords.get(id);
+            info.addStartupTimestamp(ApplicationStartInfo.START_TIMESTAMP_FULLY_DRAWN,
+                    timestampNanos);
+            mInProgRecords.remove(id);
         }
     }
 
@@ -347,7 +388,8 @@
                 ApplicationStartInfo.START_TIMESTAMP_APPLICATION_ONCREATE);
     }
 
-    void reportBindApplicationTimeNanos(ProcessRecord app, long timeNs) {
+    /** Report a bind application timestamp to add to {@link ApplicationStartInfo}. */
+    public void reportBindApplicationTimeNanos(ProcessRecord app, long timeNs) {
         addTimestampToStart(app, timeNs,
                 ApplicationStartInfo.START_TIMESTAMP_BIND_APPLICATION);
     }
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index f8f3d82..eea9337 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -33,6 +33,7 @@
 import android.annotation.NonNull;
 import android.annotation.RequiresNoPermission;
 import android.annotation.SuppressLint;
+import android.app.AlarmManager;
 import android.app.StatsManager;
 import android.app.usage.NetworkStatsManager;
 import android.bluetooth.BluetoothActivityEnergyInfo;
@@ -177,7 +178,6 @@
     final BatteryStatsImpl mStats;
     final CpuWakeupStats mCpuWakeupStats;
     private final PowerStatsStore mPowerStatsStore;
-    private final PowerStatsAggregator mPowerStatsAggregator;
     private final PowerStatsScheduler mPowerStatsScheduler;
     private final BatteryStatsImpl.UserInfoProvider mUserManagerUserInfoProvider;
     private final Context mContext;
@@ -186,6 +186,7 @@
     private final AtomicFile mConfigFile;
     private final BatteryStats.BatteryStatsDumpHelper mDumpHelper;
     private final PowerStatsUidResolver mPowerStatsUidResolver;
+    private final AggregatedPowerStatsConfig mAggregatedPowerStatsConfig;
 
     private volatile boolean mMonitorEnabled = true;
 
@@ -423,19 +424,12 @@
                 com.android.internal.R.integer.config_radioScanningTimeout) * 1000L);
         mStats.startTrackingSystemServerCpuTime();
 
-        AggregatedPowerStatsConfig aggregatedPowerStatsConfig = getAggregatedPowerStatsConfig();
-        mPowerStatsStore = new PowerStatsStore(systemDir, mHandler, aggregatedPowerStatsConfig);
-        mPowerStatsAggregator = new PowerStatsAggregator(aggregatedPowerStatsConfig,
-                mStats.getHistory());
-        final long aggregatedPowerStatsSpanDuration = context.getResources().getInteger(
-                com.android.internal.R.integer.config_aggregatedPowerStatsSpanDuration);
-        final long powerStatsAggregationPeriod = context.getResources().getInteger(
-                com.android.internal.R.integer.config_powerStatsAggregationPeriod);
-        mPowerStatsScheduler = new PowerStatsScheduler(context, mPowerStatsAggregator,
-                aggregatedPowerStatsSpanDuration, powerStatsAggregationPeriod, mPowerStatsStore,
-                Clock.SYSTEM_CLOCK, mMonotonicClock, mHandler, mStats);
+        mAggregatedPowerStatsConfig = createAggregatedPowerStatsConfig();
+        mPowerStatsStore = new PowerStatsStore(systemDir, mHandler, mAggregatedPowerStatsConfig);
+        mPowerStatsScheduler = createPowerStatsScheduler(mContext);
         PowerStatsExporter powerStatsExporter =
-                new PowerStatsExporter(mPowerStatsStore, mPowerStatsAggregator);
+                new PowerStatsExporter(mPowerStatsStore,
+                        new PowerStatsAggregator(mAggregatedPowerStatsConfig, mStats.getHistory()));
         mBatteryUsageStatsProvider = new BatteryUsageStatsProvider(context,
                 powerStatsExporter, mPowerProfile, mCpuScalingPolicies,
                 mPowerStatsStore, Clock.SYSTEM_CLOCK);
@@ -445,7 +439,25 @@
         mConfigFile = new AtomicFile(new File(systemDir, "battery_usage_stats_config"));
     }
 
-    private AggregatedPowerStatsConfig getAggregatedPowerStatsConfig() {
+    private PowerStatsScheduler createPowerStatsScheduler(Context context) {
+        final long aggregatedPowerStatsSpanDuration = context.getResources().getInteger(
+                com.android.internal.R.integer.config_aggregatedPowerStatsSpanDuration);
+        final long powerStatsAggregationPeriod = context.getResources().getInteger(
+                com.android.internal.R.integer.config_powerStatsAggregationPeriod);
+        PowerStatsScheduler.AlarmScheduler alarmScheduler =
+                (triggerAtMillis, tag, onAlarmListener, aHandler) -> {
+                    AlarmManager alarmManager = mContext.getSystemService(AlarmManager.class);
+                    alarmManager.set(AlarmManager.ELAPSED_REALTIME, triggerAtMillis, tag,
+                            onAlarmListener, aHandler);
+                };
+        return new PowerStatsScheduler(mStats::schedulePowerStatsSampleCollection,
+                new PowerStatsAggregator(mAggregatedPowerStatsConfig,
+                        mStats.getHistory()), aggregatedPowerStatsSpanDuration,
+                powerStatsAggregationPeriod, mPowerStatsStore, alarmScheduler, Clock.SYSTEM_CLOCK,
+                mMonotonicClock, () -> mStats.getHistory().getStartTime(), mHandler);
+    }
+
+    private AggregatedPowerStatsConfig createAggregatedPowerStatsConfig() {
         AggregatedPowerStatsConfig config = new AggregatedPowerStatsConfig();
         config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_CPU)
                 .trackDeviceStates(
@@ -884,6 +896,9 @@
                 SystemClock.elapsedRealtime(),
                 mWorker.getLastCollectionTimeStamp())) {
             syncStats("get-stats", BatteryExternalStatsWorker.UPDATE_ALL);
+            if (Flags.streamlinedBatteryStats()) {
+                mStats.collectPowerStatsSamples();
+            }
         }
 
         return mBatteryUsageStatsProvider.getBatteryUsageStats(mStats, queries);
@@ -2713,7 +2728,7 @@
         }
     }
 
-    private void dumpUsageStatsToProto(FileDescriptor fd, PrintWriter pw, int model,
+    private void dumpUsageStats(FileDescriptor fd, PrintWriter pw, int model,
             boolean proto) {
         awaitCompletion();
         syncStats("dump", BatteryExternalStatsWorker.UPDATE_ALL);
@@ -2729,6 +2744,12 @@
         synchronized (mStats) {
             mStats.prepareForDumpLocked();
         }
+        if (Flags.streamlinedBatteryStats()) {
+            // Important: perform this operation outside the mStats lock, because it will
+            // need to access BatteryStats from a handler thread
+            mStats.collectPowerStatsSamples();
+        }
+
         BatteryUsageStats batteryUsageStats =
                 mBatteryUsageStatsProvider.getBatteryUsageStats(mStats, query);
         if (proto) {
@@ -2933,7 +2954,7 @@
                             }
                         }
                     }
-                    dumpUsageStatsToProto(fd, pw, model, proto);
+                    dumpUsageStats(fd, pw, model, proto);
                     return;
                 } else if ("--wakeups".equals(arg)) {
                     mCpuWakeupStats.dump(new IndentingPrintWriter(pw, "  "),
diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java
index 903cb7b..982076d 100644
--- a/services/core/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java
@@ -30,7 +30,6 @@
 
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -164,12 +163,6 @@
                 WidgetFlags.MAGNIFIER_ASPECT_RATIO_DEFAULT));
 
         sDeviceConfigEntries.add(new DeviceConfigEntry<Boolean>(
-                DeviceConfig.NAMESPACE_SYSTEMUI,
-                SystemUiDeviceConfigFlags.REMOTEVIEWS_ADAPTER_CONVERSION,
-                SystemUiDeviceConfigFlags.KEY_REMOTEVIEWS_ADAPTER_CONVERSION, boolean.class,
-                SystemUiDeviceConfigFlags.REMOTEVIEWS_ADAPTER_CONVERSION_DEFAULT));
-
-        sDeviceConfigEntries.add(new DeviceConfigEntry<Boolean>(
                 TextFlags.NAMESPACE, TextFlags.ENABLE_NEW_CONTEXT_MENU,
                 TextFlags.KEY_ENABLE_NEW_CONTEXT_MENU, boolean.class,
                 TextFlags.ENABLE_NEW_CONTEXT_MENU_DEFAULT));
diff --git a/services/core/java/com/android/server/am/ForegroundServiceTypeLoggerModule.java b/services/core/java/com/android/server/am/ForegroundServiceTypeLoggerModule.java
index caafb42..fc8ad6bc 100644
--- a/services/core/java/com/android/server/am/ForegroundServiceTypeLoggerModule.java
+++ b/services/core/java/com/android/server/am/ForegroundServiceTypeLoggerModule.java
@@ -35,6 +35,7 @@
 import android.app.ForegroundServiceDelegationOptions;
 import android.content.ComponentName;
 import android.content.pm.ServiceInfo;
+import android.os.Trace;
 import android.util.ArrayMap;
 import android.util.IntArray;
 import android.util.LongArray;
@@ -134,6 +135,11 @@
      * call of the right type will also be associated and logged
      */
     public void logForegroundServiceStart(int uid, int pid, ServiceRecord record) {
+        if (record.getComponentName() != null) {
+            final String traceTag = record.getComponentName().flattenToString() + ":" + uid;
+            Trace.asyncTraceForTrackBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, traceTag,
+                    "foregroundService", record.foregroundServiceType);
+        }
         // initialize the UID stack
         UidState uidState = mUids.get(uid);
         if (uidState == null) {
@@ -205,6 +211,11 @@
         // we need to log all the API end events and remove the start events
         // then we remove the FGS from the various stacks
         // and also clean up the start calls stack by UID
+        if (record.getComponentName() != null) {
+            final String traceTag = record.getComponentName().flattenToString() + ":" + uid;
+            Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER,
+                    traceTag, record.hashCode());
+        }
         final IntArray apiTypes = convertFgsTypeToApiTypes(record.foregroundServiceType);
         final UidState uidState = mUids.get(uid);
         if (apiTypes.size() == 0) {
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 4ff34b1..3156e9d 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -498,7 +498,7 @@
 
     /** Manages the {@link android.app.ApplicationStartInfo} records. */
     @GuardedBy("mAppStartInfoTracker")
-    final AppStartInfoTracker mAppStartInfoTracker = new AppStartInfoTracker();
+    private final AppStartInfoTracker mAppStartInfoTracker = new AppStartInfoTracker();
 
     /**
      * The currently running SDK sandbox processes for a uid.
@@ -1523,6 +1523,10 @@
         return mCachedRestoreLevel;
     }
 
+    AppStartInfoTracker getAppStartInfoTracker() {
+        return mAppStartInfoTracker;
+    }
+
     /**
      * Set the out-of-memory badness adjustment for a process.
      * If {@code pid <= 0}, this method will be a no-op.
@@ -2572,6 +2576,7 @@
             boolean isSdkSandbox, int sdkSandboxUid, String sdkSandboxClientAppPackage,
             String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
         long startTime = SystemClock.uptimeMillis();
+        final long startTimeNs = SystemClock.elapsedRealtimeNanos();
         ProcessRecord app;
         if (!isolated) {
             app = getProcessRecordLocked(processName, info.uid);
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index b2082d9..b4cd6a3 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -401,7 +401,7 @@
     /**
      * All about the process state info (proc state, oom adj score) in this process.
      */
-    final ProcessStateRecord mState;
+    ProcessStateRecord mState;
 
     /**
      * All about the state info of the optimizer when the process is cached.
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 47a99fe..a6b532c 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -356,6 +356,8 @@
      * Once total number of unlocked users reach mMaxRunningUsers, least recently used user
      * will be locked.
      */
+    // TODO(b/302662311): Add javadoc changes corresponding to the user property that allows
+    // delayed locking behavior once the private space flag is finalized.
     @GuardedBy("mLock")
     private boolean mDelayUserDataLocking;
 
@@ -365,11 +367,12 @@
     private volatile boolean mAllowUserUnlocking;
 
     /**
-     * Keep track of last active users for mDelayUserDataLocking.
-     * The latest stopped user is placed in front while the least recently stopped user in back.
+     * Keep track of last active users for delayUserDataLocking.
+     * The most recently stopped user with delayed locking is placed in front, while the least
+     * recently stopped user in back.
      */
     @GuardedBy("mLock")
-    private final ArrayList<Integer> mLastActiveUsers = new ArrayList<>();
+    private final ArrayList<Integer> mLastActiveUsersForDelayedLocking = new ArrayList<>();
 
     /**
      * Map of userId to {@link UserCompletedEventType} event flags, indicating which as-yet-
@@ -1011,20 +1014,21 @@
         Slogf.i(TAG, "stopSingleUserLU userId=" + userId);
         final UserState uss = mStartedUsers.get(userId);
         if (uss == null) {  // User is not started
-            // If mDelayUserDataLocking is set and allowDelayedLocking is not set, we need to lock
-            // the requested user as the client wants to stop and lock the user. On the other hand,
-            // having keyEvictedCallback set will lead into locking user if mDelayUserDataLocking
-            // is set as that means client wants to lock the user immediately.
-            // If mDelayUserDataLocking is not set, the user was already locked when it was stopped
-            // and no further action is necessary.
-            if (mDelayUserDataLocking) {
+            // If canDelayDataLockingForUser() is true and allowDelayedLocking is false, we need
+            // to lock the requested user as the client wants to stop and lock the user. On the
+            // other hand, having keyEvictedCallback set will lead into locking user if
+            // canDelayDataLockingForUser() is true as that means client wants to lock the user
+            // immediately.
+            // If canDelayDataLockingForUser() is false, the user was already locked when it was
+            // stopped and no further action is necessary.
+            if (canDelayDataLockingForUser(userId)) {
                 if (allowDelayedLocking && keyEvictedCallback != null) {
                     Slogf.wtf(TAG, "allowDelayedLocking set with KeyEvictedCallback, ignore it"
                             + " and lock user:" + userId, new RuntimeException());
                     allowDelayedLocking = false;
                 }
                 if (!allowDelayedLocking) {
-                    if (mLastActiveUsers.remove(Integer.valueOf(userId))) {
+                    if (mLastActiveUsersForDelayedLocking.remove(Integer.valueOf(userId))) {
                         // should lock the user, user is already gone
                         final ArrayList<KeyEvictedCallback> keyEvictedCallbacks;
                         if (keyEvictedCallback != null) {
@@ -1354,14 +1358,21 @@
     @GuardedBy("mLock")
     private int updateUserToLockLU(@UserIdInt int userId, boolean allowDelayedLocking) {
         int userIdToLock = userId;
-        if (mDelayUserDataLocking && allowDelayedLocking && !getUserInfo(userId).isEphemeral()
+        // TODO: Decouple the delayed locking flows from mMaxRunningUsers or rename the property to
+        // state maximum running unlocked users specifically
+        if (canDelayDataLockingForUser(userIdToLock) && allowDelayedLocking
+                && !getUserInfo(userId).isEphemeral()
                 && !hasUserRestriction(UserManager.DISALLOW_RUN_IN_BACKGROUND, userId)) {
-            mLastActiveUsers.remove((Integer) userId); // arg should be object, not index
-            mLastActiveUsers.add(0, userId);
-            int totalUnlockedUsers = mStartedUsers.size() + mLastActiveUsers.size();
+            // arg should be object, not index
+            mLastActiveUsersForDelayedLocking.remove((Integer) userId);
+            mLastActiveUsersForDelayedLocking.add(0, userId);
+            int totalUnlockedUsers = mStartedUsers.size()
+                    + mLastActiveUsersForDelayedLocking.size();
             if (totalUnlockedUsers > mMaxRunningUsers) { // should lock a user
-                userIdToLock = mLastActiveUsers.get(mLastActiveUsers.size() - 1);
-                mLastActiveUsers.remove(mLastActiveUsers.size() - 1);
+                userIdToLock = mLastActiveUsersForDelayedLocking.get(
+                        mLastActiveUsersForDelayedLocking.size() - 1);
+                mLastActiveUsersForDelayedLocking
+                        .remove(mLastActiveUsersForDelayedLocking.size() - 1);
                 Slogf.i(TAG, "finishUserStopped, stopping user:" + userId
                         + " lock user:" + userIdToLock);
             } else {
@@ -1374,6 +1385,24 @@
     }
 
     /**
+     * Returns whether the user can have its CE storage left unlocked, even when it is stopped,
+     * either due to a global device configuration or an individual user's property.
+     */
+    private boolean canDelayDataLockingForUser(@UserIdInt int userIdToLock) {
+        if (allowBiometricUnlockForPrivateProfile()) {
+            final UserProperties userProperties = getUserProperties(userIdToLock);
+            return (mDelayUserDataLocking || (userProperties != null
+                    && userProperties.getAllowStoppingUserWithDelayedLocking()));
+        }
+        return mDelayUserDataLocking;
+    }
+
+    private boolean allowBiometricUnlockForPrivateProfile() {
+        return android.os.Flags.allowPrivateProfile()
+                && android.multiuser.Flags.enableBiometricsToUnlockPrivateSpace();
+    }
+
+    /**
      * Determines the list of users that should be stopped together with the specified
      * {@code userId}. The returned list includes {@code userId}.
      */
@@ -3161,7 +3190,7 @@
             pw.println("  mCurrentProfileIds:" + Arrays.toString(mCurrentProfileIds));
             pw.println("  mCurrentUserId:" + mCurrentUserId);
             pw.println("  mTargetUserId:" + mTargetUserId);
-            pw.println("  mLastActiveUsers:" + mLastActiveUsers);
+            pw.println("  mLastActiveUsersForDelayedLocking:" + mLastActiveUsersForDelayedLocking);
             pw.println("  mDelayUserDataLocking:" + mDelayUserDataLocking);
             pw.println("  mAllowUserUnlocking:" + mAllowUserUnlocking);
             pw.println("  shouldStopUserOnSwitch():" + shouldStopUserOnSwitch());
diff --git a/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java b/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java
index c7a560b..9f31f37 100644
--- a/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java
+++ b/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java
@@ -226,20 +226,28 @@
 
         List<AmbientContextManagerPerUserService> serviceList =
                 new ArrayList<>(serviceNames.length);
-        if (serviceNames.length == 2) {
+        if (serviceNames.length == 2
+                && !isDefaultService(serviceNames[0])
+                && !isDefaultWearableService(serviceNames[1])) {
             Slog.i(TAG, "Not using default services, "
                     + "services provided for testing should be exactly two services.");
-            if (!isDefaultService(serviceNames[0]) && !isDefaultWearableService(serviceNames[1])) {
-                serviceList.add(new DefaultAmbientContextManagerPerUserService(
-                        this, mLock, resolvedUserId,
-                        AmbientContextManagerPerUserService.ServiceType.DEFAULT, serviceNames[0]));
-                serviceList.add(new WearableAmbientContextManagerPerUserService(
-                        this, mLock, resolvedUserId,
-                        AmbientContextManagerPerUserService.ServiceType.WEARABLE,
-                        serviceNames[1]));
-            }
+            serviceList.add(
+                    new DefaultAmbientContextManagerPerUserService(
+                            this,
+                            mLock,
+                            resolvedUserId,
+                            AmbientContextManagerPerUserService.ServiceType.DEFAULT,
+                            serviceNames[0]));
+            serviceList.add(
+                    new WearableAmbientContextManagerPerUserService(
+                            this,
+                            mLock,
+                            resolvedUserId,
+                            AmbientContextManagerPerUserService.ServiceType.WEARABLE,
+                            serviceNames[1]));
             return serviceList;
-        } else {
+        }
+        if (serviceNames.length > 2) {
             Slog.i(TAG, "Incorrect number of services provided for testing.");
         }
 
diff --git a/services/core/java/com/android/server/app/GameManagerService.java b/services/core/java/com/android/server/app/GameManagerService.java
index 824bdd4..b3fb9c9 100644
--- a/services/core/java/com/android/server/app/GameManagerService.java
+++ b/services/core/java/com/android/server/app/GameManagerService.java
@@ -19,6 +19,7 @@
 import static android.content.Intent.ACTION_PACKAGE_ADDED;
 import static android.content.Intent.ACTION_PACKAGE_REMOVED;
 import static android.content.Intent.EXTRA_REPLACING;
+import static android.server.app.Flags.gameDefaultFrameRate;
 
 import static com.android.internal.R.styleable.GameModeConfig_allowGameAngleDriver;
 import static com.android.internal.R.styleable.GameModeConfig_allowGameDownscaling;
@@ -28,6 +29,7 @@
 import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
 
 import android.Manifest;
+import android.annotation.EnforcePermission;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -66,11 +68,13 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.os.PermissionEnforcer;
 import android.os.PowerManagerInternal;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ShellCallback;
+import android.os.SystemProperties;
 import android.os.UserManager;
 import android.provider.DeviceConfig;
 import android.provider.DeviceConfig.Properties;
@@ -138,6 +142,10 @@
     static final int WRITE_GAME_MODE_INTERVENTION_LIST_FILE = 6;
     static final int WRITE_DELAY_MILLIS = 10 * 1000;  // 10 seconds
     static final int LOADING_BOOST_MAX_DURATION = 5 * 1000;  // 5 seconds
+    static final String PROPERTY_DEBUG_GFX_GAME_DEFAULT_FRAME_RATE_DISABLED =
+            "debug.graphics.game_default_frame_rate.disabled";
+    static final String PROPERTY_RO_SURFACEFLINGER_GAME_DEFAULT_FRAME_RATE =
+            "ro.surface_flinger.game_default_frame_rate_override";
 
     private static final String PACKAGE_NAME_MSG_KEY = "packageName";
     private static final String USER_ID_MSG_KEY = "userId";
@@ -154,7 +162,6 @@
     private final PackageManager mPackageManager;
     private final UserManager mUserManager;
     private final PowerManagerInternal mPowerManagerInternal;
-    private final File mSystemDir;
     @VisibleForTesting
     final AtomicFile mGameModeInterventionListFile;
     private DeviceConfigListener mDeviceConfigListener;
@@ -175,28 +182,57 @@
     final MyUidObserver mUidObserver;
     @GuardedBy("mUidObserverLock")
     private final Set<Integer> mForegroundGameUids = new HashSet<>();
+    private final GameManagerServiceSystemPropertiesWrapper mSysProps;
+    private float mGameDefaultFrameRateValue;
+
+    @VisibleForTesting
+    static class Injector {
+        public GameManagerServiceSystemPropertiesWrapper createSystemPropertiesWrapper() {
+            return new GameManagerServiceSystemPropertiesWrapper() {
+                @Override
+                public String get(String key, String def) {
+                    return SystemProperties.get(key, def);
+                }
+                @Override
+                public boolean getBoolean(String key, boolean def) {
+                    return SystemProperties.getBoolean(key, def);
+                }
+
+                @Override
+                public int getInt(String key, int def) {
+                    return SystemProperties.getInt(key, def);
+                }
+
+                @Override
+                public void set(String key, String val) {
+                    SystemProperties.set(key, val);
+                }
+            };
+        }
+    }
 
     public GameManagerService(Context context) {
         this(context, createServiceThread().getLooper());
     }
 
     GameManagerService(Context context, Looper looper) {
-        this(context, looper, Environment.getDataDirectory());
+        this(context, looper, Environment.getDataDirectory(), new Injector());
     }
 
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
-    GameManagerService(Context context, Looper looper, File dataDir) {
+    GameManagerService(Context context, Looper looper, File dataDir, Injector injector) {
+        super(PermissionEnforcer.fromContext(context));
         mContext = context;
         mHandler = new SettingsHandler(looper);
         mPackageManager = mContext.getPackageManager();
         mUserManager = mContext.getSystemService(UserManager.class);
         mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
-        mSystemDir = new File(dataDir, "system");
-        mSystemDir.mkdirs();
-        FileUtils.setPermissions(mSystemDir.toString(),
+        File systemDir = new File(dataDir, "system");
+        systemDir.mkdirs();
+        FileUtils.setPermissions(systemDir.toString(),
                 FileUtils.S_IRWXU | FileUtils.S_IRWXG | FileUtils.S_IROTH | FileUtils.S_IXOTH,
                 -1, -1);
-        mGameModeInterventionListFile = new AtomicFile(new File(mSystemDir,
+        mGameModeInterventionListFile = new AtomicFile(new File(systemDir,
                 GAME_MODE_INTERVENTION_LIST_FILE_NAME));
         FileUtils.setPermissions(mGameModeInterventionListFile.getBaseFile().getAbsolutePath(),
                 FileUtils.S_IRUSR | FileUtils.S_IWUSR
@@ -220,6 +256,8 @@
         } catch (RemoteException e) {
             Slog.w(TAG, "Could not register UidObserver");
         }
+
+        mSysProps = injector.createSystemPropertiesWrapper();
     }
 
     @Override
@@ -1521,6 +1559,10 @@
         mPowerManagerInternal.setPowerMode(Mode.GAME_LOADING, false);
         Slog.v(TAG, "Game power mode OFF (game manager service start/restart)");
         mPowerManagerInternal.setPowerMode(Mode.GAME, false);
+
+        mGameDefaultFrameRateValue = (float) mSysProps.getInt(
+                PROPERTY_RO_SURFACEFLINGER_GAME_DEFAULT_FRAME_RATE, 60);
+        Slog.v(TAG, "Game Default Frame Rate : " + mGameDefaultFrameRateValue);
     }
 
     private void sendUserMessage(int userId, int what, String eventForLog, int delayMillis) {
@@ -1588,7 +1630,7 @@
         try {
             final float fps = 0.0f;
             final int uid = mPackageManager.getPackageUidAsUser(packageName, userId);
-            setOverrideFrameRate(uid, fps);
+            setGameModeFrameRateOverride(uid, fps);
         } catch (PackageManager.NameNotFoundException e) {
             return;
         }
@@ -1620,7 +1662,7 @@
         try {
             final float fps = modeConfig.getFps();
             final int uid = mPackageManager.getPackageUidAsUser(packageName, userId);
-            setOverrideFrameRate(uid, fps);
+            setGameModeFrameRateOverride(uid, fps);
         } catch (PackageManager.NameNotFoundException e) {
             return;
         }
@@ -2159,14 +2201,61 @@
     }
 
     @VisibleForTesting
-    void setOverrideFrameRate(int uid, float frameRate) {
-        nativeSetOverrideFrameRate(uid, frameRate);
+    void setGameModeFrameRateOverride(int uid, float frameRate) {
+        nativeSetGameModeFrameRateOverride(uid, frameRate);
+    }
+
+    @VisibleForTesting
+    void setGameDefaultFrameRateOverride(int uid, float frameRate) {
+        Slog.v(TAG, "setDefaultFrameRateOverride : " + uid + " , " + frameRate);
+        nativeSetGameDefaultFrameRateOverride(uid, frameRate);
+    }
+
+    private float getGameDefaultFrameRate(boolean isEnabled) {
+        float gameDefaultFrameRate = 0.0f;
+        if (gameDefaultFrameRate()) {
+            gameDefaultFrameRate = isEnabled ? mGameDefaultFrameRateValue : 0.0f;
+        }
+        return gameDefaultFrameRate;
+    }
+
+    @Override
+    @EnforcePermission(Manifest.permission.MANAGE_GAME_MODE)
+    public void toggleGameDefaultFrameRate(boolean isEnabled) {
+        toggleGameDefaultFrameRate_enforcePermission();
+        if (gameDefaultFrameRate()) {
+            Slog.v(TAG, "toggleGameDefaultFrameRate : " + isEnabled);
+            this.toggleGameDefaultFrameRateUnchecked(isEnabled);
+        }
+    }
+
+    private void toggleGameDefaultFrameRateUnchecked(boolean isEnabled) {
+        // Here we only need to immediately update games that are in the foreground.
+        // We will update game default frame rate when a game comes into foreground in
+        // MyUidObserver.
+        synchronized (mLock) {
+            if (isEnabled) {
+                mSysProps.set(
+                        PROPERTY_DEBUG_GFX_GAME_DEFAULT_FRAME_RATE_DISABLED, "false");
+            } else {
+                mSysProps.set(
+                        PROPERTY_DEBUG_GFX_GAME_DEFAULT_FRAME_RATE_DISABLED, "true");
+            }
+        }
+
+        // Update all foreground games' frame rate.
+        synchronized (mUidObserverLock) {
+            for (int uid : mForegroundGameUids) {
+                setGameDefaultFrameRateOverride(uid, getGameDefaultFrameRate(isEnabled));
+            }
+        }
     }
 
     /**
      * load dynamic library for frame rate overriding JNI calls
      */
-    private static native void nativeSetOverrideFrameRate(int uid, float frameRate);
+    private static native void nativeSetGameModeFrameRateOverride(int uid, float frameRate);
+    private static native void nativeSetGameDefaultFrameRateOverride(int uid, float frameRate);
 
     final class MyUidObserver extends UidObserver {
         @Override
@@ -2179,6 +2268,7 @@
         @Override
         public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) {
             synchronized (mUidObserverLock) {
+
                 if (procState != ActivityManager.PROCESS_STATE_TOP) {
                     disableGameMode(uid);
                     return;
@@ -2198,6 +2288,11 @@
                     Slog.v(TAG, "Game power mode ON (process state was changed to foreground)");
                     mPowerManagerInternal.setPowerMode(Mode.GAME, true);
                 }
+                final boolean isGameDefaultFrameRateDisabled =
+                        mSysProps.getBoolean(
+                                PROPERTY_DEBUG_GFX_GAME_DEFAULT_FRAME_RATE_DISABLED, false);
+                setGameDefaultFrameRateOverride(uid,
+                        getGameDefaultFrameRate(!isGameDefaultFrameRateDisabled));
                 mForegroundGameUids.add(uid);
             }
         }
diff --git a/services/core/java/com/android/server/app/GameManagerServiceSystemPropertiesWrapper.java b/services/core/java/com/android/server/app/GameManagerServiceSystemPropertiesWrapper.java
new file mode 100644
index 0000000..afaceda
--- /dev/null
+++ b/services/core/java/com/android/server/app/GameManagerServiceSystemPropertiesWrapper.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.app;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.SystemProperties;
+/**
+ * Wrapper interface to access {@link SystemProperties}.
+ *
+ * @hide
+ */
+interface GameManagerServiceSystemPropertiesWrapper {
+    /**
+     * Get the String value for the given {@code key}.
+     *
+     * @param key the key to lookup
+     * @param def the default value in case the property is not set or empty
+     * @return if the {@code key} isn't found, return {@code def} if it isn't null, or an empty
+     * string otherwise
+     */
+    @NonNull
+    String get(@NonNull String key, @Nullable String def);
+    /**
+     * Get the Boolean value for the given {@code key}.
+     *
+     * @param key the key to lookup
+     * @param def the default value in case the property is not set or empty
+     * @return if the {@code key} isn't found, return {@code def} if it isn't null, not parsable
+     * or an empty string otherwise
+     */
+    @NonNull
+    boolean getBoolean(@NonNull String key, boolean def);
+
+    /**
+     * Get the Integer value for the given {@code key}.
+     *
+     * @param key the key to lookup
+     * @param def the default value in case the property is not set or empty
+     * @return if the {@code key} isn't found, return {@code def} if it isn't null, not parsable
+     * or an empty string otherwise
+     */
+    @NonNull
+    int getInt(@NonNull String key, int def);
+    /**
+     * Set the value for the given {@code key} to {@code val}.
+     *
+     * @throws IllegalArgumentException if the {@code val} exceeds 91 characters
+     * @throws RuntimeException if the property cannot be set, for example, if it was blocked by
+     * SELinux. libc will log the underlying reason.
+     */
+    void set(@NonNull String key, @Nullable String val);
+}
diff --git a/services/core/java/com/android/server/app/flags.aconfig b/services/core/java/com/android/server/app/flags.aconfig
new file mode 100644
index 0000000..f2e4783
--- /dev/null
+++ b/services/core/java/com/android/server/app/flags.aconfig
@@ -0,0 +1,9 @@
+package: "android.server.app"
+
+flag {
+    name: "game_default_frame_rate"
+    namespace: "game"
+    description: "This flag guards the new behavior with the addition of Game Default Frame Rate feature."
+    bug: "286084594"
+    is_fixed_read_only: true
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/appop/DiscreteRegistry.java b/services/core/java/com/android/server/appop/DiscreteRegistry.java
index e91b7e8..b1a12f7 100644
--- a/services/core/java/com/android/server/appop/DiscreteRegistry.java
+++ b/services/core/java/com/android/server/appop/DiscreteRegistry.java
@@ -37,6 +37,7 @@
 import static android.app.AppOpsManager.OP_RECEIVE_AMBIENT_TRIGGER_AUDIO;
 import static android.app.AppOpsManager.OP_RECEIVE_SANDBOX_TRIGGER_AUDIO;
 import static android.app.AppOpsManager.OP_RECORD_AUDIO;
+import static android.app.AppOpsManager.OP_RESERVED_FOR_TESTING;
 import static android.app.AppOpsManager.flagsToString;
 import static android.app.AppOpsManager.getUidStateName;
 
@@ -136,7 +137,7 @@
     private static final String DEFAULT_DISCRETE_OPS = OP_FINE_LOCATION + "," + OP_COARSE_LOCATION
             + "," + OP_CAMERA + "," + OP_RECORD_AUDIO + "," + OP_PHONE_CALL_MICROPHONE + ","
             + OP_PHONE_CALL_CAMERA + "," + OP_RECEIVE_AMBIENT_TRIGGER_AUDIO + ","
-            + OP_RECEIVE_SANDBOX_TRIGGER_AUDIO;
+            + OP_RECEIVE_SANDBOX_TRIGGER_AUDIO + "," + OP_RESERVED_FOR_TESTING;
     private static final long DEFAULT_DISCRETE_HISTORY_CUTOFF = Duration.ofDays(7).toMillis();
     private static final long MAXIMUM_DISCRETE_HISTORY_CUTOFF = Duration.ofDays(30).toMillis();
     private static final long DEFAULT_DISCRETE_HISTORY_QUANTIZATION =
diff --git a/services/core/java/com/android/server/audio/AdiDeviceState.java b/services/core/java/com/android/server/audio/AdiDeviceState.java
index ffdab7d..9ae43a0 100644
--- a/services/core/java/com/android/server/audio/AdiDeviceState.java
+++ b/services/core/java/com/android/server/audio/AdiDeviceState.java
@@ -235,9 +235,10 @@
      * {@link AdiDeviceState#toPersistableString()}.
      */
     public static int getPeristedMaxSize() {
-        return 36;  /* (mDeviceType)2 + (mDeviceAddress)17 + (mInternalDeviceType)9 + (mSAEnabled)1
+        return 39;  /* (mDeviceType)2 + (mDeviceAddress)17 + (mInternalDeviceType)9 + (mSAEnabled)1
                            + (mHasHeadTracker)1 + (mHasHeadTrackerEnabled)1
-                           + (SETTINGS_FIELD_SEPARATOR)5 */
+                           + (mAudioDeviceCategory)1 + (SETTINGS_FIELD_SEPARATOR)6
+                           + (SETTING_DEVICE_SEPARATOR)1 */
     }
 
     @Nullable
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 9cfcb16..8091753 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -2037,9 +2037,8 @@
                     } break;
 
                 case MSG_L_UPDATED_ADI_DEVICE_STATE:
-                    synchronized (mDeviceStateLock) {
-                        mAudioService.onUpdatedAdiDeviceState((AdiDeviceState) msg.obj);
-                    } break;
+                    mAudioService.onUpdatedAdiDeviceState((AdiDeviceState) msg.obj);
+                    break;
 
                 default:
                     Log.wtf(TAG, "Invalid message " + msg.what);
@@ -2687,11 +2686,15 @@
             return;
         }
         final SettingsAdapter settingsAdapter = mAudioService.getSettings();
-        boolean res = settingsAdapter.putSecureStringForUser(mAudioService.getContentResolver(),
-                Settings.Secure.AUDIO_DEVICE_INVENTORY,
-                deviceSettings, UserHandle.USER_CURRENT);
-        if (!res) {
-            Log.e(TAG, "error saving AdiDeviceState: " + deviceSettings);
+        try {
+            boolean res = settingsAdapter.putSecureStringForUser(mAudioService.getContentResolver(),
+                    Settings.Secure.AUDIO_DEVICE_INVENTORY,
+                    deviceSettings, UserHandle.USER_CURRENT);
+            if (!res) {
+                Log.e(TAG, "error saving AdiDeviceState: " + deviceSettings);
+            }
+        } catch (IllegalArgumentException e) {
+            Log.e(TAG, "error saving AdiDeviceState: " + deviceSettings, e);
         }
     }
 
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index e54bf64..d138f24 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -30,7 +30,6 @@
 import static android.media.AudioSystem.isBluetoothScoOutDevice;
 import static android.media.audio.Flags.automaticBtDeviceType;
 
-
 import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
 
 import android.annotation.NonNull;
@@ -81,7 +80,6 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
@@ -104,6 +102,14 @@
     private static final String SETTING_DEVICE_SEPARATOR_CHAR = "|";
     private static final String SETTING_DEVICE_SEPARATOR = "\\|";
 
+    /** Max String length that can be persisted within the Settings. */
+    // LINT.IfChange(settings_max_length_per_string)
+    private static final int MAX_SETTINGS_LENGTH_PER_STRING = 32768;
+    // LINT.ThenChange(/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java)
+
+    private static final int MAX_DEVICE_INVENTORY_ENTRIES =
+            MAX_SETTINGS_LENGTH_PER_STRING / AdiDeviceState.getPeristedMaxSize();
+
     // lock to synchronize all access to mConnectedDevices and mApmConnectedDevices
     private final Object mDevicesLock = new Object();
 
@@ -113,7 +119,8 @@
     private final Object mDeviceInventoryLock = new Object();
 
     @GuardedBy("mDeviceInventoryLock")
-    private final HashMap<Pair<Integer, String>, AdiDeviceState> mDeviceInventory = new HashMap<>();
+    private final LinkedHashMap<Pair<Integer, String>, AdiDeviceState> mDeviceInventory =
+            new LinkedHashMap<>();
 
     Collection<AdiDeviceState> getImmutableDeviceInventory() {
         final List<AdiDeviceState> newList;
@@ -136,6 +143,7 @@
                 oldState.setSAEnabled(newState.isSAEnabled());
                 return oldState;
             });
+            checkDeviceInventorySize_l();
         }
         mDeviceBroker.postSynchronizeAdiDevicesInInventory(deviceState);
     }
@@ -173,6 +181,8 @@
             ads.setAudioDeviceCategory(category);
 
             mDeviceInventory.put(ads.getDeviceId(), ads);
+            checkDeviceInventorySize_l();
+
             mDeviceBroker.postUpdatedAdiDeviceState(ads);
             mDeviceBroker.postPersistAudioDeviceSettings();
         }
@@ -200,6 +210,7 @@
                         }
                         return oldState;
                     });
+            checkDeviceInventorySize_l();
         }
         if (updatedCategory.get()) {
             mDeviceBroker.postUpdatedAdiDeviceState(deviceState);
@@ -272,6 +283,18 @@
         }
     }
 
+    @GuardedBy("mDeviceInventoryLock")
+    private void checkDeviceInventorySize_l() {
+        if (mDeviceInventory.size() > MAX_DEVICE_INVENTORY_ENTRIES) {
+            // remove the first element
+            Iterator<Entry<Pair<Integer, String>, AdiDeviceState>> iterator =
+                    mDeviceInventory.entrySet().iterator();
+            if (iterator.hasNext()) {
+                iterator.remove();
+            }
+        }
+    }
+
     @GuardedBy({"mDevicesLock", "mDeviceInventoryLock"})
     private boolean synchronizeBleDeviceInInventory(AdiDeviceState updatedDevice) {
         for (DeviceInfo di : mConnectedDevices.values()) {
@@ -873,7 +896,8 @@
             if (event == BtHelper.EVENT_DEVICE_CONFIG_CHANGE) {
                 boolean codecChange = false;
                 if (btInfo.mProfile == BluetoothProfile.A2DP
-                        || btInfo.mProfile == BluetoothProfile.LE_AUDIO) {
+                        || btInfo.mProfile == BluetoothProfile.LE_AUDIO
+                        || btInfo.mProfile == BluetoothProfile.LE_AUDIO_BROADCAST) {
                     if (di.mDeviceCodecFormat != codec) {
                         di.mDeviceCodecFormat = codec;
                         mConnectedDevices.replace(key, di);
@@ -1501,7 +1525,7 @@
             } else {
                 status = addOp.deviceRoleAction(useCase, role, devices);
                 if (status == AudioSystem.SUCCESS) {
-                    rolesMap.put(key, devices);
+                    rolesMap.put(key, new ArrayList(devices));
                 }
             }
             return status;
@@ -2806,7 +2830,7 @@
             deviceCatalogSize = mDeviceInventory.size();
 
             final StringBuilder settingsBuilder = new StringBuilder(
-                            deviceCatalogSize * AdiDeviceState.getPeristedMaxSize());
+                    deviceCatalogSize * AdiDeviceState.getPeristedMaxSize());
 
             Iterator<AdiDeviceState> iterator = mDeviceInventory.values().iterator();
             if (iterator.hasNext()) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index f7b7aaa..0c78231 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -4505,13 +4505,13 @@
 
     private void dumpFlags(PrintWriter pw) {
         pw.println("\nFun with Flags: ");
-        pw.println("\tandroid.media.audio.Flags.autoPublicVolumeApiHardening:"
+        pw.println("\tandroid.media.audio.autoPublicVolumeApiHardening:"
                 + autoPublicVolumeApiHardening());
-        pw.println("\tandroid.media.audio.Flags.focusFreezeTestApi:"
+        pw.println("\tandroid.media.audio.focusFreezeTestApi:"
                 + focusFreezeTestApi());
-        pw.println("\tcom.android.media.audio.Flags.bluetoothMacAddressAnonymization:"
+        pw.println("\tcom.android.media.audio.bluetoothMacAddressAnonymization:"
                 + bluetoothMacAddressAnonymization());
-        pw.println("\tcom.android.media.audio.Flags.disablePrescaleAbsoluteVolume:"
+        pw.println("\tcom.android.media.audio.disablePrescaleAbsoluteVolume:"
                 + disablePrescaleAbsoluteVolume());
     }
 
@@ -5106,7 +5106,7 @@
     private void setMasterMuteInternalNoCallerCheck(
             boolean mute, int flags, int userId, String eventSource) {
         if (DEBUG_VOL) {
-            Log.d(TAG, TextUtils.formatSimple("Master mute %s, %d, user=%d from %s",
+            Log.d(TAG, TextUtils.formatSimple("Master mute %s, flags 0x%x, userId=%d from %s",
                     mute, flags, userId, eventSource));
         }
 
@@ -13779,6 +13779,11 @@
         return mDeviceBroker.getDeviceAddresses(device);
     }
 
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    MusicFxHelper getMusicFxHelper() {
+        return mMusicFxHelper;
+    }
+
     //======================
     // misc
     //======================
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index 401dc88..8075618 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -324,7 +324,8 @@
         // AUDIO_FORMAT_DEFAULT as native audio policy manager expects a specific audio format
         // only if audio HW module selection based on format is supported for the device type.
         if (!(profile == BluetoothProfile.A2DP
-                || (profile == BluetoothProfile.LE_AUDIO && isLeOutput))) {
+                || (isLeOutput && ((profile == BluetoothProfile.LE_AUDIO)
+                        || (profile == BluetoothProfile.LE_AUDIO_BROADCAST))))) {
             return AudioSystem.AUDIO_FORMAT_DEFAULT;
         }
         @AudioSystem.AudioFormatNativeEnumForBtCodec int codec =
diff --git a/services/core/java/com/android/server/audio/MusicFxHelper.java b/services/core/java/com/android/server/audio/MusicFxHelper.java
index 5f4e4c3..85b3b49 100644
--- a/services/core/java/com/android/server/audio/MusicFxHelper.java
+++ b/services/core/java/com/android/server/audio/MusicFxHelper.java
@@ -17,9 +17,11 @@
 package com.android.server.audio;
 
 import static android.content.pm.PackageManager.MATCH_ANY_USER;
+
 import static com.android.server.audio.AudioService.MUSICFX_HELPER_MSG_START;
 
 import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
 import android.app.ActivityManager;
 import android.app.IUidObserver;
 import android.app.UidObserver;
@@ -48,7 +50,6 @@
 
 /**
  * MusicFx management.
- * .
  */
 public class MusicFxHelper {
     private static final String TAG = "AS.MusicFxHelper";
@@ -60,14 +61,113 @@
     // Synchronization UidSessionMap access between UidObserver and AudioServiceBroadcastReceiver.
     private final Object mClientUidMapLock = new Object();
 
+    private final String mPackageName = this.getClass().getPackage().getName();
+
+    private final String mMusicFxPackageName = "com.android.musicfx";
+
+    /*package*/ static final int MSG_EFFECT_CLIENT_GONE = MUSICFX_HELPER_MSG_START + 1;
+
     // The binder token identifying the UidObserver registration.
     private IBinder mUidObserverToken = null;
 
+    // Package name and list of open audio sessions for this package
+    private static class PackageSessions {
+        String mPackageName;
+        List<Integer> mSessions;
+    }
+
+    /*
+     * Override of SparseArray class to add bind/unbind and UID observer in the put/remove methods.
+     *
+     * put:
+     *  - the first key/value set put into MySparseArray will trigger a procState bump (bindService)
+     *  - if no valid observer token exist, will call registerUidObserver for put
+     *  - for each new uid put into array, it will be added to uid observer list
+     *
+     * remove:
+     *  - for each uid removed from array, it will be removed from uid observer list as well
+     *  - if it's the last uid in array, no more MusicFx procState bump (unbindService), uid
+     *    observer will also be removed, and observer token reset to null
+     */
+    private class MySparseArray extends SparseArray<PackageSessions> {
+        private final String mMusicFxPackageName = "com.android.musicfx";
+
+        @RequiresPermission(anyOf = {
+                android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+                android.Manifest.permission.INTERACT_ACROSS_USERS,
+                android.Manifest.permission.INTERACT_ACROSS_PROFILES
+        })
+        @Override
+        public void put(int uid, PackageSessions pkgSessions) {
+            if (size() == 0) {
+                int procState = ActivityManager.PROCESS_STATE_NONEXISTENT;
+                try {
+                    procState = ActivityManager.getService().getPackageProcessState(
+                            mMusicFxPackageName, mPackageName);
+                } catch (RemoteException e) {
+                    Log.e(TAG, "RemoteException with getPackageProcessState: " + e);
+                }
+                if (procState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
+                    Intent bindIntent = new Intent().setClassName(mMusicFxPackageName,
+                            "com.android.musicfx.KeepAliveService");
+                    mContext.bindServiceAsUser(
+                            bindIntent, mMusicFxBindConnection, Context.BIND_AUTO_CREATE,
+                            UserHandle.of(getCurrentUserId()));
+                    Log.i(TAG, "bindService to " + mMusicFxPackageName);
+                }
+
+                Log.i(TAG, mMusicFxPackageName + " procState " + procState);
+            }
+            try {
+                if (mUidObserverToken == null) {
+                    mUidObserverToken = ActivityManager.getService().registerUidObserverForUids(
+                            mEffectUidObserver, ActivityManager.UID_OBSERVER_GONE,
+                            ActivityManager.PROCESS_STATE_UNKNOWN, mPackageName,
+                            new int[]{uid});
+                    Log.i(TAG, "registered to observer with UID " + uid);
+                } else if (get(uid) == null) { // addUidToObserver if this is a new UID
+                    ActivityManager.getService().addUidToObserver(mUidObserverToken, mPackageName,
+                            uid);
+                    Log.i(TAG, " UID " + uid + " add to observer");
+                }
+            } catch (RemoteException e) {
+                Log.e(TAG, "RemoteException with UID observer add/register: " + e);
+            }
+
+            super.put(uid, pkgSessions);
+        }
+
+        @Override
+        public void remove(int uid) {
+            if (get(uid) != null) {
+                try {
+                    ActivityManager.getService().removeUidFromObserver(mUidObserverToken,
+                            mPackageName, uid);
+                } catch (RemoteException e) {
+                    Log.e(TAG, "RemoteException with removeUidFromObserver: " + e);
+                }
+            }
+
+            super.remove(uid);
+
+            // stop foreground service delegate and unregister UID observers with the last UID
+            if (size() == 0) {
+                try {
+                    ActivityManager.getService().unregisterUidObserver(mEffectUidObserver);
+                } catch (RemoteException e) {
+                    Log.e(TAG, "RemoteException with unregisterUidObserver: " + e);
+                }
+                mUidObserverToken = null;
+                mContext.unbindService(mMusicFxBindConnection);
+                Log.i(TAG, "last session closed, unregister UID observer, and unbind "
+                        + mMusicFxPackageName);
+            }
+        }
+    }
+
     // Hashmap of UID and list of open sessions for this UID.
     @GuardedBy("mClientUidMapLock")
-    private SparseArray<List<Integer>> mClientUidSessionMap = new SparseArray<>();
-
-    /*package*/ static final int MSG_EFFECT_CLIENT_GONE = MUSICFX_HELPER_MSG_START + 1;
+    private MySparseArray mClientUidSessionMap = new MySparseArray();
 
     // UID observer for effect MusicFx clients
     private final IUidObserver mEffectUidObserver = new UidObserver() {
@@ -102,23 +202,27 @@
      * Handle the broadcast {@link #ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION} and
      * {@link #ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION} intents.
      *
+     * Only intents without target application package {@link android.content.Intent#getPackage}
+     * will be handled by the MusicFxHelper, all intents handled and forwarded by MusicFxHelper
+     * will have the target application package.
+     *
      * If the intent is {@link #ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION}:
-     *  - If the MusicFx process is not running, call bindService with AUTO_CREATE to create.
-     *  - If this is the first audio session in MusicFx, call set foreground service delegate.
+     *  - If the MusicFx process is not running, call bindServiceAsUser with AUTO_CREATE to create.
+     *  - If this is the first audio session of MusicFx, call set foreground service delegate.
      *  - If this is the first audio session for a given UID, add the UID into observer.
      *
-     * If the intent is {@link #ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION}:
-     *  - MusicFx will not be foreground delegated anymore.
-     *  - The KeepAliveService of MusicFx will be unbound.
-     *  - The UidObserver will be removed.
+     * If the intent is {@link #ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION}
+     *  - The KeepAliveService of MusicFx will be unbound, and MusicFx will not be foreground
+     *    delegated anymore if the last session of the last package was closed.
+     *  - The Uid Observer will be removed when the last session of a package was closed.
      */
+    @RequiresPermission(allOf = {android.Manifest.permission.INTERACT_ACROSS_USERS})
     public void handleAudioEffectBroadcast(Context context, Intent intent) {
         String target = intent.getPackage();
         if (target != null) {
             Log.w(TAG, "effect broadcast already targeted to " + target);
             return;
         }
-        intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
         final PackageManager pm = context.getPackageManager();
         // TODO this should target a user-selected panel
         List<ResolveInfo> ril = pm.queryBroadcastReceivers(intent, 0 /* flags */);
@@ -126,14 +230,14 @@
             ResolveInfo ri = ril.get(0);
             final String senderPackageName = intent.getStringExtra(AudioEffect.EXTRA_PACKAGE_NAME);
             try {
-                final int senderUid = pm.getPackageUidAsUser(senderPackageName,
-                        PackageManager.PackageInfoFlags.of(MATCH_ANY_USER), getCurrentUserId());
                 if (ri != null && ri.activityInfo != null && ri.activityInfo.packageName != null) {
+                    final int senderUid = pm.getPackageUidAsUser(senderPackageName,
+                            PackageManager.PackageInfoFlags.of(MATCH_ANY_USER), getCurrentUserId());
+                    intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
                     intent.setPackage(ri.activityInfo.packageName);
-                    synchronized (mClientUidMapLock) {
-                        setMusicFxServiceWithObserver(context, intent, senderUid);
+                    if (setMusicFxServiceWithObserver(intent, senderUid, senderPackageName)) {
+                        context.sendBroadcastAsUser(intent, UserHandle.ALL);
                     }
-                    context.sendBroadcastAsUser(intent, UserHandle.ALL);
                     return;
                 }
             } catch (PackageManager.NameNotFoundException e) {
@@ -144,127 +248,105 @@
         Log.w(TAG, "couldn't find receiver package for effect intent");
     }
 
-    /**
-     * Handle the UidObserver onUidGone callback of MusicFx clients.
-     * All open audio sessions of this UID will be closed.
-     * If this is the last UID for MusicFx:
-     *  - MusicFx will not be foreground delegated anymore.
-     *  - The KeepAliveService of MusicFx will be unbound.
-     *  - The UidObserver will be removed.
-     */
-    public void handleEffectClientUidGone(int uid) {
-        synchronized (mClientUidMapLock) {
-            Log.w(TAG, " inside handle MSG_EFFECT_CLIENT_GONE");
-            // Once the uid is no longer running, close all remain audio session(s) for this UID
-            if (mClientUidSessionMap.get(Integer.valueOf(uid)) != null) {
-                final List<Integer> sessions =
-                        new ArrayList(mClientUidSessionMap.get(Integer.valueOf(uid)));
-                Log.i(TAG, "UID " + uid + " gone, closing " + sessions.size() + " sessions");
-                for (Integer session : sessions) {
-                    Intent intent = new Intent(
-                            AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION);
-                    intent.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, session);
-                    setMusicFxServiceWithObserver(mContext, intent, uid);
-                    Log.i(TAG, "Close session " + session + " of UID " + uid);
-                }
-                mClientUidSessionMap.remove(Integer.valueOf(uid));
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+            android.Manifest.permission.INTERACT_ACROSS_USERS,
+            android.Manifest.permission.INTERACT_ACROSS_PROFILES
+    })
+    @GuardedBy("mClientUidMapLock")
+    private boolean handleAudioEffectSessionOpen(
+            int senderUid, String senderPackageName, int sessionId) {
+        Log.d(TAG, senderPackageName + " UID " + senderUid + " open MusicFx session " + sessionId);
+
+        PackageSessions pkgSessions = mClientUidSessionMap.get(Integer.valueOf(senderUid));
+        if (pkgSessions != null && pkgSessions.mSessions != null) {
+            if (pkgSessions.mSessions.contains(sessionId)) {
+                Log.e(TAG, "Audio session " + sessionId + " already open for UID: "
+                        + senderUid + ", package: " + senderPackageName + ", abort");
+                return false;
             }
+            if (pkgSessions.mPackageName != senderPackageName) {
+                Log.w(TAG, "Inconsistency package names for UID open: " + senderUid + " prev: "
+                        + pkgSessions.mPackageName + ", now: " + senderPackageName);
+                return false;
+            }
+        } else {
+            // first session for this UID, create a new Package/Sessions pair
+            pkgSessions = new PackageSessions();
+            pkgSessions.mSessions = new ArrayList();
+            pkgSessions.mPackageName = senderPackageName;
         }
+
+        pkgSessions.mSessions.add(Integer.valueOf(sessionId));
+        mClientUidSessionMap.put(Integer.valueOf(senderUid), pkgSessions);
+        return true;
     }
 
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+            android.Manifest.permission.INTERACT_ACROSS_USERS,
+            android.Manifest.permission.INTERACT_ACROSS_PROFILES
+    })
     @GuardedBy("mClientUidMapLock")
-    private void setMusicFxServiceWithObserver(Context context, Intent intent, int senderUid) {
-        PackageManager pm = context.getPackageManager();
-        try {
-            final int audioSession = intent.getIntExtra(AudioEffect.EXTRA_AUDIO_SESSION,
-                    AudioManager.AUDIO_SESSION_ID_GENERATE);
-            if (AudioManager.AUDIO_SESSION_ID_GENERATE == audioSession) {
-                Log.e(TAG, "Intent missing audio session: " + audioSession);
-                return;
+    private boolean handleAudioEffectSessionClose(
+            int senderUid, String senderPackageName, int sessionId) {
+        Log.d(TAG, senderPackageName + " UID " + senderUid + " close MusicFx session " + sessionId);
+
+        PackageSessions pkgSessions = mClientUidSessionMap.get(Integer.valueOf(senderUid));
+        if (pkgSessions == null) {
+            Log.e(TAG, senderPackageName + " UID " + senderUid + " does not exist in map, abort");
+            return false;
+        }
+        if (pkgSessions.mPackageName != senderPackageName) {
+            Log.w(TAG, "Inconsistency package names for UID " + senderUid + " close, prev: "
+                    + pkgSessions.mPackageName + ", now: " + senderPackageName);
+            return false;
+        }
+
+        if (pkgSessions.mSessions != null && pkgSessions.mSessions.size() != 0) {
+            if (!pkgSessions.mSessions.contains(sessionId)) {
+                Log.e(TAG, senderPackageName + " UID " + senderUid + " session " + sessionId
+                        + " does not exist in map, abort");
+                return false;
             }
 
-            // only apply to com.android.musicfx and KeepAliveService for now
-            final String musicFxPackageName = "com.android.musicfx";
-            final String musicFxKeepAliveService = "com.android.musicfx.KeepAliveService";
-            final int musicFxUid = pm.getPackageUidAsUser(musicFxPackageName,
-                    PackageManager.PackageInfoFlags.of(MATCH_ANY_USER), getCurrentUserId());
+            pkgSessions.mSessions.remove(Integer.valueOf(sessionId));
+        }
 
+        if (pkgSessions.mSessions == null || pkgSessions.mSessions.size() == 0) {
+            // remove UID from map as well as the UID observer with the last session close
+            mClientUidSessionMap.remove(Integer.valueOf(senderUid));
+        } else {
+            mClientUidSessionMap.put(Integer.valueOf(senderUid), pkgSessions);
+        }
+
+        return true;
+    }
+
+    /**
+     * @return true if the intent is validated and handled successfully, false with any error
+     * (invalid sender/intent for example).
+     */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+            android.Manifest.permission.INTERACT_ACROSS_USERS,
+            android.Manifest.permission.INTERACT_ACROSS_PROFILES
+    })
+    private boolean setMusicFxServiceWithObserver(
+            Intent intent, int senderUid, String packageName) {
+        final int session = intent.getIntExtra(AudioEffect.EXTRA_AUDIO_SESSION,
+                AudioManager.AUDIO_SESSION_ID_GENERATE);
+        if (AudioManager.AUDIO_SESSION_ID_GENERATE == session) {
+            Log.e(TAG, packageName + " intent have no invalid audio session");
+            return false;
+        }
+
+        synchronized (mClientUidMapLock) {
             if (intent.getAction().equals(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION)) {
-                List<Integer> sessions = new ArrayList<>();
-                Log.d(TAG, "UID " + senderUid + ", open MusicFx session " + audioSession);
-                // start foreground service delegate and register UID observer with the first
-                // session of first UID open
-                if (0 == mClientUidSessionMap.size()) {
-                    final int procState = ActivityManager.getService().getPackageProcessState(
-                            musicFxPackageName, this.getClass().getPackage().getName());
-                    // if musicfx process not in binding state, call bindService with AUTO_CREATE
-                    if (procState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
-                        Intent bindIntent = new Intent().setClassName(musicFxPackageName,
-                                musicFxKeepAliveService);
-                        context.bindServiceAsUser(
-                                bindIntent, mMusicFxBindConnection, Context.BIND_AUTO_CREATE,
-                                UserHandle.of(getCurrentUserId()));
-                        Log.i(TAG, "bindService to " + musicFxPackageName);
-                    }
-
-                    Log.i(TAG, "Package " + musicFxPackageName + " uid " + musicFxUid
-                            + " procState " + procState);
-                } else if (mClientUidSessionMap.get(Integer.valueOf(senderUid)) != null) {
-                    sessions = mClientUidSessionMap.get(Integer.valueOf(senderUid));
-                    if (sessions.contains(audioSession)) {
-                        Log.e(TAG, "Audio session " + audioSession + " already exist for UID "
-                                + senderUid + ", abort");
-                        return;
-                    }
-                }
-                // first session of this UID
-                if (sessions.size() == 0) {
-                    // call registerUidObserverForUids with the first UID and first session
-                    if (mClientUidSessionMap.size() == 0 || mUidObserverToken == null) {
-                        mUidObserverToken = ActivityManager.getService().registerUidObserverForUids(
-                                mEffectUidObserver, ActivityManager.UID_OBSERVER_GONE,
-                                ActivityManager.PROCESS_STATE_UNKNOWN, null, new int[]{senderUid});
-                        Log.i(TAG, "UID " + senderUid + " registered to observer");
-                    } else {
-                        // add UID to observer for each new UID
-                        ActivityManager.getService().addUidToObserver(mUidObserverToken, TAG,
-                                senderUid);
-                        Log.i(TAG, "UID " + senderUid + " addeded to observer");
-                    }
-                }
-
-                sessions.add(Integer.valueOf(audioSession));
-                mClientUidSessionMap.put(Integer.valueOf(senderUid), sessions);
+                return handleAudioEffectSessionOpen(senderUid, packageName, session);
             } else {
-                if (mClientUidSessionMap.get(senderUid) != null) {
-                    Log.d(TAG, "UID " + senderUid + ", close MusicFx session " + audioSession);
-                    List<Integer> sessions = mClientUidSessionMap.get(Integer.valueOf(senderUid));
-                    sessions.remove(Integer.valueOf(audioSession));
-                    if (0 == sessions.size()) {
-                        mClientUidSessionMap.remove(Integer.valueOf(senderUid));
-                    } else {
-                        mClientUidSessionMap.put(Integer.valueOf(senderUid), sessions);
-                    }
-
-                    // stop foreground service delegate and unregister UID observer with the
-                    // last session of last UID close
-                    if (0 == mClientUidSessionMap.size()) {
-                        ActivityManager.getService().unregisterUidObserver(mEffectUidObserver);
-                        mClientUidSessionMap.clear();
-                        context.unbindService(mMusicFxBindConnection);
-                        Log.i(TAG, " remove all sessions, unregister UID observer, and unbind "
-                                + musicFxPackageName);
-                    }
-                } else {
-                    // if the audio session already closed, print an error
-                    Log.e(TAG, "UID " + senderUid + " close audio session " + audioSession
-                            + " which does not exist");
-                }
+                return handleAudioEffectSessionClose(senderUid, packageName, session);
             }
-        } catch (PackageManager.NameNotFoundException e) {
-            Log.e(TAG, "Not able to find UID from package: " + e);
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException " + e + " with handling intent");
         }
     }
 
@@ -281,6 +363,39 @@
         return UserHandle.USER_SYSTEM;
     }
 
+
+    /**
+     * Handle the UidObserver onUidGone callback of MusicFx clients.
+     * Send close intent for all open audio sessions of this UID. The mClientUidSessionMap will be
+     * updated with the handling of close intent in setMusicFxServiceWithObserver.
+     */
+    @RequiresPermission(allOf = {android.Manifest.permission.INTERACT_ACROSS_USERS})
+    private void handleEffectClientUidGone(int uid) {
+        synchronized (mClientUidMapLock) {
+            Log.d(TAG, "handle MSG_EFFECT_CLIENT_GONE uid: " + uid + " mapSize: "
+                    + mClientUidSessionMap.size());
+            // Once the uid is no longer running, close all remain audio session(s) for this UID
+            final PackageSessions pkgSessions = mClientUidSessionMap.get(Integer.valueOf(uid));
+            if (pkgSessions != null) {
+                Log.i(TAG, "UID " + uid + " gone, closing all sessions");
+
+                // send close intent for each open session of the gone UID
+                for (Integer sessionId : pkgSessions.mSessions) {
+                    Intent closeIntent =
+                            new Intent(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION);
+                    closeIntent.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, pkgSessions.mPackageName);
+                    closeIntent.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, sessionId);
+                    closeIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
+                    // set broadcast target
+                    closeIntent.setPackage(mMusicFxPackageName);
+                    mContext.sendBroadcastAsUser(closeIntent, UserHandle.ALL);
+                }
+                mClientUidSessionMap.remove(Integer.valueOf(uid));
+            }
+        }
+    }
+
+    @RequiresPermission(allOf = {android.Manifest.permission.INTERACT_ACROSS_USERS})
     /*package*/ void handleMessage(Message msg) {
         switch (msg.what) {
             case MSG_EFFECT_CLIENT_GONE:
@@ -292,5 +407,4 @@
                 break;
         }
     }
-
 }
diff --git a/services/core/java/com/android/server/audio/RotationHelper.java b/services/core/java/com/android/server/audio/RotationHelper.java
index 394e4af..e012d17 100644
--- a/services/core/java/com/android/server/audio/RotationHelper.java
+++ b/services/core/java/com/android/server/audio/RotationHelper.java
@@ -80,6 +80,7 @@
         sContext = context;
         sHandler = handler;
         sDisplayListener = new AudioDisplayListener();
+        sFoldStateListener = new FoldStateListener(sContext, RotationHelper::updateFoldState);
         sRotationCallback = rotationCallback;
         sFoldStateCallback = foldStateCallback;
         enable();
@@ -90,7 +91,6 @@
                 .registerDisplayListener(sDisplayListener, sHandler);
         updateOrientation();
 
-        sFoldStateListener = new FoldStateListener(sContext, folded -> updateFoldState(folded));
         sContext.getSystemService(DeviceStateManager.class)
                 .registerCallback(new HandlerExecutor(sHandler), sFoldStateListener);
     }
diff --git a/services/core/java/com/android/server/biometrics/AuthService.java b/services/core/java/com/android/server/biometrics/AuthService.java
index 0629e637..dafea9a 100644
--- a/services/core/java/com/android/server/biometrics/AuthService.java
+++ b/services/core/java/com/android/server/biometrics/AuthService.java
@@ -36,6 +36,7 @@
 import android.app.AppOpsManager;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.hardware.biometrics.AuthenticationStateListener;
 import android.hardware.biometrics.BiometricAuthenticator;
 import android.hardware.biometrics.BiometricManager;
 import android.hardware.biometrics.ComponentInfoInternal;
@@ -385,6 +386,26 @@
         }
 
         @Override
+        public void registerAuthenticationStateListener(AuthenticationStateListener listener)
+                throws RemoteException {
+            checkInternalPermission();
+            final IFingerprintService fingerprintService = mInjector.getFingerprintService();
+            if (fingerprintService != null) {
+                fingerprintService.registerAuthenticationStateListener(listener);
+            }
+        }
+
+        @Override
+        public void unregisterAuthenticationStateListener(AuthenticationStateListener listener)
+                throws RemoteException {
+            checkInternalPermission();
+            final IFingerprintService fingerprintService = mInjector.getFingerprintService();
+            if (fingerprintService != null) {
+                fingerprintService.unregisterAuthenticationStateListener(listener);
+            }
+        }
+
+        @Override
         public void invalidateAuthenticatorIds(int userId, int fromSensorId,
                 IInvalidationCallback callback) throws RemoteException {
             checkInternalPermission();
diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
index a47135f..f9568ea 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
@@ -27,7 +27,7 @@
 import android.hardware.biometrics.BiometricAuthenticator;
 import android.hardware.biometrics.BiometricConstants;
 import android.hardware.biometrics.BiometricManager;
-import android.hardware.biometrics.BiometricOverlayConstants;
+import android.hardware.biometrics.BiometricRequestConstants;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.security.KeyStore;
@@ -430,19 +430,19 @@
         return mLockoutTracker;
     }
 
-    protected int getShowOverlayReason() {
+    protected int getRequestReason() {
         if (isKeyguard()) {
-            return BiometricOverlayConstants.REASON_AUTH_KEYGUARD;
+            return BiometricRequestConstants.REASON_AUTH_KEYGUARD;
         } else if (isBiometricPrompt()) {
             // BP reason always takes precedent over settings, since callers from within
             // settings can always invoke BP.
-            return BiometricOverlayConstants.REASON_AUTH_BP;
+            return BiometricRequestConstants.REASON_AUTH_BP;
         } else if (isSettings()) {
             // This is pretty much only for FingerprintManager#authenticate usage from
             // FingerprintSettings.
-            return BiometricOverlayConstants.REASON_AUTH_SETTINGS;
+            return BiometricRequestConstants.REASON_AUTH_SETTINGS;
         } else {
-            return BiometricOverlayConstants.REASON_AUTH_OTHER;
+            return BiometricRequestConstants.REASON_AUTH_OTHER;
         }
     }
 }
diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthenticationStateListeners.java b/services/core/java/com/android/server/biometrics/sensors/AuthenticationStateListeners.java
new file mode 100644
index 0000000..5863535
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationStateListeners.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors;
+
+import android.annotation.NonNull;
+import android.hardware.biometrics.AuthenticationStateListener;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * Low-level callback interface between BiometricManager and AuthService. Allows core system
+ * services (e.g. SystemUI) to register and unregister listeners for updates about the current
+ * state of biometric authentication.
+ * @hide */
+public class AuthenticationStateListeners implements IBinder.DeathRecipient {
+
+    private static final String TAG = "AuthenticationStateListeners";
+
+    @NonNull
+    private final CopyOnWriteArrayList<AuthenticationStateListener> mAuthenticationStateListeners =
+            new CopyOnWriteArrayList<>();
+
+    /**
+     * Enables clients to register an AuthenticationStateListener for updates about the current
+     * state of biometric authentication.
+     * @param listener listener to register
+     */
+    public void registerAuthenticationStateListener(
+            @NonNull AuthenticationStateListener listener) {
+        mAuthenticationStateListeners.add(listener);
+        try {
+            listener.asBinder().linkToDeath(this, 0 /* flags */);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Failed to link to death", e);
+        }
+    }
+
+    /**
+     * Enables clients to unregister an AuthenticationStateListener.
+     * @param listener listener to register
+     */
+    public void unregisterAuthenticationStateListener(
+            @NonNull AuthenticationStateListener listener) {
+        mAuthenticationStateListeners.remove(listener);
+    }
+
+    /**
+     * Defines behavior in response to authentication starting
+     * @param requestReason reason from [BiometricRequestConstants.RequestReason] for requesting
+     * authentication starting
+     */
+    public void onAuthenticationStarted(int requestReason) {
+        for (AuthenticationStateListener listener: mAuthenticationStateListeners) {
+            try {
+                listener.onAuthenticationStarted(requestReason);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Remote exception in notifying listener that authentication "
+                        + "started", e);
+            }
+        }
+    }
+
+    /**
+     * Defines behavior in response to authentication stopping
+     */
+    public void onAuthenticationStopped() {
+        for (AuthenticationStateListener listener: mAuthenticationStateListeners) {
+            try {
+                listener.onAuthenticationStopped();
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Remote exception in notifying listener that authentication "
+                        + "stopped", e);
+            }
+        }
+    }
+
+    @Override
+    public void binderDied() {
+        // Do nothing, handled below
+    }
+
+    @Override
+    public void binderDied(IBinder who) {
+        Slog.w(TAG, "Callback binder died: " + who);
+        if (mAuthenticationStateListeners.removeIf(listener -> listener.asBinder().equals(who))) {
+            Slog.w(TAG, "Removed dead listener for " + who);
+        } else {
+            Slog.w(TAG, "No dead listeners found");
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java
index 483ce75..2c4d30b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java
@@ -19,7 +19,7 @@
 import android.annotation.NonNull;
 import android.content.Context;
 import android.hardware.biometrics.BiometricAuthenticator;
-import android.hardware.biometrics.BiometricOverlayConstants;
+import android.hardware.biometrics.BiometricRequestConstants;
 import android.hardware.fingerprint.FingerprintManager;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -135,14 +135,14 @@
         return true;
     }
 
-    protected int getOverlayReasonFromEnrollReason(@FingerprintManager.EnrollReason int reason) {
+    protected int getRequestReasonFromEnrollReason(@FingerprintManager.EnrollReason int reason) {
         switch (reason) {
             case FingerprintManager.ENROLL_FIND_SENSOR:
-                return BiometricOverlayConstants.REASON_ENROLL_FIND_SENSOR;
+                return BiometricRequestConstants.REASON_ENROLL_FIND_SENSOR;
             case FingerprintManager.ENROLL_ENROLL:
-                return BiometricOverlayConstants.REASON_ENROLL_ENROLLING;
+                return BiometricRequestConstants.REASON_ENROLL_ENROLLING;
             default:
-                return BiometricOverlayConstants.REASON_UNKNOWN;
+                return BiometricRequestConstants.REASON_UNKNOWN;
         }
     }
 }
diff --git a/services/core/java/com/android/server/biometrics/sensors/SensorOverlays.java b/services/core/java/com/android/server/biometrics/sensors/SensorOverlays.java
index aeb6b6e..3d20efc 100644
--- a/services/core/java/com/android/server/biometrics/sensors/SensorOverlays.java
+++ b/services/core/java/com/android/server/biometrics/sensors/SensorOverlays.java
@@ -16,9 +16,11 @@
 
 package com.android.server.biometrics.sensors;
 
+import static com.android.systemui.shared.Flags.sidefpsControllerRefactor;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.hardware.biometrics.BiometricOverlayConstants;
+import android.hardware.biometrics.BiometricRequestConstants;
 import android.hardware.fingerprint.ISidefpsController;
 import android.hardware.fingerprint.IUdfpsOverlayController;
 import android.hardware.fingerprint.IUdfpsOverlayControllerCallback;
@@ -42,6 +44,8 @@
     private static final String TAG = "SensorOverlays";
 
     @NonNull private final Optional<IUdfpsOverlayController> mUdfpsOverlayController;
+
+    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
     @NonNull private final Optional<ISidefpsController> mSidefpsController;
 
     /**
@@ -58,19 +62,32 @@
     }
 
     /**
+     * Create an overlay controller for each modality.
+     *
+     * @param udfpsOverlayController under display fps or null if not present on device
+     */
+    public SensorOverlays(@Nullable IUdfpsOverlayController udfpsOverlayController) {
+        mUdfpsOverlayController = Optional.ofNullable(udfpsOverlayController);
+        // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
+        mSidefpsController = Optional.empty();
+    }
+
+    /**
      * Show the overlay.
      *
      * @param sensorId sensor id
      * @param reason reason for showing
      * @param client client performing operation
      */
-    public void show(int sensorId, @BiometricOverlayConstants.ShowReason int reason,
+    public void show(int sensorId, @BiometricRequestConstants.RequestReason int reason,
             @NonNull AcquisitionClient<?> client) {
-        if (mSidefpsController.isPresent()) {
-            try {
-                mSidefpsController.get().show(sensorId, reason);
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Remote exception when showing the side-fps overlay", e);
+        if (!sidefpsControllerRefactor()) {
+            if (mSidefpsController.isPresent()) {
+                try {
+                    mSidefpsController.get().show(sensorId, reason);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Remote exception when showing the side-fps overlay", e);
+                }
             }
         }
 
@@ -98,11 +115,13 @@
      * @param sensorId sensor id
      */
     public void hide(int sensorId) {
-        if (mSidefpsController.isPresent()) {
-            try {
-                mSidefpsController.get().hide(sensorId);
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Remote exception when hiding the side-fps overlay", e);
+        if (!sidefpsControllerRefactor()) {
+            if (mSidefpsController.isPresent()) {
+                try {
+                    mSidefpsController.get().hide(sensorId);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Remote exception when hiding the side-fps overlay", e);
+                }
             }
         }
 
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
index 5084b60..578d9dc 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
@@ -722,6 +722,7 @@
             if (Flags.faceVhalFeature() && Utils.isVirtualEnabled(getContext())) {
                 if (virtualAt != -1) {
                     //only virtual instance should be returned
+                    Slog.i(TAG, "virtual hal is used");
                     return new Pair(new ArrayList<>(), List.of(aidlInstances.get(virtualAt)));
                 } else {
                     Slog.e(TAG, "Could not find virtual interface while it is enabled");
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
index 5ce0c8b..83b306b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
@@ -33,6 +33,7 @@
 import android.app.AppOpsManager;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.hardware.biometrics.AuthenticationStateListener;
 import android.hardware.biometrics.BiometricPrompt;
 import android.hardware.biometrics.BiometricsProtoEnums;
 import android.hardware.biometrics.IBiometricSensorReceiver;
@@ -81,6 +82,7 @@
 import com.android.server.SystemService;
 import com.android.server.biometrics.Utils;
 import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.sensors.AuthenticationStateListeners;
 import com.android.server.biometrics.sensors.BaseClientMonitor;
 import com.android.server.biometrics.sensors.BiometricStateCallback;
 import com.android.server.biometrics.sensors.ClientMonitorCallback;
@@ -128,6 +130,8 @@
     private final BiometricStateCallback<ServiceProvider, FingerprintSensorPropertiesInternal>
             mBiometricStateCallback;
     @NonNull
+    private final AuthenticationStateListeners mAuthenticationStateListeners;
+    @NonNull
     private final Handler mHandler;
     @NonNull
     private final FingerprintServiceRegistry mRegistry;
@@ -891,6 +895,7 @@
                 return providers;
             });
         }
+
         @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
         @Override
         public void addAuthenticatorsRegisteredCallback(
@@ -902,6 +907,24 @@
 
         @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
         @Override
+        public void registerAuthenticationStateListener(
+                @NonNull AuthenticationStateListener listener) {
+            super.registerAuthenticationStateListener_enforcePermission();
+
+            mAuthenticationStateListeners.registerAuthenticationStateListener(listener);
+        }
+
+        @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
+        @Override
+        public void unregisterAuthenticationStateListener(
+                @NonNull AuthenticationStateListener listener) {
+            super.unregisterAuthenticationStateListener_enforcePermission();
+
+            mAuthenticationStateListeners.unregisterAuthenticationStateListener(listener);
+        }
+
+        @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
+        @Override
         public void registerBiometricStateListener(@NonNull IBiometricStateListener listener) {
             super.registerBiometricStateListener_enforcePermission();
 
@@ -957,6 +980,7 @@
             }
         }
 
+        // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
         @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
         @Override
         public void setSidefpsController(@NonNull ISidefpsController controller) {
@@ -1014,6 +1038,7 @@
         mLockoutResetDispatcher = new LockoutResetDispatcher(context);
         mLockPatternUtils = new LockPatternUtils(context);
         mBiometricStateCallback = new BiometricStateCallback<>(UserManager.get(context));
+        mAuthenticationStateListeners = new AuthenticationStateListeners();
         mFingerprintProvider = fingerprintProvider != null ? fingerprintProvider :
                 (name) -> {
                     final String fqName = IFingerprint.DESCRIPTOR + "/" + name;
@@ -1022,9 +1047,9 @@
                     if (fp != null) {
                         try {
                             return new FingerprintProvider(getContext(),
-                                    mBiometricStateCallback, fp.getSensorProps(), name,
-                                    mLockoutResetDispatcher, mGestureAvailabilityDispatcher,
-                                    mBiometricContext);
+                                    mBiometricStateCallback, mAuthenticationStateListeners,
+                                    fp.getSensorProps(), name, mLockoutResetDispatcher,
+                                    mGestureAvailabilityDispatcher, mBiometricContext);
                         } catch (RemoteException e) {
                             Slog.e(TAG, "Remote exception in getSensorProps: " + fqName);
                         }
@@ -1057,6 +1082,7 @@
         if (Utils.isVirtualEnabled(getContext())) {
             if (virtualAt != -1) {
                 //only virtual instance should be returned
+                Slog.i(TAG, "virtual hal is used");
                 return new Pair(new ArrayList<>(), List.of(aidlInstances.get(virtualAt)));
             } else {
                 Slog.e(TAG, "Could not find virtual interface while it is enabled");
@@ -1085,13 +1111,13 @@
                     Fingerprint21UdfpsMock.CONFIG_ENABLE_TEST_UDFPS, 0 /* default */,
                     UserHandle.USER_CURRENT) != 0) {
                 fingerprint21 = Fingerprint21UdfpsMock.newInstance(getContext(),
-                        mBiometricStateCallback, hidlSensor,
-                        mLockoutResetDispatcher, mGestureAvailabilityDispatcher,
+                        mBiometricStateCallback, mAuthenticationStateListeners,
+                        hidlSensor, mLockoutResetDispatcher, mGestureAvailabilityDispatcher,
                         BiometricContext.getInstance(getContext()));
             } else {
                 fingerprint21 = Fingerprint21.newInstance(getContext(),
-                        mBiometricStateCallback, hidlSensor, mHandler,
-                        mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
+                        mBiometricStateCallback, mAuthenticationStateListeners, hidlSensor,
+                        mHandler, mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
             }
             providers.add(fingerprint21);
         }
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java
index a15d1a4..fc37d70 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java
@@ -135,6 +135,7 @@
 
     void onPowerPressed();
 
+    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
     /**
      * Sets side-fps controller
      * @param controller side-fps controller
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
index 337c3c2..29c5a3d 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
@@ -16,6 +16,8 @@
 
 package com.android.server.biometrics.sensors.fingerprint.aidl;
 
+import static com.android.systemui.shared.Flags.sidefpsControllerRefactor;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.TaskStackListener;
@@ -48,6 +50,7 @@
 import com.android.server.biometrics.log.Probe;
 import com.android.server.biometrics.sensors.AuthSessionCoordinator;
 import com.android.server.biometrics.sensors.AuthenticationClient;
+import com.android.server.biometrics.sensors.AuthenticationStateListeners;
 import com.android.server.biometrics.sensors.BiometricNotificationUtils;
 import com.android.server.biometrics.sensors.ClientMonitorCallback;
 import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
@@ -84,6 +87,7 @@
     private final int mSkipWaitForPowerVendorAcquireMessage;
     private final long mFingerUpIgnoresPower = 500;
     private final AuthSessionCoordinator mAuthSessionCoordinator;
+    @NonNull private final AuthenticationStateListeners mAuthenticationStateListeners;
     @Nullable
     private ICancellationSignal mCancellationSignal;
     private boolean mIsPointerDown;
@@ -110,7 +114,9 @@
             boolean isStrongBiometric,
             @Nullable TaskStackListener taskStackListener,
             @Nullable IUdfpsOverlayController udfpsOverlayController,
+            // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
             @Nullable ISidefpsController sidefpsController,
+            @NonNull AuthenticationStateListeners authenticationStateListeners,
             boolean allowBackgroundAuthentication,
             @NonNull FingerprintSensorPropertiesInternal sensorProps,
             @NonNull Handler handler,
@@ -136,7 +142,12 @@
                 false /* shouldVibrate */,
                 biometricStrength);
         setRequestId(requestId);
-        mSensorOverlays = new SensorOverlays(udfpsOverlayController, sidefpsController);
+        if (sidefpsControllerRefactor()) {
+            mSensorOverlays = new SensorOverlays(udfpsOverlayController);
+        } else {
+            mSensorOverlays = new SensorOverlays(udfpsOverlayController, sidefpsController);
+        }
+        mAuthenticationStateListeners = authenticationStateListeners;
         mSensorProps = sensorProps;
         mALSProbeCallback = getLogger().getAmbientLightProbe(false /* startWithClient */);
         mHandler = handler;
@@ -216,6 +227,9 @@
         if (authenticated) {
             mState = STATE_STOPPED;
             mSensorOverlays.hide(getSensorId());
+            if (sidefpsControllerRefactor()) {
+                mAuthenticationStateListeners.onAuthenticationStopped();
+            }
         } else {
             mState = STATE_STARTED_PAUSED_ATTEMPTED;
         }
@@ -241,6 +255,9 @@
                 // controlled by the HAL, the framework must stop the sensor before finishing the
                 // client.
                 mSensorOverlays.hide(getSensorId());
+                if (sidefpsControllerRefactor()) {
+                    mAuthenticationStateListeners.onAuthenticationStopped();
+                }
                 onErrorInternal(errorCode, 0 /* vendorCode */, false /* finish */);
                 cancel();
             }
@@ -266,11 +283,17 @@
         }
 
         mSensorOverlays.hide(getSensorId());
+        if (sidefpsControllerRefactor()) {
+            mAuthenticationStateListeners.onAuthenticationStopped();
+        }
     }
 
     @Override
     protected void startHalOperation() {
-        mSensorOverlays.show(getSensorId(), getShowOverlayReason(), this);
+        mSensorOverlays.show(getSensorId(), getRequestReason(), this);
+        if (sidefpsControllerRefactor()) {
+            mAuthenticationStateListeners.onAuthenticationStarted(getRequestReason());
+        }
 
         try {
             mCancellationSignal = doAuthenticate();
@@ -280,6 +303,9 @@
                     BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE,
                     0 /* vendorCode */);
             mSensorOverlays.hide(getSensorId());
+            if (sidefpsControllerRefactor()) {
+                mAuthenticationStateListeners.onAuthenticationStopped();
+            }
             mCallback.onClientFinished(this, false /* success */);
         }
     }
@@ -323,6 +349,9 @@
     @Override
     protected void stopHalOperation() {
         mSensorOverlays.hide(getSensorId());
+        if (sidefpsControllerRefactor()) {
+            mAuthenticationStateListeners.onAuthenticationStopped();
+        }
         unsubscribeBiometricContext();
 
         if (mCancellationSignal != null) {
@@ -423,6 +452,9 @@
         }
 
         mSensorOverlays.hide(getSensorId());
+        if (sidefpsControllerRefactor()) {
+            mAuthenticationStateListeners.onAuthenticationStopped();
+        }
         mCallback.onClientFinished(this, false /* success */);
     }
 
@@ -450,6 +482,9 @@
         }
 
         mSensorOverlays.hide(getSensorId());
+        if (sidefpsControllerRefactor()) {
+            mAuthenticationStateListeners.onAuthenticationStopped();
+        }
         mCallback.onClientFinished(this, false /* success */);
     }
 
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java
index e2413ee..e58e5ae 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java
@@ -16,10 +16,12 @@
 
 package com.android.server.biometrics.sensors.fingerprint.aidl;
 
+import static com.android.systemui.shared.Flags.sidefpsControllerRefactor;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
-import android.hardware.biometrics.BiometricOverlayConstants;
+import android.hardware.biometrics.BiometricRequestConstants;
 import android.hardware.biometrics.common.ICancellationSignal;
 import android.hardware.fingerprint.FingerprintAuthenticateOptions;
 import android.hardware.fingerprint.IUdfpsOverlayController;
@@ -66,7 +68,12 @@
                 true /* shouldVibrate */, biometricLogger, biometricContext);
         setRequestId(requestId);
         mIsStrongBiometric = isStrongBiometric;
-        mSensorOverlays = new SensorOverlays(udfpsOverlayController, null /* sideFpsController*/);
+        if (sidefpsControllerRefactor()) {
+            mSensorOverlays = new SensorOverlays(udfpsOverlayController);
+        } else {
+            mSensorOverlays = new SensorOverlays(
+                    udfpsOverlayController, null /* sideFpsController */);
+        }
         mOptions = options;
     }
 
@@ -93,7 +100,7 @@
 
     @Override
     protected void startHalOperation() {
-        mSensorOverlays.show(getSensorId(), BiometricOverlayConstants.REASON_AUTH_KEYGUARD,
+        mSensorOverlays.show(getSensorId(), BiometricRequestConstants.REASON_AUTH_KEYGUARD,
                 this);
 
         try {
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
index 06550d8..c0761ed 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
@@ -16,6 +16,8 @@
 
 package com.android.server.biometrics.sensors.fingerprint.aidl;
 
+import static com.android.systemui.shared.Flags.sidefpsControllerRefactor;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
@@ -42,6 +44,7 @@
 import com.android.server.biometrics.log.CallbackWithProbe;
 import com.android.server.biometrics.log.OperationContextExt;
 import com.android.server.biometrics.log.Probe;
+import com.android.server.biometrics.sensors.AuthenticationStateListeners;
 import com.android.server.biometrics.sensors.BiometricNotificationUtils;
 import com.android.server.biometrics.sensors.BiometricUtils;
 import com.android.server.biometrics.sensors.ClientMonitorCallback;
@@ -65,6 +68,7 @@
     @NonNull private final CallbackWithProbe<Probe> mALSProbeCallback;
 
     private final @FingerprintManager.EnrollReason int mEnrollReason;
+    @NonNull private final AuthenticationStateListeners mAuthenticationStateListeners;
     @Nullable private ICancellationSignal mCancellationSignal;
     private final int mMaxTemplatesPerUser;
     private boolean mIsPointerDown;
@@ -80,15 +84,18 @@
         }
     }
 
-    public FingerprintEnrollClient(@NonNull Context context,
-            @NonNull Supplier<AidlSession> lazyDaemon, @NonNull IBinder token, long requestId,
+    public FingerprintEnrollClient(
+            @NonNull Context context, @NonNull Supplier<AidlSession> lazyDaemon,
+            @NonNull IBinder token, long requestId,
             @NonNull ClientMonitorCallbackConverter listener, int userId,
             @NonNull byte[] hardwareAuthToken, @NonNull String owner,
             @NonNull BiometricUtils<Fingerprint> utils, int sensorId,
             @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
             @NonNull FingerprintSensorPropertiesInternal sensorProps,
             @Nullable IUdfpsOverlayController udfpsOverlayController,
+            // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
             @Nullable ISidefpsController sidefpsController,
+            @NonNull AuthenticationStateListeners authenticationStateListeners,
             int maxTemplatesPerUser, @FingerprintManager.EnrollReason int enrollReason) {
         // UDFPS haptics occur when an image is acquired (instead of when the result is known)
         super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, owner, utils,
@@ -96,7 +103,13 @@
                 logger, biometricContext);
         setRequestId(requestId);
         mSensorProps = sensorProps;
-        mSensorOverlays = new SensorOverlays(udfpsOverlayController, sidefpsController);
+        if (sidefpsControllerRefactor()) {
+            mSensorOverlays = new SensorOverlays(udfpsOverlayController);
+        } else {
+            mSensorOverlays = new SensorOverlays(udfpsOverlayController, sidefpsController);
+        }
+        mAuthenticationStateListeners = authenticationStateListeners;
+
         mMaxTemplatesPerUser = maxTemplatesPerUser;
 
         mALSProbeCallback = getLogger().getAmbientLightProbe(true /* startWithClient */);
@@ -130,7 +143,11 @@
 
         if (remaining == 0) {
             mSensorOverlays.hide(getSensorId());
+            if (sidefpsControllerRefactor()) {
+                mAuthenticationStateListeners.onAuthenticationStopped();
+            }
         }
+
     }
 
     @Override
@@ -159,8 +176,10 @@
     @Override
     public void onError(int errorCode, int vendorCode) {
         super.onError(errorCode, vendorCode);
-
         mSensorOverlays.hide(getSensorId());
+        if (sidefpsControllerRefactor()) {
+            mAuthenticationStateListeners.onAuthenticationStopped();
+        }
     }
 
     @Override
@@ -171,8 +190,12 @@
 
     @Override
     protected void startHalOperation() {
-        mSensorOverlays.show(getSensorId(), getOverlayReasonFromEnrollReason(mEnrollReason),
+        mSensorOverlays.show(getSensorId(), getRequestReasonFromEnrollReason(mEnrollReason),
                 this);
+        if (sidefpsControllerRefactor()) {
+            mAuthenticationStateListeners.onAuthenticationStarted(
+                    getRequestReasonFromEnrollReason(mEnrollReason));
+        }
 
         BiometricNotificationUtils.cancelBadCalibrationNotification(getContext());
         try {
@@ -210,6 +233,10 @@
     @Override
     protected void stopHalOperation() {
         mSensorOverlays.hide(getSensorId());
+        if (sidefpsControllerRefactor()) {
+            mAuthenticationStateListeners.onAuthenticationStopped();
+        }
+
         unsubscribeBiometricContext();
 
         if (mCancellationSignal != null) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
index 9985b06..032ab87 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
@@ -64,6 +64,7 @@
 import com.android.server.biometrics.log.BiometricLogger;
 import com.android.server.biometrics.sensors.AuthSessionCoordinator;
 import com.android.server.biometrics.sensors.AuthenticationClient;
+import com.android.server.biometrics.sensors.AuthenticationStateListeners;
 import com.android.server.biometrics.sensors.BaseClientMonitor;
 import com.android.server.biometrics.sensors.BiometricScheduler;
 import com.android.server.biometrics.sensors.BiometricStateCallback;
@@ -108,6 +109,8 @@
     @NonNull
     private final BiometricStateCallback mBiometricStateCallback;
     @NonNull
+    private final AuthenticationStateListeners mAuthenticationStateListeners;
+    @NonNull
     private final String mHalInstanceName;
     @NonNull
     private final Handler mHandler;
@@ -122,6 +125,7 @@
     @NonNull private final BiometricContext mBiometricContext;
     @Nullable private IFingerprint mDaemon;
     @Nullable private IUdfpsOverlayController mUdfpsOverlayController;
+    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
     @Nullable private ISidefpsController mSidefpsController;
     private AuthSessionCoordinator mAuthSessionCoordinator;
     @Nullable private AuthenticationStatsCollector mAuthenticationStatsCollector;
@@ -157,16 +161,19 @@
 
     public FingerprintProvider(@NonNull Context context,
             @NonNull BiometricStateCallback biometricStateCallback,
+            @NonNull AuthenticationStateListeners authenticationStateListeners,
             @NonNull SensorProps[] props, @NonNull String halInstanceName,
             @NonNull LockoutResetDispatcher lockoutResetDispatcher,
             @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher,
             @NonNull BiometricContext biometricContext) {
-        this(context, biometricStateCallback, props, halInstanceName, lockoutResetDispatcher,
-                gestureAvailabilityDispatcher, biometricContext, null /* daemon */);
+        this(context, biometricStateCallback, authenticationStateListeners, props, halInstanceName,
+                lockoutResetDispatcher, gestureAvailabilityDispatcher, biometricContext,
+                null /* daemon */);
     }
 
     @VisibleForTesting FingerprintProvider(@NonNull Context context,
             @NonNull BiometricStateCallback biometricStateCallback,
+            @NonNull AuthenticationStateListeners authenticationStateListeners,
             @NonNull SensorProps[] props, @NonNull String halInstanceName,
             @NonNull LockoutResetDispatcher lockoutResetDispatcher,
             @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher,
@@ -174,6 +181,7 @@
             IFingerprint daemon) {
         mContext = context;
         mBiometricStateCallback = biometricStateCallback;
+        mAuthenticationStateListeners = authenticationStateListeners;
         mHalInstanceName = halInstanceName;
         mFingerprintSensors = new SensorList<>(ActivityManager.getService());
         mHandler = new Handler(Looper.getMainLooper());
@@ -434,7 +442,7 @@
                     mBiometricContext,
                     mFingerprintSensors.get(sensorId).getSensorProperties(),
                     mUdfpsOverlayController, mSidefpsController,
-                    maxTemplatesPerUser, enrollReason);
+                    mAuthenticationStateListeners, maxTemplatesPerUser, enrollReason);
             scheduleForSensor(sensorId, client, new ClientMonitorCompositeCallback(
                     mBiometricStateCallback, new ClientMonitorCallback() {
                 @Override
@@ -498,7 +506,7 @@
                     mBiometricContext, isStrongBiometric,
                     mTaskStackListener,
                     mUdfpsOverlayController, mSidefpsController,
-                    allowBackgroundAuthentication,
+                    mAuthenticationStateListeners, allowBackgroundAuthentication,
                     mFingerprintSensors.get(sensorId).getSensorProperties(), mHandler,
                     Utils.getCurrentStrength(sensorId),
                     SystemClock.elapsedRealtimeClock(),
@@ -732,6 +740,7 @@
         }
     }
 
+    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
     @Override
     public void setSidefpsController(@NonNull ISidefpsController controller) {
         mSidefpsController = controller;
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
index 8bfa560..d3cecd0 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
@@ -68,6 +68,7 @@
 import com.android.server.biometrics.sensors.AuthSessionCoordinator;
 import com.android.server.biometrics.sensors.AuthenticationClient;
 import com.android.server.biometrics.sensors.AuthenticationConsumer;
+import com.android.server.biometrics.sensors.AuthenticationStateListeners;
 import com.android.server.biometrics.sensors.BaseClientMonitor;
 import com.android.server.biometrics.sensors.BiometricScheduler;
 import com.android.server.biometrics.sensors.BiometricStateCallback;
@@ -115,6 +116,7 @@
 
     final Context mContext;
     @NonNull private final BiometricStateCallback mBiometricStateCallback;
+    @NonNull private final AuthenticationStateListeners mAuthenticationStateListeners;
     private final ActivityTaskManager mActivityTaskManager;
     @NonNull private final FingerprintSensorPropertiesInternal mSensorProperties;
     private final BiometricScheduler mScheduler;
@@ -128,6 +130,8 @@
     @Nullable private IBiometricsFingerprint mDaemon;
     @NonNull private final HalResultController mHalResultController;
     @Nullable private IUdfpsOverlayController mUdfpsOverlayController;
+
+    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
     @Nullable private ISidefpsController mSidefpsController;
     @NonNull private final BiometricContext mBiometricContext;
     @Nullable private AuthenticationStatsCollector mAuthenticationStatsCollector;
@@ -330,6 +334,7 @@
     @VisibleForTesting
     Fingerprint21(@NonNull Context context,
             @NonNull BiometricStateCallback biometricStateCallback,
+            @NonNull AuthenticationStateListeners authenticationStateListeners,
             @NonNull FingerprintSensorPropertiesInternal sensorProps,
             @NonNull BiometricScheduler scheduler,
             @NonNull Handler handler,
@@ -338,6 +343,7 @@
             @NonNull BiometricContext biometricContext) {
         mContext = context;
         mBiometricStateCallback = biometricStateCallback;
+        mAuthenticationStateListeners = authenticationStateListeners;
         mBiometricContext = biometricContext;
 
         mSensorProperties = sensorProps;
@@ -378,6 +384,7 @@
 
     public static Fingerprint21 newInstance(@NonNull Context context,
             @NonNull BiometricStateCallback biometricStateCallback,
+            @NonNull AuthenticationStateListeners authenticationStateListeners,
             @NonNull FingerprintSensorPropertiesInternal sensorProps,
             @NonNull Handler handler,
             @NonNull LockoutResetDispatcher lockoutResetDispatcher,
@@ -388,8 +395,9 @@
                         gestureAvailabilityDispatcher);
         final HalResultController controller = new HalResultController(sensorProps.sensorId,
                 context, handler, scheduler);
-        return new Fingerprint21(context, biometricStateCallback, sensorProps, scheduler, handler,
-                lockoutResetDispatcher, controller, BiometricContext.getInstance(context));
+        return new Fingerprint21(context, biometricStateCallback, authenticationStateListeners,
+                sensorProps, scheduler, handler, lockoutResetDispatcher, controller,
+                BiometricContext.getInstance(context));
     }
 
     @Override
@@ -719,7 +727,10 @@
                 mSensorProperties.sensorId,
                 createLogger(BiometricsProtoEnums.ACTION_ENROLL,
                         BiometricsProtoEnums.CLIENT_UNKNOWN, mAuthenticationStatsCollector),
-                mBiometricContext, mUdfpsOverlayController, mSidefpsController, enrollReason);
+                mBiometricContext, mUdfpsOverlayController,
+                // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
+                mSidefpsController,
+                mAuthenticationStateListeners, enrollReason);
         mScheduler.scheduleClientMonitor(client, new ClientMonitorCallback() {
             @Override
             public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
@@ -761,10 +772,14 @@
                                 BiometricsProtoEnums.CLIENT_UNKNOWN,
                                 mAuthenticationStatsCollector),
                         mBiometricContext, null /* sensorProps */,
-                        mUdfpsOverlayController, mSidefpsController,
+                        mUdfpsOverlayController,
+                        // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
+                        mSidefpsController,
+                        mAuthenticationStateListeners,
                         mContext.getResources().getInteger(
                                 com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser),
                         enrollReason);
+
         mScheduler.scheduleClientMonitor(client, new ClientMonitorCallback() {
             @Override
             public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
@@ -880,6 +895,7 @@
                         mBiometricContext, isStrongBiometric,
                         mTaskStackListener,
                         mUdfpsOverlayController, mSidefpsController,
+                        mAuthenticationStateListeners,
                         allowBackgroundAuthentication, mSensorProperties, mHandler,
                         Utils.getCurrentStrength(mSensorId), null /* clock */, mLockoutTracker);
         mScheduler.scheduleClientMonitor(client, mBiometricStateCallback);
@@ -898,6 +914,7 @@
                 mBiometricContext, isStrongBiometric,
                 mTaskStackListener, mLockoutTracker,
                 mUdfpsOverlayController, mSidefpsController,
+                mAuthenticationStateListeners,
                 allowBackgroundAuthentication, mSensorProperties,
                 Utils.getCurrentStrength(mSensorId));
         mScheduler.scheduleClientMonitor(client, mBiometricStateCallback);
@@ -1123,6 +1140,7 @@
         mUdfpsOverlayController = controller;
     }
 
+    // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
     @Override
     public void setSidefpsController(@NonNull ISidefpsController controller) {
         mSidefpsController = controller;
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java
index c1a9370..88dae6f 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java
@@ -41,6 +41,7 @@
 import com.android.internal.R;
 import com.android.server.biometrics.log.BiometricContext;
 import com.android.server.biometrics.sensors.AuthenticationConsumer;
+import com.android.server.biometrics.sensors.AuthenticationStateListeners;
 import com.android.server.biometrics.sensors.BaseClientMonitor;
 import com.android.server.biometrics.sensors.BiometricScheduler;
 import com.android.server.biometrics.sensors.BiometricStateCallback;
@@ -248,6 +249,7 @@
 
     public static Fingerprint21UdfpsMock newInstance(@NonNull Context context,
             @NonNull BiometricStateCallback biometricStateCallback,
+            @NonNull AuthenticationStateListeners authenticationStateListeners,
             @NonNull FingerprintSensorPropertiesInternal sensorProps,
             @NonNull LockoutResetDispatcher lockoutResetDispatcher,
             @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher,
@@ -259,8 +261,9 @@
                 new TestableBiometricScheduler(TAG, handler, gestureAvailabilityDispatcher);
         final MockHalResultController controller =
                 new MockHalResultController(sensorProps.sensorId, context, handler, scheduler);
-        return new Fingerprint21UdfpsMock(context, biometricStateCallback, sensorProps, scheduler,
-                handler, lockoutResetDispatcher, controller, biometricContext);
+        return new Fingerprint21UdfpsMock(context, biometricStateCallback,
+                authenticationStateListeners, sensorProps, scheduler, handler,
+                lockoutResetDispatcher, controller, biometricContext);
     }
 
     private static abstract class FakeFingerRunnable implements Runnable {
@@ -388,14 +391,15 @@
 
     private Fingerprint21UdfpsMock(@NonNull Context context,
             @NonNull BiometricStateCallback biometricStateCallback,
+            @NonNull AuthenticationStateListeners authenticationStateListeners,
             @NonNull FingerprintSensorPropertiesInternal sensorProps,
             @NonNull TestableBiometricScheduler scheduler,
             @NonNull Handler handler,
             @NonNull LockoutResetDispatcher lockoutResetDispatcher,
             @NonNull MockHalResultController controller,
             @NonNull BiometricContext biometricContext) {
-        super(context, biometricStateCallback, sensorProps, scheduler, handler,
-                lockoutResetDispatcher, controller, biometricContext);
+        super(context, biometricStateCallback, authenticationStateListeners, sensorProps, scheduler,
+                handler, lockoutResetDispatcher, controller, biometricContext);
         mScheduler = scheduler;
         mScheduler.init(this);
         mHandler = handler;
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
index 9966e91..4c1d4d6 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
@@ -16,6 +16,8 @@
 
 package com.android.server.biometrics.sensors.fingerprint.hidl;
 
+import static com.android.systemui.shared.Flags.sidefpsControllerRefactor;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.TaskStackListener;
@@ -40,6 +42,7 @@
 import com.android.server.biometrics.log.CallbackWithProbe;
 import com.android.server.biometrics.log.Probe;
 import com.android.server.biometrics.sensors.AuthenticationClient;
+import com.android.server.biometrics.sensors.AuthenticationStateListeners;
 import com.android.server.biometrics.sensors.BiometricNotificationUtils;
 import com.android.server.biometrics.sensors.ClientMonitorCallback;
 import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
@@ -68,6 +71,7 @@
     @NonNull private final SensorOverlays mSensorOverlays;
     @NonNull private final FingerprintSensorPropertiesInternal mSensorProps;
     @NonNull private final CallbackWithProbe<Probe> mALSProbeCallback;
+    @NonNull private final AuthenticationStateListeners mAuthenticationStateListeners;
 
     private boolean mIsPointerDown;
 
@@ -81,7 +85,9 @@
             @NonNull TaskStackListener taskStackListener,
             @NonNull LockoutFrameworkImpl lockoutTracker,
             @Nullable IUdfpsOverlayController udfpsOverlayController,
+            // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
             @Nullable ISidefpsController sidefpsController,
+            @NonNull AuthenticationStateListeners authenticationStateListeners,
             boolean allowBackgroundAuthentication,
             @NonNull FingerprintSensorPropertiesInternal sensorProps,
             @Authenticators.Types int sensorStrength) {
@@ -91,7 +97,12 @@
                 false /* shouldVibrate */, sensorStrength);
         setRequestId(requestId);
         mLockoutFrameworkImpl = lockoutTracker;
-        mSensorOverlays = new SensorOverlays(udfpsOverlayController, sidefpsController);
+        if (sidefpsControllerRefactor()) {
+            mSensorOverlays = new SensorOverlays(udfpsOverlayController);
+        } else {
+            mSensorOverlays = new SensorOverlays(udfpsOverlayController, sidefpsController);
+        }
+        mAuthenticationStateListeners = authenticationStateListeners;
         mSensorProps = sensorProps;
         mALSProbeCallback = getLogger().getAmbientLightProbe(false /* startWithClient */);
     }
@@ -128,6 +139,9 @@
             mState = STATE_STOPPED;
             resetFailedAttempts(getTargetUserId());
             mSensorOverlays.hide(getSensorId());
+            if (sidefpsControllerRefactor()) {
+                mAuthenticationStateListeners.onAuthenticationStopped();
+            }
         } else {
             mState = STATE_STARTED_PAUSED_ATTEMPTED;
             final @LockoutTracker.LockoutMode int lockoutMode =
@@ -141,6 +155,9 @@
                 // controlled by the HAL, the framework must stop the sensor before finishing the
                 // client.
                 mSensorOverlays.hide(getSensorId());
+                if (sidefpsControllerRefactor()) {
+                    mAuthenticationStateListeners.onAuthenticationStopped();
+                }
                 onErrorInternal(errorCode, 0 /* vendorCode */, false /* finish */);
                 cancel();
             }
@@ -156,6 +173,9 @@
         }
 
         mSensorOverlays.hide(getSensorId());
+        if (sidefpsControllerRefactor()) {
+            mAuthenticationStateListeners.onAuthenticationStopped();
+        }
     }
 
     private void resetFailedAttempts(int userId) {
@@ -205,7 +225,10 @@
 
     @Override
     protected void startHalOperation() {
-        mSensorOverlays.show(getSensorId(), getShowOverlayReason(), this);
+        mSensorOverlays.show(getSensorId(), getRequestReason(), this);
+        if (sidefpsControllerRefactor()) {
+            mAuthenticationStateListeners.onAuthenticationStarted(getRequestReason());
+        }
 
         try {
             // GroupId was never used. In fact, groupId is always the same as userId.
@@ -215,6 +238,9 @@
             onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE,
                     0 /* vendorCode */);
             mSensorOverlays.hide(getSensorId());
+            if (sidefpsControllerRefactor()) {
+                mAuthenticationStateListeners.onAuthenticationStopped();
+            }
             mCallback.onClientFinished(this, false /* success */);
         }
     }
@@ -222,6 +248,9 @@
     @Override
     protected void stopHalOperation() {
         mSensorOverlays.hide(getSensorId());
+        if (sidefpsControllerRefactor()) {
+            mAuthenticationStateListeners.onAuthenticationStopped();
+        }
 
         try {
             getFreshDaemon().cancel();
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java
index 0d7f9f2..6e029d2 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java
@@ -16,12 +16,14 @@
 
 package com.android.server.biometrics.sensors.fingerprint.hidl;
 
+import static com.android.systemui.shared.Flags.sidefpsControllerRefactor;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
 import android.hardware.biometrics.BiometricAuthenticator;
 import android.hardware.biometrics.BiometricFingerprintConstants;
-import android.hardware.biometrics.BiometricOverlayConstants;
+import android.hardware.biometrics.BiometricRequestConstants;
 import android.hardware.biometrics.fingerprint.PointerContext;
 import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
 import android.hardware.fingerprint.FingerprintAuthenticateOptions;
@@ -71,7 +73,12 @@
                 options.getOpPackageName(), 0 /* cookie */, options.getSensorId(),
                 true /* shouldVibrate */, biometricLogger, biometricContext);
         setRequestId(requestId);
-        mSensorOverlays = new SensorOverlays(udfpsOverlayController, null /* sideFpsController */);
+        if (sidefpsControllerRefactor()) {
+            mSensorOverlays = new SensorOverlays(udfpsOverlayController);
+        } else {
+            mSensorOverlays = new SensorOverlays(
+                    udfpsOverlayController, null /* sideFpsController */);
+        }
         mIsStrongBiometric = isStrongBiometric;
     }
 
@@ -97,7 +104,7 @@
 
     @Override
     protected void startHalOperation() {
-        mSensorOverlays.show(getSensorId(), BiometricOverlayConstants.REASON_AUTH_KEYGUARD,
+        mSensorOverlays.show(getSensorId(), BiometricRequestConstants.REASON_AUTH_KEYGUARD,
                 this);
 
         try {
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
index 382e7e2..26332ff 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
@@ -16,6 +16,8 @@
 
 package com.android.server.biometrics.sensors.fingerprint.hidl;
 
+import static com.android.systemui.shared.Flags.sidefpsControllerRefactor;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
@@ -34,6 +36,7 @@
 
 import com.android.server.biometrics.log.BiometricContext;
 import com.android.server.biometrics.log.BiometricLogger;
+import com.android.server.biometrics.sensors.AuthenticationStateListeners;
 import com.android.server.biometrics.sensors.BiometricNotificationUtils;
 import com.android.server.biometrics.sensors.BiometricUtils;
 import com.android.server.biometrics.sensors.ClientMonitorCallback;
@@ -58,22 +61,31 @@
 
     @NonNull private final SensorOverlays mSensorOverlays;
     private final @FingerprintManager.EnrollReason int mEnrollReason;
+    @NonNull private final AuthenticationStateListeners mAuthenticationStateListeners;
     private boolean mIsPointerDown;
 
-    FingerprintEnrollClient(@NonNull Context context,
-            @NonNull Supplier<IBiometricsFingerprint> lazyDaemon, @NonNull IBinder token,
-            long requestId, @NonNull ClientMonitorCallbackConverter listener, int userId,
+    FingerprintEnrollClient(
+            @NonNull Context context, @NonNull Supplier<IBiometricsFingerprint> lazyDaemon,
+            @NonNull IBinder token, long requestId,
+            @NonNull ClientMonitorCallbackConverter listener, int userId,
             @NonNull byte[] hardwareAuthToken, @NonNull String owner,
             @NonNull BiometricUtils<Fingerprint> utils, int timeoutSec, int sensorId,
             @NonNull BiometricLogger biometricLogger, @NonNull BiometricContext biometricContext,
             @Nullable IUdfpsOverlayController udfpsOverlayController,
+            // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
             @Nullable ISidefpsController sidefpsController,
+            @NonNull AuthenticationStateListeners authenticationStateListeners,
             @FingerprintManager.EnrollReason int enrollReason) {
         super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, owner, utils,
                 timeoutSec, sensorId, true /* shouldVibrate */, biometricLogger,
                 biometricContext);
         setRequestId(requestId);
-        mSensorOverlays = new SensorOverlays(udfpsOverlayController, sidefpsController);
+        if (sidefpsControllerRefactor()) {
+            mSensorOverlays = new SensorOverlays(udfpsOverlayController);
+        } else {
+            mSensorOverlays = new SensorOverlays(udfpsOverlayController, sidefpsController);
+        }
+        mAuthenticationStateListeners = authenticationStateListeners;
 
         mEnrollReason = enrollReason;
         if (enrollReason == FingerprintManager.ENROLL_FIND_SENSOR) {
@@ -110,8 +122,12 @@
 
     @Override
     protected void startHalOperation() {
-        mSensorOverlays.show(getSensorId(), getOverlayReasonFromEnrollReason(mEnrollReason),
+        mSensorOverlays.show(getSensorId(), getRequestReasonFromEnrollReason(mEnrollReason),
                 this);
+        if (sidefpsControllerRefactor()) {
+            mAuthenticationStateListeners.onAuthenticationStarted(
+                    getRequestReasonFromEnrollReason(mEnrollReason));
+        }
 
         BiometricNotificationUtils.cancelBadCalibrationNotification(getContext());
         try {
@@ -122,6 +138,9 @@
             onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE,
                     0 /* vendorCode */);
             mSensorOverlays.hide(getSensorId());
+            if (sidefpsControllerRefactor()) {
+                mAuthenticationStateListeners.onAuthenticationStopped();
+            }
             mCallback.onClientFinished(this, false /* success */);
         }
     }
@@ -129,6 +148,9 @@
     @Override
     protected void stopHalOperation() {
         mSensorOverlays.hide(getSensorId());
+        if (sidefpsControllerRefactor()) {
+            mAuthenticationStateListeners.onAuthenticationStopped();
+        }
 
         try {
             getFreshDaemon().cancel();
@@ -149,6 +171,9 @@
 
         if (remaining == 0) {
             mSensorOverlays.hide(getSensorId());
+            if (sidefpsControllerRefactor()) {
+                mAuthenticationStateListeners.onAuthenticationStopped();
+            }
         }
     }
 
@@ -170,6 +195,9 @@
         super.onError(errorCode, vendorCode);
 
         mSensorOverlays.hide(getSensorId());
+        if (sidefpsControllerRefactor()) {
+            mAuthenticationStateListeners.onAuthenticationStopped();
+        }
     }
 
     @Override
diff --git a/services/core/java/com/android/server/companion/virtual/VirtualDeviceManagerInternal.java b/services/core/java/com/android/server/companion/virtual/VirtualDeviceManagerInternal.java
index cecde55..823788f 100644
--- a/services/core/java/com/android/server/companion/virtual/VirtualDeviceManagerInternal.java
+++ b/services/core/java/com/android/server/companion/virtual/VirtualDeviceManagerInternal.java
@@ -21,6 +21,7 @@
 import android.companion.virtual.IVirtualDevice;
 import android.companion.virtual.VirtualDevice;
 import android.companion.virtual.sensor.VirtualSensor;
+import android.content.Context;
 import android.os.LocaleList;
 import android.util.ArraySet;
 
@@ -149,6 +150,14 @@
     public abstract @NonNull ArraySet<Integer> getDisplayIdsForDevice(int deviceId);
 
     /**
+     * Checks whether the passed {@code deviceId} is a valid virtual device ID or not.
+     *
+     * <p>{@link Context#DEVICE_ID_DEFAULT} is not valid as it is the ID of the default
+     * device which is not a virtual device.</p>
+     */
+    public abstract boolean isValidVirtualDeviceId(int deviceId);
+
+    /**
      * Returns the ID of the device which owns the display with the given ID.
      *
      * <p>In case the virtual display ID is invalid or doesn't belong to a virtual device, then
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 575b309..df179a9 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -105,6 +105,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.config.appcloning.AppCloningDeviceConfigHelper;
+import com.android.internal.content.PackageMonitor;
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.os.BackgroundThread;
@@ -438,19 +439,23 @@
         }
     };
 
-    private final BroadcastReceiver mForceStoppedReceiver = new BroadcastReceiver() {
+    private static class PackageMonitorImpl extends PackageMonitor {
         @Override
-        public void onReceive(Context context, Intent intent) {
+        public boolean onHandleForceStop(Intent intent, String[] packageNames, int uid,
+                boolean doit, Bundle extras) {
             final boolean isLoggable = Log.isLoggable(TAG, Log.DEBUG);
-            // For now, just log when packages were force-stopped and unstopped for debugging.
             if (isLoggable) {
-                if (Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())) {
-                    Log.d(TAG, "Package force-stopped: "
-                            + intent.getData().getSchemeSpecificPart());
-                } else if (Intent.ACTION_PACKAGE_UNSTOPPED.equals(intent.getAction())) {
-                    Log.d(TAG, "Package unstopped: "
-                            + intent.getData().getSchemeSpecificPart());
-                }
+                Log.d(TAG, "Package force-stopped: " + Arrays.toString(packageNames)
+                        + ", uid: " + uid);
+            }
+            return false;
+        }
+
+        @Override
+        public void onPackageUnstopped(String packageName, int uid, Bundle extras) {
+            final boolean isLoggable = Log.isLoggable(TAG, Log.DEBUG);
+            if (isLoggable) {
+                Log.d(TAG, "Package unstopped: " + packageName + ", uid: " + uid);
             }
         }
     };
@@ -718,11 +723,10 @@
         mContext.registerReceiverAsUser(
                 mUserIntentReceiver, UserHandle.ALL, intentFilter, null, null);
 
-        intentFilter = new IntentFilter();
-        intentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
-        intentFilter.addAction(Intent.ACTION_PACKAGE_UNSTOPPED);
-        intentFilter.addDataScheme("package");
-        context.registerReceiver(mForceStoppedReceiver, intentFilter);
+
+        final PackageMonitor packageMonitor = new PackageMonitorImpl();
+        packageMonitor.register(mContext, null /* thread */, UserHandle.ALL,
+                false /* externalStorage */);
 
         intentFilter = new IntentFilter(Intent.ACTION_TIME_CHANGED);
         context.registerReceiver(mOtherIntentsReceiver, intentFilter);
@@ -1288,7 +1292,11 @@
      */
     private boolean isPackageStopped(String packageName, int userId) {
         if (android.content.pm.Flags.stayStopped()) {
-            return mPackageManagerInternal.isPackageStopped(packageName, userId);
+            try {
+                return mPackageManagerInternal.isPackageStopped(packageName, userId);
+            } catch (NameNotFoundException e) {
+                Log.e(TAG, "Couldn't determine stopped state for unknown package: " + packageName);
+            }
         }
         return false;
     }
diff --git a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
index dff14b5..6ec6a12 100644
--- a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
+++ b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
@@ -327,7 +327,7 @@
     Optional<DeviceState> getOverrideState() {
         synchronized (mLock) {
             if (mActiveOverride.isPresent()) {
-                return getStateLocked(mActiveOverride.get().getRequestedState());
+                return getStateLocked(mActiveOverride.get().getRequestedStateIdentifier());
             }
             return Optional.empty();
         }
@@ -342,7 +342,7 @@
     Optional<DeviceState> getOverrideBaseState() {
         synchronized (mLock) {
             if (mActiveBaseStateOverride.isPresent()) {
-                return getStateLocked(mActiveBaseStateOverride.get().getRequestedState());
+                return getStateLocked(mActiveBaseStateOverride.get().getRequestedStateIdentifier());
             }
             return Optional.empty();
         }
@@ -499,6 +499,7 @@
      * @return {@code true} if the pending state has changed as a result of this call, {@code false}
      * otherwise.
      */
+    @GuardedBy("mLock")
     private boolean updatePendingStateLocked() {
         if (mPendingState.isPresent()) {
             // Have pending state, can not configure a new state until the state is committed.
@@ -507,7 +508,8 @@
 
         final DeviceState stateToConfigure;
         if (mActiveOverride.isPresent()) {
-            stateToConfigure = getStateLocked(mActiveOverride.get().getRequestedState()).get();
+            stateToConfigure = getStateLocked(
+                    mActiveOverride.get().getRequestedStateIdentifier()).get();
         } else if (mBaseState.isPresent()
                 && isSupportedStateLocked(mBaseState.get().getIdentifier())) {
             // Base state could have recently become unsupported after a change in supported states.
@@ -599,7 +601,7 @@
             // requested state is committed.
             OverrideRequest activeRequest = mActiveOverride.orElse(null);
             if (activeRequest != null
-                    && activeRequest.getRequestedState() == newState.getIdentifier()) {
+                    && activeRequest.getRequestedStateIdentifier() == newState.getIdentifier()) {
                 ProcessRecord processRecord = mProcessRecords.get(activeRequest.getPid());
                 if (processRecord != null) {
                     processRecord.notifyRequestActiveAsync(activeRequest.getToken());
@@ -666,21 +668,21 @@
                 case STATUS_ACTIVE:
                     mActiveOverride = Optional.of(request);
                     mDeviceStateNotificationController.showStateActiveNotificationIfNeeded(
-                            request.getRequestedState(), request.getUid());
+                            request.getRequestedStateIdentifier(), request.getUid());
                     break;
                 case STATUS_CANCELED:
                     if (mActiveOverride.isPresent() && mActiveOverride.get() == request) {
                         mActiveOverride = Optional.empty();
                         mDeviceStateNotificationController.cancelNotification(
-                                request.getRequestedState());
+                                request.getRequestedStateIdentifier());
                         if ((flags & FLAG_THERMAL_CRITICAL) == FLAG_THERMAL_CRITICAL) {
                             mDeviceStateNotificationController
                                     .showThermalCriticalNotificationIfNeeded(
-                                            request.getRequestedState());
+                                            request.getRequestedStateIdentifier());
                         } else if ((flags & FLAG_POWER_SAVE_ENABLED) == FLAG_POWER_SAVE_ENABLED) {
                             mDeviceStateNotificationController
                                     .showPowerSaveNotificationIfNeeded(
-                                            request.getRequestedState());
+                                            request.getRequestedStateIdentifier());
                         }
                     }
                     break;
@@ -723,7 +725,7 @@
      */
     @GuardedBy("mLock")
     private void enableBaseStateRequestLocked(OverrideRequest request) {
-        setBaseState(request.getRequestedState());
+        setBaseState(request.getRequestedStateIdentifier());
         mActiveBaseStateOverride = Optional.of(request);
         ProcessRecord processRecord = mProcessRecords.get(request.getPid());
         processRecord.notifyRequestActiveAsync(request.getToken());
@@ -762,6 +764,11 @@
         synchronized (mLock) {
             mProcessRecords.remove(processRecord.mPid);
             mOverrideRequestController.handleProcessDied(processRecord.mPid);
+
+            if (shouldCancelOverrideRequestWhenRequesterNotOnTop()) {
+                OverrideRequest request = mActiveOverride.get();
+                mOverrideRequestController.cancelRequest(request);
+            }
         }
     }
 
@@ -787,7 +794,7 @@
             }
 
             OverrideRequest request = new OverrideRequest(token, callingPid, callingUid,
-                    state, flags, OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
+                    deviceState.get(), flags, OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
 
             // If we don't have the CONTROL_DEVICE_STATE permission, we want to show the overlay
             if (!hasControlDeviceStatePermission && mRearDisplayState != null
@@ -848,7 +855,7 @@
             }
 
             OverrideRequest request = new OverrideRequest(token, callingPid, callingUid,
-                    state, flags, OVERRIDE_REQUEST_TYPE_BASE_STATE);
+                    deviceState.get(), flags, OVERRIDE_REQUEST_TYPE_BASE_STATE);
             mOverrideRequestController.addBaseStateRequest(request);
         }
     }
@@ -1318,7 +1325,7 @@
         if (mActiveOverride.isEmpty()) {
             return false;
         }
-        int identifier = mActiveOverride.get().getRequestedState();
+        int identifier = mActiveOverride.get().getRequestedStateIdentifier();
         DeviceState deviceState = mDeviceStates.get(identifier);
         return deviceState.hasFlag(DeviceState.FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP);
     }
diff --git a/services/core/java/com/android/server/devicestate/OverrideRequest.java b/services/core/java/com/android/server/devicestate/OverrideRequest.java
index 74cf184..20485c1 100644
--- a/services/core/java/com/android/server/devicestate/OverrideRequest.java
+++ b/services/core/java/com/android/server/devicestate/OverrideRequest.java
@@ -17,6 +17,7 @@
 package com.android.server.devicestate;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.hardware.devicestate.DeviceStateRequest;
 import android.os.IBinder;
 
@@ -32,7 +33,8 @@
     private final IBinder mToken;
     private final int mPid;
     private final int mUid;
-    private final int mRequestedState;
+    @NonNull
+    private final DeviceState mRequestedState;
     @DeviceStateRequest.RequestFlags
     private final int mFlags;
     @OverrideRequestType
@@ -69,7 +71,7 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface OverrideRequestType {}
 
-    OverrideRequest(IBinder token, int pid, int uid, int requestedState,
+    OverrideRequest(IBinder token, int pid, int uid, @NonNull DeviceState requestedState,
             @DeviceStateRequest.RequestFlags int flags, @OverrideRequestType int requestType) {
         mToken = token;
         mPid = pid;
@@ -91,10 +93,15 @@
         return mUid;
     }
 
-    int getRequestedState() {
+    @NonNull
+    DeviceState getRequestedDeviceState() {
         return mRequestedState;
     }
 
+    int getRequestedStateIdentifier() {
+        return mRequestedState.getIdentifier();
+    }
+
     @DeviceStateRequest.RequestFlags
     int getFlags() {
         return mFlags;
diff --git a/services/core/java/com/android/server/devicestate/OverrideRequestController.java b/services/core/java/com/android/server/devicestate/OverrideRequestController.java
index 46f0bc0..f5f2fa8 100644
--- a/services/core/java/com/android/server/devicestate/OverrideRequestController.java
+++ b/services/core/java/com/android/server/devicestate/OverrideRequestController.java
@@ -204,6 +204,12 @@
         }
 
         if (mRequest != null && mRequest.getPid() == pid) {
+            if (mRequest.getRequestedDeviceState().hasFlag(
+                    DeviceState.FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP)) {
+                cancelCurrentRequestLocked();
+                return;
+            }
+
             if (mStickyRequestsAllowed) {
                 // Do not cancel the requests now because sticky requests are allowed. These
                 // requests will be cancelled on a call to cancelStickyRequests().
@@ -219,7 +225,7 @@
      * listener of all changes to request status as a result of this change.
      */
     void handleBaseStateChanged(int state) {
-        if (mBaseStateRequest != null && state != mBaseStateRequest.getRequestedState()) {
+        if (mBaseStateRequest != null && state != mBaseStateRequest.getRequestedStateIdentifier()) {
             cancelBaseStateOverrideRequest();
         }
         if (mRequest == null) {
@@ -246,11 +252,12 @@
         flags |= isThermalCritical ? FLAG_THERMAL_CRITICAL : 0;
         flags |= isPowerSaveEnabled ? FLAG_POWER_SAVE_ENABLED : 0;
         if (mBaseStateRequest != null && !contains(newSupportedStates,
-                mBaseStateRequest.getRequestedState())) {
+                mBaseStateRequest.getRequestedStateIdentifier())) {
             cancelCurrentBaseStateRequestLocked(flags);
         }
 
-        if (mRequest != null && !contains(newSupportedStates, mRequest.getRequestedState())) {
+        if (mRequest != null && !contains(newSupportedStates,
+                mRequest.getRequestedStateIdentifier())) {
             cancelCurrentRequestLocked(flags);
         }
     }
@@ -262,7 +269,7 @@
         pw.println("Override Request active: " + requestActive);
         if (requestActive) {
             pw.println("Request: mPid=" + overrideRequest.getPid()
-                    + ", mRequestedState=" + overrideRequest.getRequestedState()
+                    + ", mRequestedState=" + overrideRequest.getRequestedStateIdentifier()
                     + ", mFlags=" + overrideRequest.getFlags()
                     + ", mStatus=" + statusToString(STATUS_ACTIVE));
         }
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 80c3a27..b542893 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -583,8 +583,8 @@
         pw.println("  mCurrentLightSensorRate=" + mCurrentLightSensorRate);
         pw.println("  mAmbientLux=" + mAmbientLux);
         pw.println("  mAmbientLuxValid=" + mAmbientLuxValid);
-        pw.println("  mPreThesholdLux=" + mPreThresholdLux);
-        pw.println("  mPreThesholdBrightness=" + mPreThresholdBrightness);
+        pw.println("  mPreThresholdLux=" + mPreThresholdLux);
+        pw.println("  mPreThresholdBrightness=" + mPreThresholdBrightness);
         pw.println("  mAmbientBrighteningThreshold=" + mAmbientBrighteningThreshold);
         pw.println("  mAmbientDarkeningThreshold=" + mAmbientDarkeningThreshold);
         pw.println("  mScreenBrighteningThreshold=" + mScreenBrighteningThreshold);
diff --git a/services/core/java/com/android/server/display/DisplayDeviceInfo.java b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
index 3529b04..b1b1dba 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceInfo.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
@@ -122,11 +122,10 @@
 
     /**
      * Flag: This flag identifies secondary displays that should show system decorations, such as
-     * status bar, navigation bar, home activity or IME.
+     * navigation bar, home activity or wallpaper.
      * <p>Note that this flag doesn't work without {@link #FLAG_TRUSTED}</p>
      * @hide
      */
-    // TODO (b/114338689): Remove the flag and use IWindowManager#setShouldShowSystemDecors
     public static final int FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS = 1 << 12;
 
     /**
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 bd5e189..aa7f07d 100644
--- a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
+++ b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
@@ -93,6 +93,10 @@
             Flags.FLAG_ENABLE_EXTERNAL_VSYNC_PROXIMITY_VOTE,
             Flags::enableExternalVsyncProximityVote);
 
+    private final FlagState mVsyncLowPowerVote = new FlagState(
+            Flags.FLAG_ENABLE_VSYNC_LOW_POWER_VOTE,
+            Flags::enableVsyncLowPowerVote);
+
     private final FlagState mBrightnessWearBedtimeModeClamperFlagState = new FlagState(
             Flags.FLAG_BRIGHTNESS_WEAR_BEDTIME_MODE_CLAMPER,
             Flags::brightnessWearBedtimeModeClamper);
@@ -125,7 +129,6 @@
         return mPowerThrottlingClamperFlagState.isEnabled();
     }
 
-
     /**
      * Returns whether adaptive tone improvements are enabled
      */
@@ -198,6 +201,10 @@
         return mVsyncProximityVote.isEnabled();
     }
 
+    public boolean isVsyncLowPowerVoteEnabled() {
+        return mVsyncLowPowerVote.isEnabled();
+    }
+
     public boolean isBrightnessWearBedtimeModeClamperEnabled() {
         return mBrightnessWearBedtimeModeClamperFlagState.isEnabled();
     }
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 7a723a3..04ecbb9 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
@@ -130,6 +130,14 @@
 }
 
 flag {
+    name: "enable_vsync_low_power_vote"
+    namespace: "display_manager"
+    description: "Feature flag for vsync low power vote"
+    bug: "314920284"
+    is_fixed_read_only: true
+}
+
+flag {
     name: "brightness_wear_bedtime_mode_clamper"
     namespace: "display_manager"
     description: "Feature flag for the Wear Bedtime mode brightness clamper"
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 f7b540b..6e503cb 100644
--- a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
@@ -179,7 +179,7 @@
 
     private final boolean mIsBackUpSmoothDisplayAndForcePeakRefreshRateEnabled;
 
-    private final boolean mVsyncProximityVoteEnabled;
+    private final boolean mDvrrSupported;
 
 
     public DisplayModeDirector(@NonNull Context context, @NonNull Handler handler,
@@ -190,6 +190,8 @@
     public DisplayModeDirector(@NonNull Context context, @NonNull Handler handler,
             @NonNull Injector injector,
             @NonNull DisplayManagerFlags displayManagerFlags) {
+        mDvrrSupported = context.getResources().getBoolean(
+                com.android.internal.R.bool.config_supportsDvrr);
         mIsDisplayResolutionRangeVotingEnabled = displayManagerFlags
                 .isDisplayResolutionRangeVotingEnabled();
         mIsUserPreferredModeVoteEnabled = displayManagerFlags.isUserPreferredModeVoteEnabled();
@@ -199,7 +201,6 @@
             .isDisplaysRefreshRatesSynchronizationEnabled();
         mIsBackUpSmoothDisplayAndForcePeakRefreshRateEnabled = displayManagerFlags
                 .isBackUpSmoothDisplayAndForcePeakRefreshRateEnabled();
-        mVsyncProximityVoteEnabled = displayManagerFlags.isVsyncProximityVoteEnabled();
         mContext = context;
         mHandler = new DisplayModeDirectorHandler(handler.getLooper());
         mInjector = injector;
@@ -208,7 +209,8 @@
         mAppRequestObserver = new AppRequestObserver();
         mConfigParameterProvider = new DeviceConfigParameterProvider(injector.getDeviceConfig());
         mDeviceConfigDisplaySettings = new DeviceConfigDisplaySettings();
-        mSettingsObserver = new SettingsObserver(context, handler);
+        mSettingsObserver = new SettingsObserver(context, handler, mDvrrSupported,
+                displayManagerFlags);
         mBrightnessObserver = new BrightnessObserver(context, handler, injector);
         mDefaultDisplayDeviceConfig = null;
         mUdfpsObserver = new UdfpsObserver();
@@ -290,7 +292,7 @@
             List<Display.Mode> availableModes = new ArrayList<>();
             availableModes.add(defaultMode);
             VoteSummary primarySummary = new VoteSummary(mIsDisplayResolutionRangeVotingEnabled,
-                    mVsyncProximityVoteEnabled, mLoggingEnabled, mSupportsFrameRateOverride);
+                    mDvrrSupported, mLoggingEnabled, mSupportsFrameRateOverride);
             int lowestConsideredPriority = Vote.MIN_PRIORITY;
             int highestConsideredPriority = Vote.MAX_PRIORITY;
 
@@ -330,7 +332,7 @@
             }
 
             VoteSummary appRequestSummary = new VoteSummary(mIsDisplayResolutionRangeVotingEnabled,
-                    mVsyncProximityVoteEnabled, mLoggingEnabled, mSupportsFrameRateOverride);
+                    mDvrrSupported, mLoggingEnabled, mSupportsFrameRateOverride);
 
             appRequestSummary.applyVotes(votes,
                     Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF,
@@ -818,13 +820,17 @@
         private final Uri mMatchContentFrameRateSetting =
                 Settings.Secure.getUriFor(Settings.Secure.MATCH_CONTENT_FRAME_RATE);
 
+        private final boolean mVsynLowPowerVoteEnabled;
+
         private final Context mContext;
         private float mDefaultPeakRefreshRate;
         private float mDefaultRefreshRate;
 
-        SettingsObserver(@NonNull Context context, @NonNull Handler handler) {
+        SettingsObserver(@NonNull Context context, @NonNull Handler handler, boolean dvrrSupported,
+                DisplayManagerFlags flags) {
             super(handler);
             mContext = context;
+            mVsynLowPowerVoteEnabled = dvrrSupported && flags.isVsyncLowPowerVoteEnabled();
             // We don't want to load from the DeviceConfig while constructing since this leads to
             // a spike in the latency of DisplayManagerService startup. This happens because
             // reading from the DeviceConfig is an intensive IO operation and having it in the
@@ -936,7 +942,14 @@
             boolean inLowPowerMode = Settings.Global.getInt(mContext.getContentResolver(),
                     Settings.Global.LOW_POWER_MODE, 0 /*default*/) != 0;
             final Vote vote;
-            if (inLowPowerMode) {
+            if (inLowPowerMode && mVsynLowPowerVoteEnabled) {
+                vote = Vote.forSupportedModes(List.of(
+                        new SupportedModesVote.SupportedMode(/* peakRefreshRate= */ 60f,
+                                /* vsyncRate= */ 240f),
+                        new SupportedModesVote.SupportedMode(/* peakRefreshRate= */ 60f,
+                                /* vsyncRate= */ 60f)
+                ));
+            } else if (inLowPowerMode) {
                 vote = Vote.forRenderFrameRates(0f, 60f);
             } else {
                 vote = null;
diff --git a/services/core/java/com/android/server/display/mode/Vote.java b/services/core/java/com/android/server/display/mode/Vote.java
index aa44566..8f39570 100644
--- a/services/core/java/com/android/server/display/mode/Vote.java
+++ b/services/core/java/com/android/server/display/mode/Vote.java
@@ -166,6 +166,10 @@
         return new BaseModeRefreshRateVote(baseModeRefreshRate);
     }
 
+    static Vote forSupportedModes(List<SupportedModesVote.SupportedMode> supportedModes) {
+        return new SupportedModesVote(supportedModes);
+    }
+
     static String priorityToString(int priority) {
         switch (priority) {
             case PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE:
diff --git a/services/core/java/com/android/server/display/mode/VoteSummary.java b/services/core/java/com/android/server/display/mode/VoteSummary.java
index 99f4142..5fc36b5 100644
--- a/services/core/java/com/android/server/display/mode/VoteSummary.java
+++ b/services/core/java/com/android/server/display/mode/VoteSummary.java
@@ -43,14 +43,14 @@
 
     final boolean mIsDisplayResolutionRangeVotingEnabled;
 
-    private final boolean mVsyncProximityVoteEnabled;
+    private final boolean mSupportedModesVoteEnabled;
     private final boolean mSupportsFrameRateOverride;
     private final boolean mLoggingEnabled;
 
-    VoteSummary(boolean isDisplayResolutionRangeVotingEnabled, boolean vsyncProximityVoteEnabled,
+    VoteSummary(boolean isDisplayResolutionRangeVotingEnabled, boolean supportedModesVoteEnabled,
             boolean loggingEnabled, boolean supportsFrameRateOverride) {
         mIsDisplayResolutionRangeVotingEnabled = isDisplayResolutionRangeVotingEnabled;
-        mVsyncProximityVoteEnabled = vsyncProximityVoteEnabled;
+        mSupportedModesVoteEnabled = supportedModesVoteEnabled;
         mLoggingEnabled = loggingEnabled;
         mSupportsFrameRateOverride = supportsFrameRateOverride;
         reset();
@@ -253,7 +253,7 @@
     }
 
     private boolean validateModeSupported(Display.Mode mode) {
-        if (supportedModes == null || !mVsyncProximityVoteEnabled) {
+        if (supportedModes == null || !mSupportedModesVoteEnabled) {
             return true;
         }
         for (SupportedModesVote.SupportedMode supportedMode : supportedModes) {
@@ -298,7 +298,7 @@
             return false;
         }
 
-        if (supportedModes != null && mVsyncProximityVoteEnabled && supportedModes.isEmpty()) {
+        if (supportedModes != null && mSupportedModesVoteEnabled && supportedModes.isEmpty()) {
             if (mLoggingEnabled) {
                 Slog.w(TAG, "Vote summary resulted in empty set (empty supportedModes)");
             }
@@ -370,7 +370,7 @@
                 + ", supportedModes=" + supportedModes
                 + ", mIsDisplayResolutionRangeVotingEnabled="
                 + mIsDisplayResolutionRangeVotingEnabled
-                + ", mVsyncProximityVoteEnabled=" + mVsyncProximityVoteEnabled
+                + ", mSupportedModesVoteEnabled=" + mSupportedModesVoteEnabled
                 + ", mSupportsFrameRateOverride=" + mSupportsFrameRateOverride + " }";
     }
 }
diff --git a/services/core/java/com/android/server/display/notifications/DisplayNotificationManager.java b/services/core/java/com/android/server/display/notifications/DisplayNotificationManager.java
index f57bf29..405c149 100644
--- a/services/core/java/com/android/server/display/notifications/DisplayNotificationManager.java
+++ b/services/core/java/com/android/server/display/notifications/DisplayNotificationManager.java
@@ -130,8 +130,8 @@
         }
 
         sendErrorNotification(createErrorNotification(
-                R.string.connected_display_cable_dont_support_displays_notification_title,
-                R.string.connected_display_cable_dont_support_displays_notification_content,
+                R.string.connected_display_unavailable_notification_title,
+                R.string.connected_display_unavailable_notification_content,
                 R.drawable.usb_cable_unknown_issue));
     }
 
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 1687157..5831b29 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -194,10 +194,14 @@
             addAndStartAction(new RequestActiveSourceAction(this, new IHdmiControlCallback.Stub() {
                 @Override
                 public void onComplete(int result) {
-                    if (result != HdmiControlManager.RESULT_SUCCESS) {
+                    if (!mService.getLocalActiveSource().isValid()
+                            && result != HdmiControlManager.RESULT_SUCCESS) {
                         mService.sendCecCommand(HdmiCecMessageBuilder.buildActiveSource(
                                 getDeviceInfo().getLogicalAddress(),
                                 getDeviceInfo().getPhysicalAddress()));
+                        updateActiveSource(getDeviceInfo().getLogicalAddress(),
+                                getDeviceInfo().getPhysicalAddress(),
+                                "RequestActiveSourceAction#finishWithCallback()");
                     }
                 }
             }));
@@ -257,6 +261,7 @@
         if (isAlreadyActiveSource(targetDevice, targetAddress, callback)) {
             return;
         }
+        removeAction(RequestActiveSourceAction.class);
         if (targetAddress == Constants.ADDR_INTERNAL) {
             handleSelectInternalSource();
             // Switching to internal source is always successful even when CEC control is disabled.
diff --git a/services/core/java/com/android/server/hdmi/RequestActiveSourceAction.java b/services/core/java/com/android/server/hdmi/RequestActiveSourceAction.java
index 017c86d..d250416 100644
--- a/services/core/java/com/android/server/hdmi/RequestActiveSourceAction.java
+++ b/services/core/java/com/android/server/hdmi/RequestActiveSourceAction.java
@@ -29,6 +29,12 @@
     // State to wait for the <Active Source> message.
     private static final int STATE_WAIT_FOR_ACTIVE_SOURCE = 1;
 
+    // Number of retries <Request Active Source> is sent if no device answers this message.
+    private static final int MAX_SEND_RETRY_COUNT = 1;
+
+    private int mSendRetryCount = 0;
+
+
     RequestActiveSourceAction(HdmiCecLocalDevice source, IHdmiControlCallback callback) {
         super(source, callback);
     }
@@ -60,7 +66,12 @@
             return;
         }
         if (mState == STATE_WAIT_FOR_ACTIVE_SOURCE) {
-            finishWithCallback(HdmiControlManager.RESULT_TIMEOUT);
+            if (mSendRetryCount++ < MAX_SEND_RETRY_COUNT) {
+                sendCommand(HdmiCecMessageBuilder.buildRequestActiveSource(getSourceAddress()));
+                addTimer(mState, HdmiConfig.TIMEOUT_MS);
+            } else {
+                finishWithCallback(HdmiControlManager.RESULT_TIMEOUT);
+            }
         }
     }
 }
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 3fc9594..24e23003 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -3504,6 +3504,20 @@
         wm.addView(view, lp);
     }
 
+    /**
+     * Sets Accessibility bounce keys threshold in milliseconds.
+     */
+    public void setAccessibilityBounceKeysThreshold(int thresholdTimeMs) {
+        mNative.setAccessibilityBounceKeysThreshold(thresholdTimeMs);
+    }
+
+    /**
+     * Sets whether Accessibility sticky keys is enabled.
+     */
+    public void setAccessibilityStickyKeysEnabled(boolean enabled) {
+        mNative.setAccessibilityStickyKeysEnabled(enabled);
+    }
+
     interface KeyboardBacklightControllerInterface {
         default void incrementKeyboardBacklight(int deviceId) {}
         default void decrementKeyboardBacklight(int deviceId) {}
diff --git a/services/core/java/com/android/server/input/InputSettingsObserver.java b/services/core/java/com/android/server/input/InputSettingsObserver.java
index 8e0289e..c9668a2 100644
--- a/services/core/java/com/android/server/input/InputSettingsObserver.java
+++ b/services/core/java/com/android/server/input/InputSettingsObserver.java
@@ -85,7 +85,11 @@
                 Map.entry(Settings.Secure.getUriFor(Settings.Secure.KEY_REPEAT_DELAY_MS),
                         (reason) -> updateKeyRepeatInfo()),
                 Map.entry(Settings.System.getUriFor(Settings.System.SHOW_ROTARY_INPUT),
-                        (reason) -> updateShowRotaryInput()));
+                        (reason) -> updateShowRotaryInput()),
+                Map.entry(Settings.System.getUriFor(Settings.Secure.ACCESSIBILITY_BOUNCE_KEYS),
+                        (reason) -> updateAccessibilityBounceKeys()),
+                Map.entry(Settings.System.getUriFor(Settings.Secure.ACCESSIBILITY_STICKY_KEYS),
+                        (reason) -> updateAccessibilityStickyKeys()));
     }
 
     /**
@@ -216,4 +220,14 @@
         }
         mNative.setMaximumObscuringOpacityForTouch(opacity);
     }
+
+    private void updateAccessibilityBounceKeys() {
+        mService.setAccessibilityBounceKeysThreshold(
+                InputSettings.getAccessibilityBounceKeysThreshold(mContext));
+    }
+
+    private void updateAccessibilityStickyKeys() {
+        mService.setAccessibilityStickyKeysEnabled(
+                InputSettings.isAccessibilityStickyKeysEnabled(mContext));
+    }
 }
diff --git a/services/core/java/com/android/server/input/NativeInputManagerService.java b/services/core/java/com/android/server/input/NativeInputManagerService.java
index 620cde5..829b660 100644
--- a/services/core/java/com/android/server/input/NativeInputManagerService.java
+++ b/services/core/java/com/android/server/input/NativeInputManagerService.java
@@ -246,6 +246,16 @@
      */
     void sysfsNodeChanged(String sysfsNodePath);
 
+    /**
+     * Notify if Accessibility bounce keys threshold is changed from InputSettings.
+     */
+    void setAccessibilityBounceKeysThreshold(int thresholdTimeMs);
+
+    /**
+     * Notify if Accessibility sticky keys is enabled/disabled from InputSettings.
+     */
+    void setAccessibilityStickyKeysEnabled(boolean enabled);
+
     /** The native implementation of InputManagerService methods. */
     class NativeImpl implements NativeInputManagerService {
         /** Pointer to native input manager service object, used by native code. */
@@ -500,5 +510,11 @@
 
         @Override
         public native void sysfsNodeChanged(String sysfsNodePath);
+
+        @Override
+        public native void setAccessibilityBounceKeysThreshold(int thresholdTimeMs);
+
+        @Override
+        public native void setAccessibilityStickyKeysEnabled(boolean enabled);
     }
 }
diff --git a/services/core/java/com/android/server/inputmethod/HandwritingModeController.java b/services/core/java/com/android/server/inputmethod/HandwritingModeController.java
index dcb86a7..66807ae 100644
--- a/services/core/java/com/android/server/inputmethod/HandwritingModeController.java
+++ b/services/core/java/com/android/server/inputmethod/HandwritingModeController.java
@@ -23,7 +23,9 @@
 import android.annotation.RequiresPermission;
 import android.annotation.UiThread;
 import android.content.ComponentName;
+import android.content.Context;
 import android.content.pm.PackageManagerInternal;
+import android.hardware.input.InputManager;
 import android.hardware.input.InputManagerGlobal;
 import android.os.Handler;
 import android.os.IBinder;
@@ -64,6 +66,7 @@
     private static final int LONG_EVENT_BUFFER_SIZE = EVENT_BUFFER_SIZE * 20;
     private static final long HANDWRITING_DELEGATION_IDLE_TIMEOUT_MS = 3000;
 
+    private final Context mContext;
     // This must be the looper for the UiThread.
     private final Looper mLooper;
     private final InputManagerInternal mInputManagerInternal;
@@ -87,7 +90,9 @@
     private int mCurrentRequestId;
 
     @AnyThread
-    HandwritingModeController(Looper uiThreadLooper, Runnable inkWindowInitRunnable) {
+    HandwritingModeController(Context context, Looper uiThreadLooper,
+            Runnable inkWindowInitRunnable) {
+        mContext = context;
         mLooper = uiThreadLooper;
         mCurrentDisplayId = Display.INVALID_DISPLAY;
         mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
@@ -285,7 +290,14 @@
         mHandwritingSurface.startIntercepting(imePid, imeUid);
 
         // Unset the pointer icon for the stylus in case the app had set it.
-        InputManagerGlobal.getInstance().setPointerIconType(PointerIcon.TYPE_NOT_SPECIFIED);
+        if (com.android.input.flags.Flags.enablePointerChoreographer()) {
+            Objects.requireNonNull(mContext.getSystemService(InputManager.class)).setPointerIcon(
+                    PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_NOT_SPECIFIED),
+                    downEvent.getDisplayId(), downEvent.getDeviceId(), downEvent.getPointerId(0),
+                    mHandwritingSurface.getInputChannel().getToken());
+        } else {
+            InputManagerGlobal.getInstance().setPointerIconType(PointerIcon.TYPE_NOT_SPECIFIED);
+        }
 
         return new HandwritingSession(mCurrentRequestId, mHandwritingSurface.getInputChannel(),
                 mHandwritingBuffer);
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java
index ffd714b..4089a81 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java
@@ -120,6 +120,25 @@
             @UserIdInt int userId);
 
     /**
+     * Makes the input method associated with {@code imeId} the default input method for all users
+     * on displays that are owned by the virtual device with the given {@code deviceId}. If the
+     * input method associated with {@code imeId} is not available, there will be no IME on the
+     * relevant displays.
+     *
+     * <p>The caller of this method is responsible for resetting it to {@code null} after the
+     * virtual device is closed.</p>
+     *
+     * @param deviceId the device ID on which to use the given input method as default.
+     * @param imeId  the input method ID to be used as default on the given device. If {@code null},
+     *               then any existing input method association with that device will be removed.
+     * @throws IllegalArgumentException if a non-{@code null} input method ID is passed for a
+     *                                  device ID that already has a custom input method set or if
+     *                                  the device ID is not a valid virtual device.
+     */
+    public abstract void setVirtualDeviceInputMethodForAllUsers(
+            int deviceId, @Nullable String imeId);
+
+    /**
      * Registers a new {@link InputMethodListListener}.
      *
      * @param listener the listener to add
@@ -196,10 +215,20 @@
     /**
      * Switch the keyboard layout in response to a keyboard shortcut.
      *
-     * @param direction {@code 1} to switch to the next subtype, {@code -1} to switch to the
-     *                  previous subtype
+     * @param direction         {@code 1} to switch to the next subtype, {@code -1} to switch to the
+     *                          previous subtype
+     * @param displayId         the display to which the keyboard layout switch shortcut is
+     *                          dispatched. Note that there is no guarantee that an IME is
+     *                          associated with this display. This is more or less than a hint for
+     *                          cases when no IME is running for the given targetWindowToken. There
+     *                          is a longstanding discussion whether we should allow users to
+     *                          rotate keyboard layout even when there is no edit field, and this
+     *                          displayID would be helpful for such a situation.
+     * @param targetWindowToken the window token to which other keys are being sent while handling
+     *                          this shortcut.
      */
-    public abstract void switchKeyboardLayout(int direction);
+    public abstract void onSwitchKeyboardLayoutShortcut(int direction, int displayId,
+            IBinder targetWindowToken);
 
     /**
      * Returns true if any InputConnection is currently active.
@@ -250,6 +279,11 @@
                 }
 
                 @Override
+                public void setVirtualDeviceInputMethodForAllUsers(
+                        int deviceId, @Nullable String imeId) {
+                }
+
+                @Override
                 public void registerInputMethodListListener(InputMethodListListener listener) {
                 }
 
@@ -290,7 +324,8 @@
                 }
 
                 @Override
-                public void switchKeyboardLayout(int direction) {
+                public void onSwitchKeyboardLayoutShortcut(int direction, int displayId,
+                        IBinder targetWindowToken) {
                 }
 
                 @Override
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index b1a362d..16e043c 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -169,6 +169,7 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.ConcurrentUtils;
 import com.android.internal.util.DumpUtils;
+import com.android.internal.util.Preconditions;
 import com.android.internal.view.IInputMethodManager;
 import com.android.server.AccessibilityManagerInternal;
 import com.android.server.EventLogTags;
@@ -312,6 +313,9 @@
     // All known input methods.
     final ArrayList<InputMethodInfo> mMethodList = new ArrayList<>();
     private final ArrayMap<String, InputMethodInfo> mMethodMap = new ArrayMap<>();
+    // Mapping from deviceId to the device-specific imeId for that device.
+    private final SparseArray<String> mVirtualDeviceMethodMap = new SparseArray<>();
+
     final InputMethodSubtypeSwitchingController mSwitchingController;
     final HardwareKeyboardShortcutController mHardwareKeyboardShortcutController =
             new HardwareKeyboardShortcutController();
@@ -1689,7 +1693,7 @@
         mLastSwitchUserId = userId;
 
         // mSettings should be created before buildInputMethodListLocked
-        mSettings = new InputMethodSettings(mContext, mMethodMap, userId, !mSystemReady);
+        mSettings = new InputMethodSettings(mMethodMap, userId, !mSystemReady);
 
         AdditionalSubtypeUtils.load(mAdditionalSubtypeMap, userId);
         mSwitchingController =
@@ -1709,7 +1713,7 @@
                 com.android.internal.R.bool.config_preventImeStartupUnlessTextEditor);
         mNonPreemptibleInputMethods = mRes.getStringArray(
                 com.android.internal.R.array.config_nonPreemptibleInputMethods);
-        mHwController = new HandwritingModeController(thread.getLooper(),
+        mHwController = new HandwritingModeController(mContext, thread.getLooper(),
                 new InkWindowInitializer());
         registerDeviceListenerAndCheckStylusSupport();
     }
@@ -2019,8 +2023,7 @@
             //TODO(b/197848765): This can be optimized by caching multi-user methodMaps/methodList.
             //TODO(b/210039666): use cache.
             final ArrayMap<String, InputMethodInfo> methodMap = queryMethodMapForUser(userId);
-            final InputMethodSettings settings = new InputMethodSettings(mContext, methodMap,
-                    userId, true);
+            final InputMethodSettings settings = new InputMethodSettings(methodMap, userId, true);
             final InputMethodInfo imi = methodMap.get(settings.getSelectedInputMethod());
             return imi != null && imi.supportsStylusHandwriting();
         }
@@ -2056,7 +2059,7 @@
             AdditionalSubtypeUtils.load(additionalSubtypeMap, userId);
             queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, methodMap,
                     methodList, directBootAwareness);
-            settings = new InputMethodSettings(mContext, methodMap, userId, true /* copyOnWrite */);
+            settings = new InputMethodSettings(methodMap, userId, true /* copyOnWrite */);
         }
         // filter caller's access to input methods
         methodList.removeIf(imi ->
@@ -2074,7 +2077,7 @@
             settings = mSettings;
         } else {
             final ArrayMap<String, InputMethodInfo> methodMap = queryMethodMapForUser(userId);
-            settings = new InputMethodSettings(mContext, methodMap, userId, true /* copyOnWrite */);
+            settings = new InputMethodSettings(methodMap, userId, true /* copyOnWrite */);
             methodList = settings.getEnabledInputMethodListLocked();
         }
         // filter caller's access to input methods
@@ -2154,8 +2157,7 @@
         if (imi == null) {
             return Collections.emptyList();
         }
-        final InputMethodSettings settings = new InputMethodSettings(mContext, methodMap, userId,
-                true);
+        final InputMethodSettings settings = new InputMethodSettings(methodMap, userId, true);
         if (!canCallerAccessInputMethod(imi.getPackageName(), callingUid, userId, settings)) {
             return Collections.emptyList();
         }
@@ -4132,8 +4134,7 @@
             }
 
             final ArrayMap<String, InputMethodInfo> methodMap = queryMethodMapForUser(userId);
-            final InputMethodSettings settings = new InputMethodSettings(mContext, methodMap,
-                    userId, false);
+            final InputMethodSettings settings = new InputMethodSettings(methodMap, userId, false);
             return settings.getLastInputMethodSubtypeLocked();
         }
     }
@@ -4185,8 +4186,7 @@
             AdditionalSubtypeUtils.load(additionalSubtypeMap, userId);
             queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, methodMap,
                     methodList, DirectBootAwareness.AUTO);
-            final InputMethodSettings settings = new InputMethodSettings(mContext, methodMap,
-                    userId, false);
+            final InputMethodSettings settings = new InputMethodSettings(methodMap, userId, false);
             settings.setAdditionalInputMethodSubtypes(imiId, toBeAdded, additionalSubtypeMap,
                     mPackageManagerInternal, callingUid);
         }
@@ -4215,7 +4215,7 @@
                 final boolean currentUser = (mSettings.getCurrentUserId() == userId);
                 final InputMethodSettings settings = currentUser
                         ? mSettings
-                        : new InputMethodSettings(mContext, queryMethodMapForUser(userId), userId,
+                        : new InputMethodSettings(queryMethodMapForUser(userId), userId,
                                 !mUserManagerInternal.isUserUnlocked(userId));
                 if (!settings.setEnabledInputMethodSubtypes(imeId, subtypeHashCodes)) {
                     return;
@@ -5275,7 +5275,7 @@
                     return true;
                 }
             }
-            mSettings.appendAndPutEnabledInputMethodLocked(id, false);
+            mSettings.appendAndPutEnabledInputMethodLocked(id);
             // Previous state was disabled.
             return false;
         } else {
@@ -5365,8 +5365,7 @@
             }
 
             final ArrayMap<String, InputMethodInfo> methodMap = queryMethodMapForUser(userId);
-            final InputMethodSettings settings = new InputMethodSettings(mContext, methodMap,
-                    userId, false);
+            final InputMethodSettings settings = new InputMethodSettings(methodMap, userId, false);
             return settings.getCurrentInputMethodSubtypeForNonCurrentUsers();
         }
     }
@@ -5439,8 +5438,7 @@
         AdditionalSubtypeUtils.load(additionalSubtypeMap, userId);
         queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, methodMap,
                 methodList, DirectBootAwareness.AUTO);
-        InputMethodSettings settings = new InputMethodSettings(mContext, methodMap, userId,
-                true /* copyOnWrite */);
+        InputMethodSettings settings = new InputMethodSettings(methodMap, userId, true);
         return methodMap.get(settings.getSelectedInputMethod());
     }
 
@@ -5467,8 +5465,7 @@
             return true;
         }
         final ArrayMap<String, InputMethodInfo> methodMap = queryMethodMapForUser(userId);
-        final InputMethodSettings settings = new InputMethodSettings(mContext, methodMap, userId,
-                false);
+        final InputMethodSettings settings = new InputMethodSettings(methodMap, userId, false);
         if (!methodMap.containsKey(imeId)
                 || !settings.getEnabledInputMethodListLocked().contains(methodMap.get(imeId))) {
             return false; // IME is not found or not enabled.
@@ -5607,7 +5604,7 @@
                     return true;
                 }
                 final ArrayMap<String, InputMethodInfo> methodMap = queryMethodMapForUser(userId);
-                final InputMethodSettings settings = new InputMethodSettings(mContext, methodMap,
+                final InputMethodSettings settings = new InputMethodSettings(methodMap,
                         userId, false);
                 if (!methodMap.containsKey(imeId)) {
                     return false; // IME is not found.
@@ -5615,7 +5612,7 @@
                 if (enabled) {
                     if (!settings.getEnabledInputMethodListLocked().contains(
                             methodMap.get(imeId))) {
-                        settings.appendAndPutEnabledInputMethodLocked(imeId, false);
+                        settings.appendAndPutEnabledInputMethodLocked(imeId);
                     }
                 } else {
                     settings.buildAndPutEnabledInputMethodsStrRemovingIdLocked(
@@ -5627,6 +5624,23 @@
         }
 
         @Override
+        public void setVirtualDeviceInputMethodForAllUsers(int deviceId, @Nullable String imeId) {
+            // TODO(b/287269288): validate that id belongs to a valid virtual device instead.
+            Preconditions.checkArgument(deviceId != Context.DEVICE_ID_DEFAULT,
+                    "DeviceId " + deviceId + " does not belong to a virtual device.");
+            synchronized (ImfLock.class) {
+                if (imeId == null) {
+                    mVirtualDeviceMethodMap.remove(deviceId);
+                } else if (mVirtualDeviceMethodMap.contains(deviceId)) {
+                    throw new IllegalArgumentException("Virtual device " + deviceId
+                            + " already has a custom input method component");
+                } else {
+                    mVirtualDeviceMethodMap.put(deviceId, imeId);
+                }
+            }
+        }
+
+        @Override
         public void registerInputMethodListListener(InputMethodListListener listener) {
             mInputMethodListListeners.addIfAbsent(listener);
         }
@@ -5749,7 +5763,8 @@
         }
 
         @Override
-        public void switchKeyboardLayout(int direction) {
+        public void onSwitchKeyboardLayoutShortcut(int direction, int displayId,
+                IBinder targetWindowToken) {
             synchronized (ImfLock.class) {
                 switchKeyboardLayoutLocked(direction);
             }
@@ -6331,8 +6346,7 @@
             }
         } else {
             final ArrayMap<String, InputMethodInfo> methodMap = queryMethodMapForUser(userId);
-            final InputMethodSettings settings = new InputMethodSettings(mContext, methodMap,
-                    userId, false);
+            final InputMethodSettings settings = new InputMethodSettings(methodMap, userId, false);
             if (enabled) {
                 if (!methodMap.containsKey(imeId)) {
                     failedToEnableUnknownIme = true;
@@ -6344,7 +6358,7 @@
                         }
                     }
                     if (!previouslyEnabled) {
-                        settings.appendAndPutEnabledInputMethodLocked(imeId, false);
+                        settings.appendAndPutEnabledInputMethodLocked(imeId);
                     }
                 }
             } else {
@@ -6476,7 +6490,7 @@
                         AdditionalSubtypeUtils.load(additionalSubtypeMap, userId);
                         queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap,
                                 methodMap, methodList, DirectBootAwareness.AUTO);
-                        final InputMethodSettings settings = new InputMethodSettings(mContext,
+                        final InputMethodSettings settings = new InputMethodSettings(
                                 methodMap, userId, false);
 
                         nextEnabledImes = InputMethodInfoUtils.getDefaultEnabledImes(mContext,
@@ -6485,10 +6499,12 @@
                                 nextEnabledImes).getId();
 
                         // Reset enabled IMEs.
-                        settings.putEnabledInputMethodsStr("");
-                        nextEnabledImes.forEach(
-                                imi -> settings.appendAndPutEnabledInputMethodLocked(
-                                        imi.getId(), false));
+                        final String[] nextEnabledImeIds = new String[nextEnabledImes.size()];
+                        for (int i = 0; i < nextEnabledImeIds.length; ++i) {
+                            nextEnabledImeIds[i] = nextEnabledImes.get(i).getId();
+                        }
+                        settings.putEnabledInputMethodsStr(InputMethodUtils.concatEnabledImeIds(
+                                settings.getEnabledInputMethodsStr(), nextEnabledImeIds));
 
                         // Reset selected IME.
                         settings.putSelectedInputMethod(nextIme);
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodUtils.java b/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
index b4338f6..773293f 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
@@ -33,6 +33,7 @@
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.IntArray;
 import android.util.Pair;
 import android.util.Printer;
@@ -50,6 +51,8 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.StringJoiner;
+import java.util.function.Consumer;
 import java.util.function.Predicate;
 
 /**
@@ -208,8 +211,6 @@
      */
     @UserHandleAware
     public static class InputMethodSettings {
-        @NonNull
-        private Context mUserAwareContext;
         private final ArrayMap<String, InputMethodInfo> mMethodMap;
 
         private boolean mCopyOnWrite = false;
@@ -253,17 +254,9 @@
             return imsList;
         }
 
-        private void initContentWithUserContext(@NonNull Context context, @UserIdInt int userId) {
-            mUserAwareContext = context.getUserId() == userId
-                    ? context
-                    : context.createContextAsUser(UserHandle.of(userId), 0 /* flags */);
-        }
-
-        InputMethodSettings(@NonNull Context context,
-                ArrayMap<String, InputMethodInfo> methodMap, @UserIdInt int userId,
+        InputMethodSettings(ArrayMap<String, InputMethodInfo> methodMap, @UserIdInt int userId,
                 boolean copyOnWrite) {
             mMethodMap = methodMap;
-            initContentWithUserContext(context, userId);
             switchCurrentUser(userId, copyOnWrite);
         }
 
@@ -282,9 +275,6 @@
             if (mCurrentUserId != userId || mCopyOnWrite != copyOnWrite) {
                 mEnabledInputMethodsStrCache = "";
             }
-            if (mUserAwareContext.getUserId() != userId) {
-                initContentWithUserContext(mUserAwareContext, userId);
-            }
             mCurrentUserId = userId;
             mCopyOnWrite = copyOnWrite;
         }
@@ -375,10 +365,7 @@
             return result;
         }
 
-        void appendAndPutEnabledInputMethodLocked(String id, boolean reloadInputMethodStr) {
-            if (reloadInputMethodStr) {
-                getEnabledInputMethodsStr();
-            }
+        void appendAndPutEnabledInputMethodLocked(String id) {
             if (TextUtils.isEmpty(mEnabledInputMethodsStrCache)) {
                 // Add in the newly enabled input method.
                 putEnabledInputMethodsStr(id);
@@ -968,24 +955,64 @@
         final String enabledInputMethodsStr = TextUtils.nullIfEmpty(
                 SecureSettingsWrapper.getString(Settings.Secure.ENABLED_INPUT_METHODS, null,
                         userId));
-        if (enabledInputMethodsStr == null) {
-            return List.of();
+        final ArrayList<String> result = new ArrayList<>();
+        splitEnabledImeStr(enabledInputMethodsStr, result::add);
+        return result;
+    }
+
+    /**
+     * Split enabled IME string ({@link Settings.Secure#ENABLED_INPUT_METHODS}) into IME IDs.
+     *
+     * @param text a text formatted with {@link Settings.Secure#ENABLED_INPUT_METHODS}.
+     * @param consumer {@link Consumer} called back when a new IME ID is found.
+     */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    static void splitEnabledImeStr(@Nullable String text, @NonNull Consumer<String> consumer) {
+        if (TextUtils.isEmpty(text)) {
+            return;
         }
         final TextUtils.SimpleStringSplitter inputMethodSplitter =
                 new TextUtils.SimpleStringSplitter(INPUT_METHOD_SEPARATOR);
         final TextUtils.SimpleStringSplitter subtypeSplitter =
                 new TextUtils.SimpleStringSplitter(INPUT_METHOD_SUBTYPE_SEPARATOR);
-        inputMethodSplitter.setString(enabledInputMethodsStr);
-        final ArrayList<String> result = new ArrayList<>();
+        inputMethodSplitter.setString(text);
         while (inputMethodSplitter.hasNext()) {
             String nextImsStr = inputMethodSplitter.next();
             subtypeSplitter.setString(nextImsStr);
             if (subtypeSplitter.hasNext()) {
                 // The first element is ime id.
-                result.add(subtypeSplitter.next());
+                consumer.accept(subtypeSplitter.next());
             }
         }
-        return result;
+    }
+
+    /**
+     * Concat given IME IDs with an existing enabled IME
+     * ({@link Settings.Secure#ENABLED_INPUT_METHODS}).
+     *
+     * @param existingEnabledImeId an existing {@link Settings.Secure#ENABLED_INPUT_METHODS} to
+     *                             which {@code imeIDs} will be added.
+     * @param imeIds an array of IME IDs to be added. For IME IDs that are already seen in
+     *               {@code existingEnabledImeId} will be skipped.
+     * @return a new enabled IME ID string that can be stored in
+     *         {@link Settings.Secure#ENABLED_INPUT_METHODS}.
+     */
+    @NonNull
+    static String concatEnabledImeIds(@NonNull String existingEnabledImeId,
+            @NonNull String... imeIds) {
+        final ArraySet<String> alreadyEnabledIds = new ArraySet<>();
+        final StringJoiner joiner = new StringJoiner(Character.toString(INPUT_METHOD_SEPARATOR));
+        if (!TextUtils.isEmpty(existingEnabledImeId)) {
+            splitEnabledImeStr(existingEnabledImeId, alreadyEnabledIds::add);
+            joiner.add(existingEnabledImeId);
+        }
+        for (String id : imeIds) {
+            if (!alreadyEnabledIds.contains(id)) {
+                joiner.add(id);
+                alreadyEnabledIds.add(id);
+            }
+        }
+        return joiner.toString();
     }
 
     /**
diff --git a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
index ec858ee2..f2dcba4 100644
--- a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
+++ b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
@@ -59,6 +59,7 @@
 
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.pm.pkg.parsing.ParsingPackageUtils;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FrameworkStatsLog;
 import com.android.server.LocalServices;
@@ -67,7 +68,6 @@
 import com.android.server.integrity.model.RuleMetadata;
 import com.android.server.pm.PackageManagerServiceUtils;
 import com.android.server.pm.parsing.PackageParser2;
-import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
 
 import java.io.ByteArrayInputStream;
 import java.io.File;
diff --git a/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java b/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
index d359280..9c27c22 100644
--- a/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
+++ b/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
@@ -18,6 +18,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.hardware.contexthub.HostEndpointInfo;
+import android.hardware.contexthub.MessageDeliveryStatus;
 import android.hardware.contexthub.NanSessionRequest;
 import android.hardware.contexthub.V1_0.ContextHub;
 import android.hardware.contexthub.V1_0.ContextHubMsg;
@@ -424,6 +425,7 @@
             // 9a17008d-6bf1-445a-9011-6d21bd985b6c
             private static final byte[] UUID = {-102, 23, 0, -115, 107, -15, 68, 90,
                                                 -112, 17, 109, 33, -67, -104, 91, 108};
+            private static final String NAME = "ContextHubService";
 
             ContextHubAidlCallback(int contextHubId, ICallback callback) {
                 mContextHubId = contextHubId;
@@ -466,10 +468,19 @@
                 // TODO(271471342): Implement
             }
 
-            public byte[] getUuid() throws RemoteException {
+            public void handleMessageDeliveryStatus(char hostEndPointId,
+                    MessageDeliveryStatus messageDeliveryStatus) {
+                // TODO(b/312417087): Implement reliable message support
+            }
+
+            public byte[] getUuid() {
                 return UUID;
             }
 
+            public String getName() {
+                return NAME;
+            }
+
             @Override
             public String getInterfaceHash() {
                 return android.hardware.contexthub.IContextHubCallback.HASH;
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 49095ce..0c2eee5 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -209,7 +209,7 @@
  *   <li>Protect each user's data using their SP.  For example, use the SP to encrypt/decrypt the
  *   user's credential-encrypted (CE) key for file-based encryption (FBE).</li>
  *
- *   <li>Generate, protect, and use profile passwords for managed profiles.</li>
+ *   <li>Generate, protect, and use unified profile passwords.</li>
  *
  *   <li>Support unlocking the SP by alternative means: resume-on-reboot (reboot escrow) for easier
  *   OTA updates, and escrow tokens when set up by the Device Policy Controller (DPC).</li>
@@ -287,7 +287,7 @@
 
     private final java.security.KeyStore mJavaKeyStore;
     private final RecoverableKeyStoreManager mRecoverableKeyStoreManager;
-    private ManagedProfilePasswordCache mManagedProfilePasswordCache;
+    private final UnifiedProfilePasswordCache mUnifiedProfilePasswordCache;
 
     private final RebootEscrowManager mRebootEscrowManager;
 
@@ -404,7 +404,8 @@
         for (int i = 0; i < newPasswordChars.length; i++) {
             newPassword[i] = (byte) newPasswordChars[i];
         }
-        LockscreenCredential credential = LockscreenCredential.createManagedPassword(newPassword);
+        LockscreenCredential credential =
+                LockscreenCredential.createUnifiedProfilePassword(newPassword);
         Arrays.fill(newPasswordChars, '\u0000');
         Arrays.fill(newPassword, (byte) 0);
         Arrays.fill(randomLockSeed, (byte) 0);
@@ -424,7 +425,7 @@
         if (!isCredentialSharableWithParent(profileUserId)) {
             return;
         }
-        // Do not tie profile when work challenge is enabled
+        // Do not tie profile when separate challenge is enabled
         if (getSeparateProfileChallengeEnabledInternal(profileUserId)) {
             return;
         }
@@ -462,7 +463,7 @@
             setLockCredentialInternal(unifiedProfilePassword, profileUserPassword, profileUserId,
                     /* isLockTiedToParent= */ true);
             tieProfileLockToParent(profileUserId, parent.id, unifiedProfilePassword);
-            mManagedProfilePasswordCache.storePassword(profileUserId, unifiedProfilePassword,
+            mUnifiedProfilePasswordCache.storePassword(profileUserId, unifiedProfilePassword,
                     parentSid);
         }
     }
@@ -620,9 +621,9 @@
             }
         }
 
-        public @NonNull ManagedProfilePasswordCache getManagedProfilePasswordCache(
+        public @NonNull UnifiedProfilePasswordCache getUnifiedProfilePasswordCache(
                 java.security.KeyStore ks) {
-            return new ManagedProfilePasswordCache(ks);
+            return new UnifiedProfilePasswordCache(ks);
         }
 
         public boolean isHeadlessSystemUserMode() {
@@ -665,7 +666,7 @@
         mGatekeeperPasswords = new LongSparseArray<>();
 
         mSpManager = injector.getSyntheticPasswordManager(mStorage);
-        mManagedProfilePasswordCache = injector.getManagedProfilePasswordCache(mJavaKeyStore);
+        mUnifiedProfilePasswordCache = injector.getUnifiedProfilePasswordCache(mJavaKeyStore);
         mBiometricDeferredQueue = new BiometricDeferredQueue(mSpManager, mHandler);
 
         mRebootEscrowManager = injector.getRebootEscrowManager(new RebootEscrowCallbacks(),
@@ -689,8 +690,8 @@
     }
 
     /**
-     * If the account is credential-encrypted, show notification requesting the user to unlock the
-     * device.
+     * If the user is a managed profile whose credential-encrypted storage is locked, show a
+     * notification requesting the user to unlock the device.
      */
     private void maybeShowEncryptionNotificationForUser(@UserIdInt int userId, String reason) {
         final UserInfo user = mUserManager.getUserInfo(userId);
@@ -846,7 +847,7 @@
         mHandler.post(new Runnable() {
             @Override
             public void run() {
-                // Hide notification first, as tie managed profile lock takes time
+                // Hide notification first, as tie profile lock takes time
                 hideEncryptionNotification(new UserHandle(userId));
 
                 if (isCredentialSharableWithParent(userId)) {
@@ -1432,7 +1433,7 @@
     }
 
     private void unlockKeystore(int userId, SyntheticPassword sp) {
-        Authorization.onLockScreenEvent(false, userId, sp.deriveKeyStorePassword(), null);
+        Authorization.onDeviceUnlocked(userId, sp.deriveKeyStorePassword());
     }
 
     @VisibleForTesting /** Note: this method is overridden in unit tests */
@@ -1458,13 +1459,13 @@
 
         cipher.init(Cipher.DECRYPT_MODE, decryptionKey, new GCMParameterSpec(128, iv));
         decryptionResult = cipher.doFinal(encryptedPassword);
-        LockscreenCredential credential = LockscreenCredential.createManagedPassword(
+        LockscreenCredential credential = LockscreenCredential.createUnifiedProfilePassword(
                 decryptionResult);
         Arrays.fill(decryptionResult, (byte) 0);
         try {
             long parentSid = getGateKeeperService().getSecureUserId(
                     mUserManager.getProfileParent(userId).id);
-            mManagedProfilePasswordCache.storePassword(userId, credential, parentSid);
+            mUnifiedProfilePasswordCache.storePassword(userId, credential, parentSid);
         } catch (RemoteException e) {
             Slogf.w(TAG, "Failed to talk to GateKeeper service", e);
         }
@@ -1550,7 +1551,7 @@
                         // so it goes into the cache
                         getDecryptedPasswordForTiedProfile(profile.id);
                     } catch (GeneralSecurityException | IOException e) {
-                        Slog.d(TAG, "Cache work profile password failed", e);
+                        Slog.d(TAG, "Cache unified profile password failed", e);
                     }
                 }
             }
@@ -1604,19 +1605,19 @@
     }
 
     /**
-     * Synchronize all profile's work challenge of the given user if it's unified: tie or clear them
+     * Synchronize all profile's challenge of the given user if it's unified: tie or clear them
      * depending on the parent user's secure state.
      *
-     * When clearing tied work challenges, a pre-computed password table for profiles are required,
-     * since changing password for profiles requires existing password, and existing passwords can
-     * only be computed before the parent user's password is cleared.
+     * When clearing tied challenges, a pre-computed password table for profiles are required, since
+     * changing password for profiles requires existing password, and existing passwords can only be
+     * computed before the parent user's password is cleared.
      *
      * Strictly this is a recursive function, since setLockCredentialInternal ends up calling this
      * method again on profiles. However the recursion is guaranteed to terminate as this method
      * terminates when the user is a profile that shares lock credentials with parent.
      * (e.g. managed and clone profile).
      */
-    private void synchronizeUnifiedWorkChallengeForProfiles(int userId,
+    private void synchronizeUnifiedChallengeForProfiles(int userId,
             Map<Integer, LockscreenCredential> profilePasswordMap) {
         if (isCredentialSharableWithParent(userId)) {
             return;
@@ -1635,7 +1636,7 @@
                     tieProfileLockIfNecessary(profileUserId,
                             LockscreenCredential.createNone());
                 } else {
-                    // We use cached work profile password computed before clearing the parent's
+                    // We use cached profile password computed before clearing the parent's
                     // credential, otherwise they get lost
                     if (profilePasswordMap != null
                             && profilePasswordMap.containsKey(profileUserId)) {
@@ -1777,7 +1778,7 @@
                 notifyPasswordChanged(credential, userId);
             }
             if (isCredentialSharableWithParent(userId)) {
-                // Make sure the profile doesn't get locked straight after setting work challenge.
+                // Make sure the profile doesn't get locked straight after setting challenge.
                 setDeviceUnlockedForUser(userId);
             }
             notifySeparateProfileChallengeChanged(userId);
@@ -2368,7 +2369,7 @@
         }
 
         try {
-            // Unlock work profile, and work profile with unified lock must use password only
+            // Unlock profile with unified lock
             return doVerifyCredential(getDecryptedPasswordForTiedProfile(userId),
                     userId, null /* progressCallback */, flags);
         } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
@@ -2492,7 +2493,7 @@
         mStrongAuth.removeUser(userId);
 
         AndroidKeyStoreMaintenance.onUserRemoved(userId);
-        mManagedProfilePasswordCache.removePassword(userId);
+        mUnifiedProfilePasswordCache.removePassword(userId);
 
         gateKeeperClearSecureUserId(userId);
         removeKeystoreProfileKey(userId);
@@ -2982,7 +2983,7 @@
                 credential, sp, userId);
         final Map<Integer, LockscreenCredential> profilePasswords;
         if (!credential.isNone()) {
-            // not needed by synchronizeUnifiedWorkChallengeForProfiles()
+            // not needed by synchronizeUnifiedChallengeForProfiles()
             profilePasswords = null;
 
             if (!mSpManager.hasSidForUser(userId)) {
@@ -2993,8 +2994,8 @@
                 }
             }
         } else {
-            // Cache all profile password if they use unified work challenge. This will later be
-            // used to clear the profile's password in synchronizeUnifiedWorkChallengeForProfiles()
+            // Cache all profile password if they use unified challenge. This will later be used to
+            // clear the profile's password in synchronizeUnifiedChallengeForProfiles().
             profilePasswords = getDecryptedPasswordsForAllTiedProfiles(userId);
 
             mSpManager.clearSidForUser(userId);
@@ -3010,10 +3011,10 @@
         }
         setCurrentLskfBasedProtectorId(newProtectorId, userId);
         LockPatternUtils.invalidateCredentialTypeCache();
-        synchronizeUnifiedWorkChallengeForProfiles(userId, profilePasswords);
+        synchronizeUnifiedChallengeForProfiles(userId, profilePasswords);
 
         setUserPasswordMetrics(credential, userId);
-        mManagedProfilePasswordCache.removePassword(userId);
+        mUnifiedProfilePasswordCache.removePassword(userId);
         if (savedCredentialType != CREDENTIAL_TYPE_NONE) {
             mSpManager.destroyAllWeakTokenBasedProtectors(userId);
         }
@@ -3114,7 +3115,7 @@
                 try {
                     currentCredential = getDecryptedPasswordForTiedProfile(userId);
                 } catch (Exception e) {
-                    Slog.e(TAG, "Failed to get work profile credential", e);
+                    Slog.e(TAG, "Failed to get unified profile password", e);
                     return null;
                 }
             }
@@ -3284,7 +3285,7 @@
     @Override
     public boolean tryUnlockWithCachedUnifiedChallenge(int userId) {
         checkPasswordReadPermission();
-        try (LockscreenCredential cred = mManagedProfilePasswordCache.retrievePassword(userId)) {
+        try (LockscreenCredential cred = mUnifiedProfilePasswordCache.retrievePassword(userId)) {
             if (cred == null) {
                 return false;
             }
@@ -3296,7 +3297,7 @@
     @Override
     public void removeCachedUnifiedChallenge(int userId) {
         checkWritePermission();
-        mManagedProfilePasswordCache.removePassword(userId);
+        mUnifiedProfilePasswordCache.removePassword(userId);
     }
 
     static String timestampToString(long timestamp) {
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
index 1e8b387..6d123cc 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
@@ -501,10 +501,10 @@
         final UserInfo parentInfo = um.getProfileParent(userId);
 
         if (parentInfo == null) {
-            // This user owns its lock settings files - safe to delete them
+            // Delete files specific to non-profile users.
             deleteFile(getRebootEscrowFile(userId));
         } else {
-            // Managed profile
+            // Delete files specific to profile users.
             removeChildProfileLock(userId);
         }
 
diff --git a/services/core/java/com/android/server/locksettings/ManagedProfilePasswordCache.java b/services/core/java/com/android/server/locksettings/UnifiedProfilePasswordCache.java
similarity index 84%
rename from services/core/java/com/android/server/locksettings/ManagedProfilePasswordCache.java
rename to services/core/java/com/android/server/locksettings/UnifiedProfilePasswordCache.java
index 1298fe8f..21caf76 100644
--- a/services/core/java/com/android/server/locksettings/ManagedProfilePasswordCache.java
+++ b/services/core/java/com/android/server/locksettings/UnifiedProfilePasswordCache.java
@@ -43,30 +43,31 @@
 import javax.crypto.spec.GCMParameterSpec;
 
 /**
- * Caches *unified* work challenge for managed profiles. The cached credential is encrypted using
- * a keystore key auth-bound to the parent user's lockscreen credential, similar to how unified
- * work challenge is normally secured.
- *
- * <p> The cache is filled whenever the managed profile's unified challenge is created or derived
- * (as part of the parent user's credential verification flow). It's removed when the profile is
- * deleted or a (separate) lockscreen credential is explicitly set on the profile. There is also
- * an ADB command to evict the cache "cmd lock_settings remove-cache --user X", to assist
- * development and testing.
-
- * <p> The encrypted credential is stored in-memory only so the cache does not persist across
- * reboots.
+ * An in-memory cache for unified profile passwords.  A "unified profile password" is the random
+ * password that the system automatically generates and manages for each profile that uses a unified
+ * challenge and where the parent user has a secure lock screen.
+ * <p>
+ * Each password in this cache is encrypted by a Keystore key that is auth-bound to the parent user.
+ * This is very similar to how the password is protected on-disk, but the in-memory cache uses a
+ * much longer timeout on the keys: 7 days instead of 30 seconds.  This enables use cases like
+ * unpausing work apps without requiring authentication as frequently.
+ * <p>
+ * Unified profile passwords are cached when they are created, or when they are decrypted as part of
+ * the parent user's LSKF verification flow.  They are removed when the profile is deleted or when a
+ * separate challenge is explicitly set on the profile.  There is also an ADB command to evict a
+ * cached password, "locksettings remove-cache --user X", to assist development and testing.
  */
 @VisibleForTesting // public visibility is needed for Mockito
-public class ManagedProfilePasswordCache {
+public class UnifiedProfilePasswordCache {
 
-    private static final String TAG = "ManagedProfilePasswordCache";
+    private static final String TAG = "UnifiedProfilePasswordCache";
     private static final int KEY_LENGTH = 256;
     private static final int CACHE_TIMEOUT_SECONDS = (int) TimeUnit.DAYS.toSeconds(7);
 
     private final SparseArray<byte[]> mEncryptedPasswords = new SparseArray<>();
     private final KeyStore mKeyStore;
 
-    public ManagedProfilePasswordCache(KeyStore keyStore) {
+    public UnifiedProfilePasswordCache(KeyStore keyStore) {
         mKeyStore = keyStore;
     }
 
@@ -151,7 +152,8 @@
                 Slog.d(TAG, "Cannot decrypt", e);
                 return null;
             }
-            LockscreenCredential result = LockscreenCredential.createManagedPassword(credential);
+            LockscreenCredential result =
+                    LockscreenCredential.createUnifiedProfilePassword(credential);
             Arrays.fill(credential, (byte) 0);
             return result;
         }
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
index 10b6052..e5807e8 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
@@ -82,6 +82,7 @@
 import java.security.cert.X509Certificate;
 import java.security.spec.InvalidKeySpecException;
 import java.util.Arrays;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
@@ -272,9 +273,10 @@
         CertPath certPath;
         X509Certificate rootCert =
                 mTestCertHelper.getRootCertificate(rootCertificateAlias);
+        Date validationDate = mTestCertHelper.getValidationDate(rootCertificateAlias);
         try {
             Log.d(TAG, "Getting and validating a random endpoint certificate");
-            certPath = certXml.getRandomEndpointCert(rootCert);
+            certPath = certXml.getRandomEndpointCert(rootCert, validationDate);
         } catch (CertValidationException e) {
             Log.e(TAG, "Invalid endpoint cert", e);
             throw new ServiceSpecificException(ERROR_INVALID_CERTIFICATE, e.getMessage());
@@ -348,10 +350,11 @@
 
         X509Certificate rootCert =
                 mTestCertHelper.getRootCertificate(rootCertificateAlias);
+        Date validationDate = mTestCertHelper.getValidationDate(rootCertificateAlias);
         try {
-            sigXml.verifyFileSignature(rootCert, recoveryServiceCertFile);
+            sigXml.verifyFileSignature(rootCert, recoveryServiceCertFile, validationDate);
         } catch (CertValidationException e) {
-            Log.d(TAG, "The signature over the cert file is invalid."
+            Log.e(TAG, "The signature over the cert file is invalid."
                     + " Cert: " + HexDump.toHexString(recoveryServiceCertFile)
                     + " Sig: " + HexDump.toHexString(recoveryServiceSigFile));
             throw new ServiceSpecificException(ERROR_INVALID_CERTIFICATE, e.getMessage());
@@ -601,8 +604,9 @@
         }
 
         try {
-            CertUtils.validateCertPath(
-                    mTestCertHelper.getRootCertificate(rootCertificateAlias), certPath);
+            Date validationDate = mTestCertHelper.getValidationDate(rootCertificateAlias);
+            CertUtils.validateCertPath(mTestCertHelper.getRootCertificate(rootCertificateAlias),
+                    certPath, validationDate);
         } catch (CertValidationException e) {
             Log.e(TAG, "Failed to validate the given cert path", e);
             throw new ServiceSpecificException(ERROR_INVALID_CERTIFICATE, e.getMessage());
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/TestOnlyInsecureCertificateHelper.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/TestOnlyInsecureCertificateHelper.java
index c963f79..4a1cae2 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/TestOnlyInsecureCertificateHelper.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/TestOnlyInsecureCertificateHelper.java
@@ -29,6 +29,7 @@
 import com.android.internal.widget.LockPatternUtils;
 
 import java.security.cert.X509Certificate;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -67,6 +68,18 @@
         return rootCertificate;
     }
 
+    /**
+     * Returns hardcoded validation date for e2e tests.
+     */
+    public @Nullable Date getValidationDate(String rootCertificateAlias) {
+        if (isTestOnlyCertificateAlias(rootCertificateAlias)) {
+            // Certificate used for e2e test is expired.
+            return new Date(2019 - 1900, 1, 30);
+        } else {
+            return null; // Use current time
+        }
+    }
+
     public @NonNull String getDefaultCertificateAliasIfEmpty(
             @Nullable String rootCertificateAlias) {
         if (rootCertificateAlias == null || rootCertificateAlias.isEmpty()) {
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/CertUtils.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/CertUtils.java
index 26e8270..0881275 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/CertUtils.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/CertUtils.java
@@ -305,12 +305,13 @@
      *
      * @param trustedRoot the trusted root certificate
      * @param certPath the certificate path to be validated
+     * @param validationDate use null for current time
      * @throws CertValidationException if the given certificate path is invalid, e.g., is expired,
      *                                 or does not have a valid signature
      */
-    public static void validateCertPath(X509Certificate trustedRoot, CertPath certPath)
-            throws CertValidationException {
-        validateCertPath(/*validationDate=*/ null, trustedRoot, certPath);
+    public static void validateCertPath(X509Certificate trustedRoot, CertPath certPath,
+                @Nullable Date validationDate) throws CertValidationException {
+        validateCertPath(validationDate, trustedRoot, certPath);
     }
 
     /**
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/CertXml.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/CertXml.java
index ff22a8d..d159a84 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/CertXml.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/CertXml.java
@@ -76,15 +76,16 @@
      * and returns the certificate path including the chosen certificate if it is valid.
      *
      * @param trustedRoot the trusted root certificate
+     * @param validationDate use null for current time
      * @return the certificate path including the chosen certificate if the certificate is valid
      * @throws CertValidationException if the chosen certificate cannot be validated based on the
      *                                 trusted root certificate
      */
-    public CertPath getRandomEndpointCert(X509Certificate trustedRoot)
-            throws CertValidationException {
+    public CertPath getRandomEndpointCert(X509Certificate trustedRoot,
+            @Nullable Date validationDate)throws CertValidationException {
         return getEndpointCert(
                 new SecureRandom().nextInt(this.endpointCerts.size()),
-                /*validationDate=*/ null,
+                validationDate,
                 trustedRoot);
     }
 
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/SigXml.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/SigXml.java
index e75be85..c3f4f55 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/SigXml.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/SigXml.java
@@ -18,7 +18,7 @@
 
 import android.annotation.Nullable;
 
-import com.android.internal.annotations.VisibleForTesting;
+import org.w3c.dom.Element;
 
 import java.security.cert.X509Certificate;
 import java.util.ArrayList;
@@ -26,8 +26,6 @@
 import java.util.Date;
 import java.util.List;
 
-import org.w3c.dom.Element;
-
 /**
  * Parses and holds the XML file containing the signature of the XML file containing the list of THM
  * public-key certificates.
@@ -58,17 +56,13 @@
      *
      * @param trustedRoot     the trusted root certificate
      * @param signedFileBytes the original file content that has been signed
+     * @param validationDate use null for current time
+     *
      * @throws CertValidationException if the signature verification fails, or the signer's
      *                                 certificate contained in this XML file cannot be validated
      *                                 based on the trusted root certificate
      */
-    public void verifyFileSignature(X509Certificate trustedRoot, byte[] signedFileBytes)
-            throws CertValidationException {
-        verifyFileSignature(trustedRoot, signedFileBytes, /*validationDate=*/ null);
-    }
-
-    @VisibleForTesting
-    void verifyFileSignature(
+    public void verifyFileSignature(
             X509Certificate trustedRoot, byte[] signedFileBytes, @Nullable Date validationDate)
             throws CertValidationException {
         CertUtils.validateCert(validationDate, trustedRoot, intermediateCerts, signerCert);
diff --git a/services/core/java/com/android/server/media/AudioPoliciesBluetoothRouteController.java b/services/core/java/com/android/server/media/AudioPoliciesBluetoothRouteController.java
index a00999d..7cf3983 100644
--- a/services/core/java/com/android/server/media/AudioPoliciesBluetoothRouteController.java
+++ b/services/core/java/com/android/server/media/AudioPoliciesBluetoothRouteController.java
@@ -39,6 +39,7 @@
 
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.media.flags.Flags;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -219,7 +220,10 @@
         BluetoothRouteInfo
                 newBtRoute = new BluetoothRouteInfo();
         newBtRoute.mBtDevice = device;
-        String deviceName = device.getName();
+        String deviceName =
+                Flags.enableUseOfBluetoothDeviceGetAliasForMr2infoGetName()
+                        ? device.getAlias()
+                        : device.getName();
         if (TextUtils.isEmpty(deviceName)) {
             deviceName = mContext.getResources().getText(R.string.unknownName).toString();
         }
diff --git a/services/core/java/com/android/server/media/AudioPoliciesDeviceRouteController.java b/services/core/java/com/android/server/media/AudioPoliciesDeviceRouteController.java
index 173c452..8504495 100644
--- a/services/core/java/com/android/server/media/AudioPoliciesDeviceRouteController.java
+++ b/services/core/java/com/android/server/media/AudioPoliciesDeviceRouteController.java
@@ -330,8 +330,11 @@
                 TextUtils.isEmpty(address)
                         ? null
                         : mBluetoothRouteController.getRouteIdForBluetoothAddress(address);
-        return createMediaRoute2Info(
-                routeId, audioDeviceInfo.getType(), audioDeviceInfo.getProductName(), address);
+        // We use the name from the port instead AudioDeviceInfo#getProductName because the latter
+        // replaces empty names with the name of the device (example: Pixel 8). In that case we want
+        // to derive a name ourselves from the type instead.
+        String deviceName = audioDeviceInfo.getPort().name();
+        return createMediaRoute2Info(routeId, audioDeviceInfo.getType(), deviceName, address);
     }
 
     /**
@@ -339,8 +342,8 @@
      *
      * @param routeId A route id, or null to use an id pre-defined for the given {@code type}.
      * @param audioDeviceInfoType The type as obtained from {@link AudioDeviceInfo#getType}.
-     * @param productName The product name as obtained from {@link
-     *     AudioDeviceInfo#getProductName()}, or null to use a predefined name for the given {@code
+     * @param deviceName A human readable name to populate the route's {@link
+     *     MediaRoute2Info#getName name}, or null to use a predefined name for the given {@code
      *     type}.
      * @param address The type as obtained from {@link AudioDeviceInfo#getAddress()} or {@link
      *     BluetoothDevice#getAddress()}.
@@ -350,7 +353,7 @@
     private MediaRoute2Info createMediaRoute2Info(
             @Nullable String routeId,
             int audioDeviceInfoType,
-            @Nullable CharSequence productName,
+            @Nullable CharSequence deviceName,
             @Nullable String address) {
         SystemRouteInfo systemRouteInfo =
                 AUDIO_DEVICE_INFO_TYPE_TO_ROUTE_INFO.get(audioDeviceInfoType);
@@ -359,7 +362,7 @@
             // earpiece.
             return null;
         }
-        CharSequence humanReadableName = productName;
+        CharSequence humanReadableName = deviceName;
         if (TextUtils.isEmpty(humanReadableName)) {
             humanReadableName = mContext.getResources().getText(systemRouteInfo.mNameResource);
         }
diff --git a/services/core/java/com/android/server/media/LegacyBluetoothRouteController.java b/services/core/java/com/android/server/media/LegacyBluetoothRouteController.java
index 041fceaf..ede2d27 100644
--- a/services/core/java/com/android/server/media/LegacyBluetoothRouteController.java
+++ b/services/core/java/com/android/server/media/LegacyBluetoothRouteController.java
@@ -43,6 +43,7 @@
 import android.util.SparseIntArray;
 
 import com.android.internal.R;
+import com.android.media.flags.Flags;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -283,7 +284,10 @@
         newBtRoute.mBtDevice = device;
 
         String routeId = device.getAddress();
-        String deviceName = device.getName();
+        String deviceName =
+                Flags.enableUseOfBluetoothDeviceGetAliasForMr2infoGetName()
+                        ? device.getAlias()
+                        : device.getName();
         if (TextUtils.isEmpty(deviceName)) {
             deviceName = mContext.getResources().getText(R.string.unknownName).toString();
         }
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index df9e741..5e18727 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -964,6 +964,7 @@
         disposeUserIfNeededLocked(userRecord); // since router removed from user
     }
 
+    @GuardedBy("mLock")
     private void setDiscoveryRequestWithRouter2Locked(@NonNull RouterRecord routerRecord,
             @NonNull RouteDiscoveryPreference discoveryRequest) {
         if (routerRecord.mDiscoveryPreference.equals(discoveryRequest)) {
@@ -1016,6 +1017,7 @@
                         routeListingPreference));
     }
 
+    @GuardedBy("mLock")
     private void setRouteVolumeWithRouter2Locked(@NonNull IMediaRouter2 router,
             @NonNull MediaRoute2Info route, int volume) {
         final IBinder binder = router.asBinder();
@@ -1035,6 +1037,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void requestCreateSessionWithRouter2Locked(int requestId, long managerRequestId,
             @NonNull IMediaRouter2 router, @NonNull RoutingSessionInfo oldSession,
             @NonNull MediaRoute2Info route, @Nullable Bundle sessionHints) {
@@ -1117,6 +1120,7 @@
                         sessionHints));
     }
 
+    @GuardedBy("mLock")
     private void selectRouteWithRouter2Locked(@NonNull IMediaRouter2 router,
             @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route) {
         final IBinder binder = router.asBinder();
@@ -1138,6 +1142,7 @@
                         DUMMY_REQUEST_ID, routerRecord, uniqueSessionId, route));
     }
 
+    @GuardedBy("mLock")
     private void deselectRouteWithRouter2Locked(@NonNull IMediaRouter2 router,
             @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route) {
         final IBinder binder = router.asBinder();
@@ -1159,6 +1164,7 @@
                         DUMMY_REQUEST_ID, routerRecord, uniqueSessionId, route));
     }
 
+    @GuardedBy("mLock")
     private void transferToRouteWithRouter2Locked(@NonNull IMediaRouter2 router,
             @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route) {
         final IBinder binder = router.asBinder();
@@ -1191,6 +1197,7 @@
         }
     }
 
+    @GuardedBy("mLock")
     private void setSessionVolumeWithRouter2Locked(@NonNull IMediaRouter2 router,
             @NonNull String uniqueSessionId, int volume) {
         final IBinder binder = router.asBinder();
@@ -1215,6 +1222,7 @@
                         DUMMY_REQUEST_ID, uniqueSessionId, volume));
     }
 
+    @GuardedBy("mLock")
     private void releaseSessionWithRouter2Locked(@NonNull IMediaRouter2 router,
             @NonNull String uniqueSessionId) {
         final IBinder binder = router.asBinder();
@@ -1240,6 +1248,7 @@
 
     // Start of locked methods that are used by MediaRouter2Manager.
 
+    @GuardedBy("mLock")
     private List<RoutingSessionInfo> getRemoteSessionsLocked(
             @NonNull IMediaRouter2Manager manager) {
         final IBinder binder = manager.asBinder();
@@ -1330,6 +1339,7 @@
                         UserHandler::notifyInitialRoutesToManager, userRecord.mHandler, manager));
     }
 
+    @GuardedBy("mLock")
     private void unregisterManagerLocked(@NonNull IMediaRouter2Manager manager, boolean died) {
         ManagerRecord managerRecord = mAllManagerRecords.remove(manager.asBinder());
         if (managerRecord == null) {
@@ -1355,6 +1365,7 @@
         disposeUserIfNeededLocked(userRecord); // since manager removed from user
     }
 
+    @GuardedBy("mLock")
     private void startScanLocked(@NonNull IMediaRouter2Manager manager) {
         final IBinder binder = manager.asBinder();
         ManagerRecord managerRecord = mAllManagerRecords.get(binder);
@@ -1368,6 +1379,7 @@
         managerRecord.startScan();
     }
 
+    @GuardedBy("mLock")
     private void stopScanLocked(@NonNull IMediaRouter2Manager manager) {
         final IBinder binder = manager.asBinder();
         ManagerRecord managerRecord = mAllManagerRecords.get(binder);
@@ -1381,6 +1393,7 @@
         managerRecord.stopScan();
     }
 
+    @GuardedBy("mLock")
     private void setRouteVolumeWithManagerLocked(int requestId,
             @NonNull IMediaRouter2Manager manager,
             @NonNull MediaRoute2Info route, int volume) {
@@ -1402,6 +1415,7 @@
                         uniqueRequestId, route, volume));
     }
 
+    @GuardedBy("mLock")
     private void requestCreateSessionWithManagerLocked(int requestId,
             @NonNull IMediaRouter2Manager manager, @NonNull RoutingSessionInfo oldSession,
             @NonNull MediaRoute2Info route) {
@@ -1455,6 +1469,7 @@
                         uniqueRequestId, routerRecord, managerRecord, oldSession, route));
     }
 
+    @GuardedBy("mLock")
     private void selectRouteWithManagerLocked(int requestId, @NonNull IMediaRouter2Manager manager,
             @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route) {
         final IBinder binder = manager.asBinder();
@@ -1479,6 +1494,7 @@
                         uniqueRequestId, routerRecord, uniqueSessionId, route));
     }
 
+    @GuardedBy("mLock")
     private void deselectRouteWithManagerLocked(int requestId,
             @NonNull IMediaRouter2Manager manager,
             @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route) {
@@ -1504,6 +1520,7 @@
                         uniqueRequestId, routerRecord, uniqueSessionId, route));
     }
 
+    @GuardedBy("mLock")
     private void transferToRouteWithManagerLocked(int requestId,
             @NonNull IMediaRouter2Manager manager,
             @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route) {
@@ -1529,6 +1546,7 @@
                         uniqueRequestId, routerRecord, uniqueSessionId, route));
     }
 
+    @GuardedBy("mLock")
     private void setSessionVolumeWithManagerLocked(int requestId,
             @NonNull IMediaRouter2Manager manager,
             @NonNull String uniqueSessionId, int volume) {
@@ -1550,6 +1568,7 @@
                         uniqueRequestId, uniqueSessionId, volume));
     }
 
+    @GuardedBy("mLock")
     private void releaseSessionWithManagerLocked(int requestId,
             @NonNull IMediaRouter2Manager manager, @NonNull String uniqueSessionId) {
         final IBinder binder = manager.asBinder();
@@ -1652,6 +1671,7 @@
 
         // TODO: This assumes that only one router exists in a package.
         //       Do this in Android S or later.
+        @GuardedBy("mLock")
         RouterRecord findRouterRecordLocked(String packageName) {
             for (RouterRecord routerRecord : mRouterRecords) {
                 if (TextUtils.equals(routerRecord.mPackageName, packageName)) {
@@ -1739,6 +1759,7 @@
             return mHasModifyAudioRoutingPermission || mHasBluetoothRoutingPermission.get();
         }
 
+        @GuardedBy("mLock")
         public void maybeUpdateSystemRoutingPermissionLocked() {
             boolean oldSystemRoutingPermissionValue = hasSystemRoutingPermission();
             mHasBluetoothRoutingPermission.set(checkCallerHasBluetoothPermissions(mPid, mUid));
@@ -2063,6 +2084,7 @@
                     this, provider, uniqueRequestId, reason));
         }
 
+        @GuardedBy("mLock")
         @Nullable
         public RouterRecord findRouterWithSessionLocked(@NonNull String uniqueSessionId) {
             return mSessionToRouterMap.get(uniqueSessionId);
diff --git a/services/core/java/com/android/server/notification/DefaultDeviceEffectsApplier.java b/services/core/java/com/android/server/notification/DefaultDeviceEffectsApplier.java
index 9fdeda4..8855666 100644
--- a/services/core/java/com/android/server/notification/DefaultDeviceEffectsApplier.java
+++ b/services/core/java/com/android/server/notification/DefaultDeviceEffectsApplier.java
@@ -16,14 +16,23 @@
 
 package com.android.server.notification;
 
+import static android.app.UiModeManager.MODE_NIGHT_CUSTOM_TYPE_BEDTIME;
+
 import android.app.UiModeManager;
 import android.app.WallpaperManager;
+import android.content.BroadcastReceiver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.hardware.display.ColorDisplayManager;
 import android.os.Binder;
 import android.os.PowerManager;
 import android.service.notification.DeviceEffectsApplier;
 import android.service.notification.ZenDeviceEffects;
+import android.service.notification.ZenModeConfig;
+import android.service.notification.ZenModeConfig.ConfigChangeOrigin;
+
+import com.android.internal.annotations.GuardedBy;
 
 /** Default implementation for {@link DeviceEffectsApplier}. */
 class DefaultDeviceEffectsApplier implements DeviceEffectsApplier {
@@ -34,13 +43,24 @@
     private static final int SATURATION_LEVEL_FULL_COLOR = 100;
     private static final float WALLPAPER_DIM_AMOUNT_DIMMED = 0.6f;
     private static final float WALLPAPER_DIM_AMOUNT_NORMAL = 0f;
+    private static final IntentFilter SCREEN_OFF_INTENT_FILTER = new IntentFilter(
+            Intent.ACTION_SCREEN_OFF);
 
+    private final Context mContext;
     private final ColorDisplayManager mColorDisplayManager;
     private final PowerManager mPowerManager;
     private final UiModeManager mUiModeManager;
     private final WallpaperManager mWallpaperManager;
 
+    private final Object mRegisterReceiverLock = new Object();
+    @GuardedBy("mRegisterReceiverLock")
+    private boolean mIsScreenOffReceiverRegistered;
+
+    private ZenDeviceEffects mLastAppliedEffects = new ZenDeviceEffects.Builder().build();
+    private boolean mPendingNightMode;
+
     DefaultDeviceEffectsApplier(Context context) {
+        mContext = context;
         mColorDisplayManager = context.getSystemService(ColorDisplayManager.class);
         mPowerManager = context.getSystemService(PowerManager.class);
         mUiModeManager = context.getSystemService(UiModeManager.class);
@@ -48,24 +68,90 @@
     }
 
     @Override
-    public void apply(ZenDeviceEffects effects) {
+    public void apply(ZenDeviceEffects effects, @ConfigChangeOrigin int origin) {
         Binder.withCleanCallingIdentity(() -> {
-            mPowerManager.suppressAmbientDisplay(SUPPRESS_AMBIENT_DISPLAY_TOKEN,
-                    effects.shouldSuppressAmbientDisplay());
-
-            if (mColorDisplayManager != null) {
-                mColorDisplayManager.setSaturationLevel(
-                        effects.shouldDisplayGrayscale() ? SATURATION_LEVEL_GRAYSCALE
-                                : SATURATION_LEVEL_FULL_COLOR);
+            if (mLastAppliedEffects.shouldSuppressAmbientDisplay()
+                    != effects.shouldSuppressAmbientDisplay()) {
+                mPowerManager.suppressAmbientDisplay(SUPPRESS_AMBIENT_DISPLAY_TOKEN,
+                        effects.shouldSuppressAmbientDisplay());
             }
 
-            if (mWallpaperManager != null) {
-                mWallpaperManager.setWallpaperDimAmount(
-                        effects.shouldDimWallpaper() ? WALLPAPER_DIM_AMOUNT_DIMMED
-                                : WALLPAPER_DIM_AMOUNT_NORMAL);
+            if (mLastAppliedEffects.shouldDisplayGrayscale() != effects.shouldDisplayGrayscale()) {
+                if (mColorDisplayManager != null) {
+                    mColorDisplayManager.setSaturationLevel(
+                            effects.shouldDisplayGrayscale() ? SATURATION_LEVEL_GRAYSCALE
+                                    : SATURATION_LEVEL_FULL_COLOR);
+                }
             }
 
-            // TODO: b/308673343 - Apply dark theme (via UiModeManager) when screen is off.
+            if (mLastAppliedEffects.shouldDimWallpaper() != effects.shouldDimWallpaper()) {
+                if (mWallpaperManager != null) {
+                    mWallpaperManager.setWallpaperDimAmount(
+                            effects.shouldDimWallpaper() ? WALLPAPER_DIM_AMOUNT_DIMMED
+                                    : WALLPAPER_DIM_AMOUNT_NORMAL);
+                }
+            }
+
+            if (mLastAppliedEffects.shouldUseNightMode() != effects.shouldUseNightMode()) {
+                updateOrScheduleNightMode(effects.shouldUseNightMode(), origin);
+            }
         });
+
+        mLastAppliedEffects = effects;
+    }
+
+    private void updateOrScheduleNightMode(boolean useNightMode, @ConfigChangeOrigin int origin) {
+        mPendingNightMode = useNightMode;
+
+        // Changing the theme can be disruptive for the user (Activities are likely recreated, may
+        // lose some state). Therefore we only apply the change immediately if the rule was
+        // activated manually, or we are initializing, or the screen is currently off/dreaming.
+        if (origin == ZenModeConfig.UPDATE_ORIGIN_INIT
+                || origin == ZenModeConfig.UPDATE_ORIGIN_INIT_USER
+                || origin == ZenModeConfig.UPDATE_ORIGIN_USER
+                || origin == ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI
+                || !mPowerManager.isInteractive()) {
+            unregisterScreenOffReceiver();
+            updateNightModeImmediately(useNightMode);
+        } else {
+            registerScreenOffReceiver();
+        }
+    }
+
+    @GuardedBy("mRegisterReceiverLock")
+    private final BroadcastReceiver mNightModeWhenScreenOff = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            unregisterScreenOffReceiver();
+            updateNightModeImmediately(mPendingNightMode);
+        }
+    };
+
+    private void updateNightModeImmediately(boolean useNightMode) {
+        Binder.withCleanCallingIdentity(() -> {
+            // TODO: b/314285749 - Placeholder; use real APIs when available.
+            mUiModeManager.setNightModeCustomType(MODE_NIGHT_CUSTOM_TYPE_BEDTIME);
+            mUiModeManager.setNightModeActivatedForCustomMode(MODE_NIGHT_CUSTOM_TYPE_BEDTIME,
+                    useNightMode);
+        });
+    }
+
+    private void registerScreenOffReceiver() {
+        synchronized (mRegisterReceiverLock) {
+            if (!mIsScreenOffReceiverRegistered) {
+                mContext.registerReceiver(mNightModeWhenScreenOff, SCREEN_OFF_INTENT_FILTER,
+                        Context.RECEIVER_NOT_EXPORTED);
+                mIsScreenOffReceiverRegistered = true;
+            }
+        }
+    }
+
+    private void unregisterScreenOffReceiver() {
+        synchronized (mRegisterReceiverLock) {
+            if (mIsScreenOffReceiverRegistered) {
+                mIsScreenOffReceiverRegistered = false;
+                mContext.unregisterReceiver(mNightModeWhenScreenOff);
+            }
+        }
     }
 }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerInternal.java b/services/core/java/com/android/server/notification/NotificationManagerInternal.java
index b12180b..4b8de4e 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerInternal.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerInternal.java
@@ -19,6 +19,7 @@
 import android.app.Notification;
 import android.app.NotificationChannel;
 import android.app.NotificationChannelGroup;
+import android.service.notification.DeviceEffectsApplier;
 
 import java.util.Set;
 
@@ -54,4 +55,22 @@
     void cleanupHistoryFiles();
 
     void removeBitmaps();
+
+    /**
+     * Sets the {@link DeviceEffectsApplier} that will be used to apply the different
+     * {@link android.service.notification.ZenDeviceEffects} that are relevant for the platform
+     * when {@link android.service.notification.ZenModeConfig.ZenRule} instances are activated and
+     * deactivated.
+     *
+     * <p>This method is optional and needs only be called if the platform supports non-standard
+     * effects (i.e. any that are not <em>public APIs</em> in
+     * {@link android.service.notification.ZenDeviceEffects}, or if they must be applied in a
+     * non-standard fashion. If not used, a {@link DefaultDeviceEffectsApplier} will be invoked,
+     * which should be sufficient for most devices.
+     *
+     * <p>If this method is called, it <em>must</em> be during system startup and <em>before</em>
+     * the {@link com.android.server.SystemService#PHASE_THIRD_PARTY_APPS_CAN_START} boot phase.
+     * Otherwise an {@link IllegalStateException} will be thrown.
+     */
+    void setDeviceEffectsApplier(DeviceEffectsApplier applier);
 }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 02845fb..75d3dce 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -16,10 +16,17 @@
 
 package com.android.server.notification;
 
+import static android.Manifest.permission.RECEIVE_SENSITIVE_NOTIFICATIONS;
 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
 import static android.app.ActivityManagerInternal.ServiceNotificationPolicy.NOT_FOREGROUND_SERVICE;
 import static android.app.AppOpsManager.MODE_ALLOWED;
 import static android.app.Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
+import static android.app.Notification.EXTRA_BUILDER_APPLICATION_INFO;
+import static android.app.Notification.EXTRA_LARGE_ICON_BIG;
+import static android.app.Notification.EXTRA_SUB_TEXT;
+import static android.app.Notification.EXTRA_TEXT;
+import static android.app.Notification.EXTRA_TEXT_LINES;
+import static android.app.Notification.EXTRA_TITLE_BIG;
 import static android.app.Notification.FLAG_AUTOGROUP_SUMMARY;
 import static android.app.Notification.FLAG_AUTO_CANCEL;
 import static android.app.Notification.FLAG_BUBBLE;
@@ -80,6 +87,7 @@
 import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
 import static android.os.UserHandle.USER_NULL;
 import static android.os.UserHandle.USER_SYSTEM;
+import static android.service.notification.Flags.redactSensitiveNotificationsFromUntrustedListeners;
 import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ALERTING;
 import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_CONVERSATIONS;
 import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ONGOING;
@@ -119,6 +127,7 @@
 import static android.service.notification.NotificationListenerService.Ranking.RANKING_UNCHANGED;
 import static android.service.notification.NotificationListenerService.TRIM_FULL;
 import static android.service.notification.NotificationListenerService.TRIM_LIGHT;
+import static android.view.contentprotection.flags.Flags.rapidClearNotificationsByListenerAppOpEnabled;
 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
 
 import static com.android.internal.util.FrameworkStatsLog.DND_MODE_RULE;
@@ -162,6 +171,7 @@
 import android.app.IUriGrantsManager;
 import android.app.KeyguardManager;
 import android.app.Notification;
+import android.app.Notification.MessagingStyle;
 import android.app.NotificationChannel;
 import android.app.NotificationChannelGroup;
 import android.app.NotificationHistory;
@@ -169,6 +179,7 @@
 import android.app.NotificationManager;
 import android.app.NotificationManager.Policy;
 import android.app.PendingIntent;
+import android.app.Person;
 import android.app.RemoteServiceException.BadForegroundServiceNotificationException;
 import android.app.RemoteServiceException.BadUserInitiatedJobNotificationException;
 import android.app.StatsManager;
@@ -250,6 +261,7 @@
 import android.service.notification.Adjustment;
 import android.service.notification.Condition;
 import android.service.notification.ConversationChannelWrapper;
+import android.service.notification.DeviceEffectsApplier;
 import android.service.notification.IConditionProvider;
 import android.service.notification.INotificationListener;
 import android.service.notification.IStatusBarNotificationHolder;
@@ -414,6 +426,12 @@
 
     static final long SNOOZE_UNTIL_UNSPECIFIED = -1;
 
+    /**
+     *  The threshold, in milliseconds, to determine whether a notification has been
+     * cleared too quickly.
+     */
+    private static final int NOTIFICATION_RAPID_CLEAR_THRESHOLD_MS = 5000;
+
     static final int INVALID_UID = -1;
     static final String ROOT_PKG = "root";
 
@@ -567,7 +585,8 @@
     private ActivityTaskManagerInternal mAtm;
     private ActivityManager mActivityManager;
     private ActivityManagerInternal mAmi;
-    private IPackageManager mPackageManager;
+    @VisibleForTesting
+    IPackageManager mPackageManager;
     private PackageManager mPackageManagerClient;
     PackageManagerInternal mPackageManagerInternal;
     private PermissionManager mPermissionManager;
@@ -578,7 +597,8 @@
     @Nullable StatusBarManagerInternal mStatusBar;
     private WindowManagerInternal mWindowManagerInternal;
     private AlarmManager mAlarmManager;
-    private ICompanionDeviceManager mCompanionManager;
+    @VisibleForTesting
+    ICompanionDeviceManager mCompanionManager;
     private AccessibilityManager mAccessibilityManager;
     private DeviceIdleManager mDeviceIdleManager;
     private IUriGrantsManager mUgm;
@@ -595,7 +615,8 @@
     private PostNotificationTrackerFactory mPostNotificationTrackerFactory;
 
     final IBinder mForegroundToken = new Binder();
-    private WorkerHandler mHandler;
+    @VisibleForTesting
+    WorkerHandler mHandler;
     private final HandlerThread mRankingThread = new HandlerThread("ranker",
             Process.THREAD_PRIORITY_BACKGROUND);
 
@@ -687,7 +708,8 @@
 
     private final UserProfiles mUserProfiles = new UserProfiles();
     private NotificationListeners mListeners;
-    private NotificationAssistants mAssistants;
+    @VisibleForTesting
+    NotificationAssistants mAssistants;
     private ConditionProviders mConditionProviders;
     private NotificationUsageStats mUsageStats;
     private boolean mLockScreenAllowSecureNotifications = true;
@@ -2714,7 +2736,8 @@
                 new NotificationAssistants(getContext(), mNotificationLock, mUserProfiles,
                         AppGlobals.getPackageManager()),
                 new ConditionProviders(getContext(), mUserProfiles, AppGlobals.getPackageManager()),
-                null, snoozeHelper, new NotificationUsageStats(getContext()),
+                null /*CDM is not initialized yet*/, snoozeHelper,
+                new NotificationUsageStats(getContext()),
                 new AtomicFile(new File(
                         systemDir, "notification_policy.xml"), "notification-policy"),
                 (ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE),
@@ -3394,7 +3417,7 @@
     private String getHistoryText(Context appContext, Notification n) {
         CharSequence text = null;
         if (n.extras != null) {
-            text = n.extras.getCharSequence(Notification.EXTRA_TEXT);
+            text = n.extras.getCharSequence(EXTRA_TEXT);
 
             Notification.Builder nb = Notification.Builder.recoverBuilder(appContext, n);
 
@@ -3409,7 +3432,7 @@
             }
 
             if (TextUtils.isEmpty(text)) {
-                text = n.extras.getCharSequence(Notification.EXTRA_TEXT);
+                text = n.extras.getCharSequence(EXTRA_TEXT);
             }
         }
         return text == null ? null : String.valueOf(text);
@@ -4817,9 +4840,12 @@
             final int callingUid = Binder.getCallingUid();
             final int callingPid = Binder.getCallingPid();
             final long identity = Binder.clearCallingIdentity();
+            boolean notificationsRapidlyCleared = false;
+            final String pkg;
             try {
                 synchronized (mNotificationLock) {
                     final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
+                    pkg = info.component.getPackageName();
 
                     // Cancellation reason. If the token comes from assistant, label the
                     // cancellation as coming from the assistant; default to LISTENER_CANCEL.
@@ -4838,11 +4864,19 @@
                                     !mUserProfiles.isCurrentProfile(userId)) {
                                 continue;
                             }
+                            notificationsRapidlyCleared = notificationsRapidlyCleared
+                                    || isNotificationRecent(r);
                             cancelNotificationFromListenerLocked(info, callingUid, callingPid,
                                     r.getSbn().getPackageName(), r.getSbn().getTag(),
                                     r.getSbn().getId(), userId, reason);
                         }
                     } else {
+                        for (NotificationRecord notificationRecord : mNotificationList) {
+                            if (isNotificationRecent(notificationRecord)) {
+                                notificationsRapidlyCleared = true;
+                                break;
+                            }
+                        }
                         if (lifetimeExtensionRefactor()) {
                             cancelAllLocked(callingUid, callingPid, info.userid,
                                     REASON_LISTENER_CANCEL_ALL, info, info.supportsProfiles(),
@@ -4855,11 +4889,23 @@
                         }
                     }
                 }
+                if (notificationsRapidlyCleared) {
+                    mAppOps.noteOpNoThrow(AppOpsManager.OP_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER,
+                            callingUid, pkg, /* attributionTag= */ null, /* message= */ null);
+                }
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
         }
 
+        private boolean isNotificationRecent(@NonNull NotificationRecord notificationRecord) {
+            if (!rapidClearNotificationsByListenerAppOpEnabled()) {
+                return false;
+            }
+            return notificationRecord.getFreshnessMs(System.currentTimeMillis())
+                    < NOTIFICATION_RAPID_CLEAR_THRESHOLD_MS;
+        }
+
         /**
          * Handle request from an approved listener to re-enable itself.
          *
@@ -5149,20 +5195,14 @@
                 final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
                 final boolean getKeys = keys != null;
                 final int N = getKeys ? keys.length : mNotificationList.size();
-                final ArrayList<StatusBarNotification> list
-                        = new ArrayList<StatusBarNotification>(N);
+                final ArrayList<StatusBarNotification> list = new ArrayList<>(N);
                 for (int i=0; i<N; i++) {
                     final NotificationRecord r = getKeys
                             ? mNotificationsByKey.get(keys[i])
                             : mNotificationList.get(i);
-                    if (r == null) continue;
-                    StatusBarNotification sbn = r.getSbn();
-                    if (!isVisibleToListener(sbn, r.getNotificationType(), info)) continue;
-                    StatusBarNotification sbnToSend =
-                            (trim == TRIM_FULL) ? sbn : sbn.cloneLight();
-                    list.add(sbnToSend);
+                    addToListIfNeeded(r, info, list, trim);
                 }
-                return new ParceledListSlice<StatusBarNotification>(list);
+                return new ParceledListSlice<>(list);
             }
         }
 
@@ -5184,18 +5224,25 @@
                 final int N = snoozedRecords.size();
                 final ArrayList<StatusBarNotification> list = new ArrayList<>(N);
                 for (int i=0; i < N; i++) {
-                    final NotificationRecord r = snoozedRecords.get(i);
-                    if (r == null) continue;
-                    StatusBarNotification sbn = r.getSbn();
-                    if (!isVisibleToListener(sbn, r.getNotificationType(), info)) continue;
-                    StatusBarNotification sbnToSend =
-                            (trim == TRIM_FULL) ? sbn : sbn.cloneLight();
-                    list.add(sbnToSend);
+                    addToListIfNeeded(snoozedRecords.get(i), info, list, trim);
                 }
                 return new ParceledListSlice<>(list);
             }
         }
 
+        private void addToListIfNeeded(NotificationRecord r, ManagedServiceInfo info,
+                ArrayList<StatusBarNotification> notifications, int trim) {
+            if (r == null) return;
+            StatusBarNotification sbn = r.getSbn();
+            if (!isVisibleToListener(sbn, r.getNotificationType(), info)) return;
+            if (mListeners.hasSensitiveContent(r) && !mListeners.isUidTrusted(info.uid)) {
+                notifications.add(mListeners.redactStatusBarNotification(sbn));
+            } else {
+                notifications.add((trim == TRIM_FULL) ? sbn : sbn.cloneLight());
+            }
+
+        }
+
         @Override
         public void clearRequestedListenerHints(INotificationListener token) {
             final long identity = Binder.clearCallingIdentity();
@@ -5299,11 +5346,11 @@
         public void setZenMode(int mode, Uri conditionId, String reason) throws RemoteException {
             enforceSystemOrSystemUI("INotificationManager.setZenMode");
             final int callingUid = Binder.getCallingUid();
-            final boolean isSystemOrSystemUi = isCallerSystemOrSystemUi();
             final long identity = Binder.clearCallingIdentity();
             try {
-                mZenModeHelper.setManualZenMode(mode, conditionId, null, reason, callingUid,
-                        isSystemOrSystemUi);
+                mZenModeHelper.setManualZenMode(mode, conditionId,
+                        ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, // Checked by enforce()
+                        reason, /* caller= */ null, callingUid);
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
@@ -5334,14 +5381,7 @@
 
         @Override
         public String addAutomaticZenRule(AutomaticZenRule automaticZenRule, String pkg) {
-            Objects.requireNonNull(automaticZenRule, "automaticZenRule is null");
-            Objects.requireNonNull(automaticZenRule.getName(), "Name is null");
-            if (automaticZenRule.getOwner() == null
-                    && automaticZenRule.getConfigurationActivity() == null) {
-                throw new NullPointerException(
-                        "Rule must have a conditionproviderservice and/or configuration activity");
-            }
-            Objects.requireNonNull(automaticZenRule.getConditionId(), "ConditionId is null");
+            validateAutomaticZenRule(automaticZenRule);
             checkCallerIsSameApp(pkg);
             if (automaticZenRule.getZenPolicy() != null
                     && automaticZenRule.getInterruptionFilter() != INTERRUPTION_FILTER_PRIORITY) {
@@ -5360,30 +5400,48 @@
             }
 
             return mZenModeHelper.addAutomaticZenRule(rulePkg, automaticZenRule,
-                    "addAutomaticZenRule", Binder.getCallingUid(),
-                    // TODO: b/308670715: Distinguish FROM_APP from FROM_USER
-                    isCallerSystemOrSystemUi() ? ZenModeHelper.FROM_SYSTEM_OR_SYSTEMUI
-                            : ZenModeHelper.FROM_APP);
+                    // TODO: b/308670715: Distinguish origin properly (e.g. USER if creating a rule
+                    //  manually in Settings).
+                    isCallerSystemOrSystemUi() ? ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI
+                            : ZenModeConfig.UPDATE_ORIGIN_APP,
+                    "addAutomaticZenRule", Binder.getCallingUid());
         }
 
         @Override
-        public boolean updateAutomaticZenRule(String id, AutomaticZenRule automaticZenRule)
-                throws RemoteException {
-            Objects.requireNonNull(automaticZenRule, "automaticZenRule is null");
-            Objects.requireNonNull(automaticZenRule.getName(), "Name is null");
-            if (automaticZenRule.getOwner() == null
-                    && automaticZenRule.getConfigurationActivity() == null) {
+        public boolean updateAutomaticZenRule(String id, AutomaticZenRule automaticZenRule) {
+            validateAutomaticZenRule(automaticZenRule);
+            enforcePolicyAccess(Binder.getCallingUid(), "updateAutomaticZenRule");
+
+            // TODO: b/308670715: Distinguish origin properly (e.g. USER if updating a rule
+            //  manually in Settings).
+            return mZenModeHelper.updateAutomaticZenRule(id, automaticZenRule,
+                    isCallerSystemOrSystemUi() ? ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI
+                            : ZenModeConfig.UPDATE_ORIGIN_APP,
+                    "updateAutomaticZenRule", Binder.getCallingUid());
+        }
+
+        private void validateAutomaticZenRule(AutomaticZenRule rule) {
+            Objects.requireNonNull(rule, "automaticZenRule is null");
+            Objects.requireNonNull(rule.getName(), "Name is null");
+            rule.validate();
+            if (rule.getOwner() == null
+                    && rule.getConfigurationActivity() == null) {
                 throw new NullPointerException(
                         "Rule must have a conditionproviderservice and/or configuration activity");
             }
-            Objects.requireNonNull(automaticZenRule.getConditionId(), "ConditionId is null");
-            enforcePolicyAccess(Binder.getCallingUid(), "updateAutomaticZenRule");
+            Objects.requireNonNull(rule.getConditionId(), "ConditionId is null");
 
-            return mZenModeHelper.updateAutomaticZenRule(id, automaticZenRule,
-                    "updateAutomaticZenRule", Binder.getCallingUid(),
-                    // TODO: b/308670715: Distinguish FROM_APP from FROM_USER
-                    isCallerSystemOrSystemUi() ? ZenModeHelper.FROM_SYSTEM_OR_SYSTEMUI
-                            : ZenModeHelper.FROM_APP);
+            if (android.app.Flags.modesApi()) {
+                if (rule.getType() == AutomaticZenRule.TYPE_MANAGED) {
+                    int uid = Binder.getCallingUid();
+                    boolean isDeviceOwner = Binder.withCleanCallingIdentity(
+                            () -> mDpm.isActiveDeviceOwner(uid));
+                    if (!isDeviceOwner) {
+                        throw new IllegalArgumentException(
+                                "Only Device Owners can use AutomaticZenRules with TYPE_MANAGED");
+                    }
+                }
+            }
         }
 
         @Override
@@ -5392,8 +5450,12 @@
             // Verify that they can modify zen rules.
             enforcePolicyAccess(Binder.getCallingUid(), "removeAutomaticZenRule");
 
-            return mZenModeHelper.removeAutomaticZenRule(id, "removeAutomaticZenRule",
-                    Binder.getCallingUid(), isCallerSystemOrSystemUi());
+            // TODO: b/308670715: Distinguish origin properly (e.g. USER if removing a rule
+            //  manually in Settings).
+            return mZenModeHelper.removeAutomaticZenRule(id,
+                    isCallerSystemOrSystemUi() ? ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI
+                            : ZenModeConfig.UPDATE_ORIGIN_APP,
+                    "removeAutomaticZenRule", Binder.getCallingUid());
         }
 
         @Override
@@ -5402,8 +5464,9 @@
             enforceSystemOrSystemUI("removeAutomaticZenRules");
 
             return mZenModeHelper.removeAutomaticZenRules(packageName,
-                    packageName + "|removeAutomaticZenRules", Binder.getCallingUid(),
-                    isCallerSystemOrSystemUi());
+                    isCallerSystemOrSystemUi() ? ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI
+                            : ZenModeConfig.UPDATE_ORIGIN_APP,
+                    packageName + "|removeAutomaticZenRules", Binder.getCallingUid());
         }
 
         @Override
@@ -5418,11 +5481,16 @@
         public void setAutomaticZenRuleState(String id, Condition condition) {
             Objects.requireNonNull(id, "id is null");
             Objects.requireNonNull(condition, "Condition is null");
+            condition.validate();
 
             enforcePolicyAccess(Binder.getCallingUid(), "setAutomaticZenRuleState");
 
-            mZenModeHelper.setAutomaticZenRuleState(id, condition, Binder.getCallingUid(),
-                    isCallerSystemOrSystemUi());
+            // TODO: b/308670715: Distinguish origin properly (e.g. USER if toggling a rule
+            //  manually in Settings).
+            mZenModeHelper.setAutomaticZenRuleState(id, condition,
+                    isCallerSystemOrSystemUi() ? ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI
+                            : ZenModeConfig.UPDATE_ORIGIN_APP,
+                    Binder.getCallingUid());
         }
 
         @Override
@@ -5440,8 +5508,11 @@
 
             final long identity = Binder.clearCallingIdentity();
             try {
-                mZenModeHelper.setManualZenMode(zen, null, pkg, "setInterruptionFilter",
-                        callingUid, isSystemOrSystemUi);
+                mZenModeHelper.setManualZenMode(zen, null,
+                        isSystemOrSystemUi ? ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI
+                                : ZenModeConfig.UPDATE_ORIGIN_APP,
+                        /* reason= */ "setInterruptionFilter", /* caller= */ pkg,
+                        callingUid);
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
@@ -5806,7 +5877,10 @@
                 } else {
                     ZenLog.traceSetNotificationPolicy(pkg, applicationInfo.targetSdkVersion,
                             policy);
-                    mZenModeHelper.setNotificationPolicy(policy, callingUid, isSystemOrSystemUi);
+                    mZenModeHelper.setNotificationPolicy(policy,
+                            isSystemOrSystemUi ? ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI
+                                    : ZenModeConfig.UPDATE_ORIGIN_APP,
+                            callingUid);
                 }
             } catch (RemoteException e) {
                 Slog.e(TAG, "Failed to set notification policy", e);
@@ -6907,6 +6981,18 @@
                 }
             }
         }
+
+        @Override
+        public void setDeviceEffectsApplier(DeviceEffectsApplier applier) {
+            if (!android.app.Flags.modesApi()) {
+                return;
+            }
+            if (mZenModeHelper == null) {
+                throw new IllegalStateException("ZenModeHelper is not yet ready!");
+            }
+            // This can also throw IllegalStateException if called too late.
+            mZenModeHelper.setDeviceEffectsApplier(applier);
+        }
     };
 
     private static boolean isBigPictureWithBitmapOrIcon(Notification n) {
@@ -8507,8 +8593,8 @@
         }
 
         // Do not compare Spannables (will always return false); compare unstyled Strings
-        final String oldText = String.valueOf(oldN.extras.get(Notification.EXTRA_TEXT));
-        final String newText = String.valueOf(newN.extras.get(Notification.EXTRA_TEXT));
+        final String oldText = String.valueOf(oldN.extras.get(EXTRA_TEXT));
+        final String newText = String.valueOf(newN.extras.get(EXTRA_TEXT));
         if (!Objects.equals(oldText, newText)) {
             if (DEBUG_INTERRUPTIVENESS) {
                 Slog.v(TAG, "INTERRUPTIVENESS: "
@@ -11389,6 +11475,9 @@
         static final String FLAG_SEPARATOR = "\\|";
 
         private final ArraySet<ManagedServiceInfo> mLightTrimListeners = new ArraySet<>();
+
+        @GuardedBy("mTrustedListenerUids")
+        private final ArraySet<Integer> mTrustedListenerUids = new ArraySet<>();
         @GuardedBy("mRequestedNotificationListeners")
         private final ArrayMap<Pair<ComponentName, Integer>, NotificationListenerFilter>
                 mRequestedNotificationListeners = new ArrayMap<>();
@@ -11410,6 +11499,24 @@
         protected void setPackageOrComponentEnabled(String pkgOrComponent, int userId,
                 boolean isPrimary, boolean enabled, boolean userSet) {
             super.setPackageOrComponentEnabled(pkgOrComponent, userId, isPrimary, enabled, userSet);
+            String pkgName = getPackageName(pkgOrComponent);
+            if (redactSensitiveNotificationsFromUntrustedListeners()) {
+                try {
+                    int uid = mPackageManagerClient.getPackageUidAsUser(pkgName, userId);
+                    if (!enabled) {
+                        synchronized (mTrustedListenerUids) {
+                            mTrustedListenerUids.remove(uid);
+                        }
+                    }
+                    if (enabled && isAppTrustedNotificationListenerService(uid, pkgName)) {
+                        synchronized (mTrustedListenerUids) {
+                            mTrustedListenerUids.add(uid);
+                        }
+                    }
+                } catch (NameNotFoundException e) {
+                    Slog.e(TAG, "PackageManager could not find package " + pkgName, e);
+                }
+            }
 
             mContext.sendBroadcastAsUser(
                     new Intent(ACTION_NOTIFICATION_LISTENER_ENABLED_CHANGED)
@@ -11487,6 +11594,13 @@
                 update = makeRankingUpdateLocked(info);
                 updateUriPermissionsForActiveNotificationsLocked(info, true);
             }
+            if (redactSensitiveNotificationsFromUntrustedListeners()
+                    && isAppTrustedNotificationListenerService(
+                    info.uid, info.component.getPackageName())) {
+                synchronized (mTrustedListenerUids) {
+                    mTrustedListenerUids.add(info.uid);
+                }
+            }
             try {
                 listener.onListenerConnected(update);
             } catch (RemoteException e) {
@@ -11502,6 +11616,11 @@
                 updateListenerHintsLocked();
                 updateEffectsSuppressorLocked();
             }
+            if (redactSensitiveNotificationsFromUntrustedListeners()) {
+                synchronized (mTrustedListenerUids) {
+                    mTrustedListenerUids.remove(removed.uid);
+                }
+            }
             mLightTrimListeners.remove(removed);
         }
 
@@ -11807,8 +11926,16 @@
                 StatusBarNotification sbn = r.getSbn();
                 StatusBarNotification oldSbn = (old != null) ? old.getSbn() : null;
                 TrimCache trimCache = new TrimCache(sbn);
+                TrimCache redactedCache = null;
+                StatusBarNotification redactedSbn = null;
+                StatusBarNotification oldRedactedSbn = null;
+                boolean isNewSensitive = hasSensitiveContent(r);
+                boolean isOldSensitive = hasSensitiveContent(old);
 
                 for (final ManagedServiceInfo info : getServices()) {
+                    boolean isTrusted = isUidTrusted(info.uid);
+                    boolean sendRedacted = isNewSensitive && !isTrusted;
+                    boolean sendOldRedacted = isOldSensitive && !isTrusted;
                     boolean sbnVisible = isVisibleToListener(sbn, r.getNotificationType(), info);
                     boolean oldSbnVisible = (oldSbn != null)
                             && isVisibleToListener(oldSbn, old.getNotificationType(), info);
@@ -11834,9 +11961,14 @@
 
                     // This notification became invisible -> remove the old one.
                     if (oldSbnVisible && !sbnVisible) {
-                        final StatusBarNotification oldSbnLightClone = oldSbn.cloneLight();
+                        if (sendOldRedacted && oldRedactedSbn == null) {
+                            oldRedactedSbn = redactStatusBarNotification(oldSbn);
+                        }
+                        final StatusBarNotification oldSbnLightClone =
+                                sendOldRedacted ? oldRedactedSbn.cloneLight() : oldSbn.cloneLight();
                         listenerCalls.add(() -> notifyRemoved(
                                 info, oldSbnLightClone, update, null, REASON_USER_STOPPED));
+
                         continue;
                     }
                     // Grant access before listener is notified
@@ -11850,7 +11982,13 @@
                             sbn.getUid(),
                             false /* direct */, false /* retainOnUpdate */);
 
-                    final StatusBarNotification sbnToPost = trimCache.ForListener(info);
+                    if (sendRedacted && redactedSbn == null) {
+                        redactedSbn = redactStatusBarNotification(sbn);
+                        redactedCache = new TrimCache(redactedSbn);
+                    }
+
+                    final StatusBarNotification sbnToPost = sendRedacted
+                            ? redactedCache.ForListener(info) : trimCache.ForListener(info);
                     listenerCalls.add(() -> notifyPosted(info, sbnToPost, update));
                 }
             } catch (Exception e) {
@@ -11859,6 +11997,109 @@
             return listenerCalls;
         }
 
+        boolean isAppTrustedNotificationListenerService(int uid, String pkg) {
+            if (!redactSensitiveNotificationsFromUntrustedListeners()) {
+                return true;
+            }
+
+            try {
+                if (mPackageManager.checkUidPermission(RECEIVE_SENSITIVE_NOTIFICATIONS, uid)
+                        == PERMISSION_GRANTED || mPackageManagerInternal.isPlatformSigned(pkg)) {
+                    return true;
+                }
+
+                // check if there is a CDM association with the listener
+                // We don't listen for changes because if an association is lost, the app loses
+                // NLS access
+                List<AssociationInfo> cdmAssocs = new ArrayList<>();
+                if (mCompanionManager == null) {
+                    mCompanionManager = getCompanionManager();
+                }
+                if (mCompanionManager != null) {
+                    cdmAssocs =
+                            mCompanionManager.getAllAssociationsForUser(UserHandle.getUserId(uid));
+                }
+                for (int i = 0; i < cdmAssocs.size(); i++) {
+                    AssociationInfo assocInfo = cdmAssocs.get(i);
+                    if (!assocInfo.isRevoked() && pkg.equals(assocInfo.getPackageName())
+                            && assocInfo.getUserId() == UserHandle.getUserId(uid)) {
+                        return true;
+                    }
+                }
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Failed to check trusted status of listener", e);
+            }
+            return false;
+        }
+
+        StatusBarNotification redactStatusBarNotification(StatusBarNotification sbn) {
+            if (!redactSensitiveNotificationsFromUntrustedListeners()) {
+                return sbn;
+            }
+
+            ApplicationInfo appInfo = sbn.getNotification().extras.getParcelable(
+                    EXTRA_BUILDER_APPLICATION_INFO, ApplicationInfo.class);
+            String pkgLabel;
+            if (appInfo != null) {
+                pkgLabel = appInfo.loadLabel(mPackageManagerClient).toString();
+            } else {
+                Slog.w(TAG, "StatusBarNotification " + sbn + " does not have ApplicationInfo."
+                        + " Did you pass in a 'cloneLight' notification?");
+                pkgLabel = sbn.getPackageName();
+            }
+            String redactedText = mContext.getString(R.string.redacted_notification_message);
+            Notification oldNotif = sbn.getNotification();
+            Notification oldClone = new Notification();
+            oldNotif.cloneInto(oldClone, false);
+            Notification.Builder redactedNotifBuilder =
+                    new Notification.Builder(getContext(), oldClone);
+            redactedNotifBuilder.setContentTitle(pkgLabel);
+            redactedNotifBuilder.setContentText(redactedText);
+            redactedNotifBuilder.setSubText(null);
+            redactedNotifBuilder.setActions();
+            if (oldNotif.actions != null) {
+                for (int i = 0; i < oldNotif.actions.length; i++) {
+                    Notification.Action act =
+                            new Notification.Action.Builder(oldNotif.actions[i]).build();
+                    act.title = mContext.getString(R.string.redacted_notification_action_title);
+                    redactedNotifBuilder.addAction(act);
+                }
+            }
+
+            if (oldNotif.isStyle(MessagingStyle.class)) {
+                Person empty = new Person.Builder().setName("").build();
+                MessagingStyle messageStyle = new MessagingStyle(empty);
+                messageStyle.addMessage(new MessagingStyle.Message(
+                        redactedText, System.currentTimeMillis(), empty));
+                redactedNotifBuilder.setStyle(messageStyle);
+            }
+
+            Notification redacted = redactedNotifBuilder.build();
+            // Notification extras can't always be overridden by a builder (configured by a system
+            // property), so set them after building
+            if (redacted.extras.containsKey(EXTRA_TITLE_BIG)) {
+                redacted.extras.putString(EXTRA_TITLE_BIG, pkgLabel);
+            }
+            redacted.extras.remove(EXTRA_SUB_TEXT);
+            redacted.extras.remove(EXTRA_TEXT_LINES);
+            redacted.extras.remove(EXTRA_LARGE_ICON_BIG);
+            return sbn.cloneShallow(redacted);
+        }
+
+        boolean hasSensitiveContent(NotificationRecord r) {
+            if (r == null || !redactSensitiveNotificationsFromUntrustedListeners()) {
+                return false;
+            }
+            return r.hasSensitiveContent();
+        }
+
+        boolean isUidTrusted(int uid) {
+            synchronized (mTrustedListenerUids) {
+                return !redactSensitiveNotificationsFromUntrustedListeners()
+                        || mTrustedListenerUids.contains(uid);
+            }
+        }
+
         /**
          * Synchronously grant or revoke permissions to Uris for all active and visible
          * notifications to just the NotificationListenerService provided.
@@ -11915,6 +12156,8 @@
             // NOTE: this copy is lightweight: it doesn't include heavyweight parts of the
             // notification
             final StatusBarNotification sbnLight = sbn.cloneLight();
+            StatusBarNotification redactedSbn = null;
+            boolean hasSensitiveContent = hasSensitiveContent(r);
             for (final ManagedServiceInfo info : getServices()) {
                 if (!isVisibleToListener(sbn, r.getNotificationType(), info)) {
                     continue;
@@ -11934,11 +12177,18 @@
                     continue;
                 }
 
+                boolean sendRedacted = redactSensitiveNotificationsFromUntrustedListeners()
+                        && hasSensitiveContent && !isUidTrusted(info.uid);
+                if (sendRedacted && redactedSbn == null) {
+                    redactedSbn = redactStatusBarNotification(sbn);
+                }
+
                 // Only assistants can get stats
                 final NotificationStats stats = mAssistants.isServiceTokenValidLocked(info.service)
                         ? notificationStats : null;
+                final StatusBarNotification sbnToSend = sendRedacted ? redactedSbn : sbnLight;
                 final NotificationRankingUpdate update = makeRankingUpdateLocked(info);
-                mHandler.post(() -> notifyRemoved(info, sbnLight, update, stats, reason));
+                mHandler.post(() -> notifyRemoved(info, sbnToSend, update, stats, reason));
             }
 
             // Revoke access after all listeners have been updated
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 6a7eebb..1bafcfe 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -59,6 +59,7 @@
 import android.service.notification.ConversationChannelWrapper;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.RankingHelperProto;
+import android.service.notification.ZenModeConfig;
 import android.text.TextUtils;
 import android.text.format.DateUtils;
 import android.util.ArrayMap;
@@ -160,7 +161,6 @@
     static final boolean DEFAULT_BUBBLES_ENABLED = true;
     @VisibleForTesting
     static final int DEFAULT_BUBBLE_PREFERENCE = BUBBLE_PREFERENCE_NONE;
-    static final boolean DEFAULT_MEDIA_NOTIFICATION_FILTERING = true;
 
     private static final int NOTIFICATION_UPDATE_LOG_SUBTYPE_FROM_APP = 0;
     private static final int NOTIFICATION_UPDATE_LOG_SUBTYPE_FROM_USER = 1;
@@ -199,7 +199,7 @@
     private SparseBooleanArray mBubblesEnabled;
     private SparseBooleanArray mLockScreenShowNotifications;
     private SparseBooleanArray mLockScreenPrivateNotifications;
-    private boolean mIsMediaNotificationFilteringEnabled = DEFAULT_MEDIA_NOTIFICATION_FILTERING;
+    private boolean mIsMediaNotificationFilteringEnabled;
     // When modes_api flag is enabled, this value only tracks whether the current user has any
     // channels marked as "priority channels", but not necessarily whether they are permitted
     // to bypass DND by current zen policy.
@@ -223,6 +223,8 @@
         mAppOps = appOpsManager;
         mUserProfiles = userProfiles;
         mShowReviewPermissionsNotification = showReviewPermissionsNotification;
+        mIsMediaNotificationFilteringEnabled = context.getResources()
+                .getBoolean(R.bool.config_quickSettingsShowMediaPlayer);
 
         XML_VERSION = 4;
 
@@ -1862,12 +1864,16 @@
     public void updateZenPolicy(boolean areChannelsBypassingDnd, int callingUid,
             boolean fromSystemOrSystemUi) {
         NotificationManager.Policy policy = mZenModeHelper.getNotificationPolicy();
-        mZenModeHelper.setNotificationPolicy(new NotificationManager.Policy(
-                policy.priorityCategories, policy.priorityCallSenders,
-                policy.priorityMessageSenders, policy.suppressedVisualEffects,
-                (areChannelsBypassingDnd ? NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND
-                        : 0),
-                policy.priorityConversationSenders), callingUid, fromSystemOrSystemUi);
+        mZenModeHelper.setNotificationPolicy(
+                new NotificationManager.Policy(
+                        policy.priorityCategories, policy.priorityCallSenders,
+                        policy.priorityMessageSenders, policy.suppressedVisualEffects,
+                        (areChannelsBypassingDnd
+                                ? NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND : 0),
+                        policy.priorityConversationSenders),
+                fromSystemOrSystemUi ? ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI
+                        : ZenModeConfig.UPDATE_ORIGIN_APP,
+                callingUid);
     }
 
     // TODO: b/310620812 - rename to hasPriorityChannels() when modes_api is inlined.
@@ -2687,8 +2693,11 @@
 
     /** Requests check of the feature setting for showing media notifications in quick settings. */
     public void updateMediaNotificationFilteringEnabled() {
+        // TODO(b/192412820): Consolidate SHOW_MEDIA_ON_QUICK_SETTINGS into compile-time value.
         final boolean newValue = Settings.Global.getInt(mContext.getContentResolver(),
-                Settings.Global.SHOW_MEDIA_ON_QUICK_SETTINGS, 1) > 0;
+                Settings.Global.SHOW_MEDIA_ON_QUICK_SETTINGS, 1) > 0
+                        && mContext.getResources().getBoolean(
+                                R.bool.config_quickSettingsShowMediaPlayer);
         if (newValue != mIsMediaNotificationFilteringEnabled) {
             mIsMediaNotificationFilteringEnabled = newValue;
             updateConfig();
diff --git a/services/core/java/com/android/server/notification/ZenModeConditions.java b/services/core/java/com/android/server/notification/ZenModeConditions.java
index 6ecd799..86aa2d8 100644
--- a/services/core/java/com/android/server/notification/ZenModeConditions.java
+++ b/services/core/java/com/android/server/notification/ZenModeConditions.java
@@ -111,8 +111,10 @@
     public void onServiceAdded(ComponentName component) {
         if (DEBUG) Log.d(TAG, "onServiceAdded " + component);
         final int callingUid = Binder.getCallingUid();
-        mHelper.setConfig(mHelper.getConfig(), component, "zmc.onServiceAdded:" + component,
-                callingUid, callingUid == Process.SYSTEM_UID);
+        mHelper.setConfig(mHelper.getConfig(), component,
+                callingUid == Process.SYSTEM_UID ? ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI
+                        : ZenModeConfig.UPDATE_ORIGIN_APP,
+                "zmc.onServiceAdded:" + component, callingUid);
     }
 
     @Override
@@ -121,8 +123,10 @@
         ZenModeConfig config = mHelper.getConfig();
         if (config == null) return;
         final int callingUid = Binder.getCallingUid();
-        mHelper.setAutomaticZenRuleState(id, condition, callingUid,
-                callingUid == Process.SYSTEM_UID);
+        mHelper.setAutomaticZenRuleState(id, condition,
+                callingUid == Process.SYSTEM_UID ? ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI
+                        : ZenModeConfig.UPDATE_ORIGIN_APP,
+                callingUid);
     }
 
     // Only valid for CPS backed rules
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 218519f..3f8b595 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2014, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -24,11 +24,16 @@
 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_UNKNOWN;
 import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_ANY;
 import static android.service.notification.NotificationServiceProto.ROOT_CONFIG;
+import static android.service.notification.ZenModeConfig.UPDATE_ORIGIN_APP;
+import static android.service.notification.ZenModeConfig.UPDATE_ORIGIN_INIT;
+import static android.service.notification.ZenModeConfig.UPDATE_ORIGIN_INIT_USER;
+import static android.service.notification.ZenModeConfig.UPDATE_ORIGIN_RESTORE_BACKUP;
+import static android.service.notification.ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI;
+import static android.service.notification.ZenModeConfig.UPDATE_ORIGIN_USER;
 
 import static com.android.internal.util.FrameworkStatsLog.DND_MODE_RULE;
 
 import android.annotation.DrawableRes;
-import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SuppressLint;
@@ -79,6 +84,7 @@
 import android.service.notification.DeviceEffectsApplier;
 import android.service.notification.ZenDeviceEffects;
 import android.service.notification.ZenModeConfig;
+import android.service.notification.ZenModeConfig.ConfigChangeOrigin;
 import android.service.notification.ZenModeConfig.ZenRule;
 import android.service.notification.ZenModeProto;
 import android.service.notification.ZenPolicy;
@@ -111,8 +117,6 @@
 
 import java.io.IOException;
 import java.io.PrintWriter;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -137,21 +141,6 @@
     @EnabledSince(targetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM)
     static final long SEND_ACTIVATION_AZR_STATUSES = 308673617L;
 
-    /** A rule addition or update that is initiated by the System or SystemUI. */
-    static final int FROM_SYSTEM_OR_SYSTEMUI = 1;
-    /** A rule addition or update that is initiated by the user (through system settings). */
-    static final int FROM_USER = 2;
-    /** A rule addition or update that is initiated by an app (via NotificationManager APIs). */
-    static final int FROM_APP = 3;
-
-    @IntDef(prefix = { "FROM_" }, value = {
-            FROM_SYSTEM_OR_SYSTEMUI,
-            FROM_USER,
-            FROM_APP
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    @interface ChangeOrigin {}
-
     // pkg|userId => uid
     @VisibleForTesting protected final ArrayMap<String, Integer> mRulesUidCache = new ArrayMap<>();
 
@@ -160,7 +149,7 @@
     private final SettingsObserver mSettingsObserver;
     private final AppOpsManager mAppOps;
     private final NotificationManager mNotificationManager;
-    private ZenModeConfig mDefaultConfig;
+    private final ZenModeConfig mDefaultConfig;
     private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
     private final ZenModeFiltering mFiltering;
     private final RingerModeDelegate mRingerModeDelegate = new
@@ -275,9 +264,8 @@
             // "update" config to itself, which will have no effect in the case where a config
             // was read in via XML, but will initialize zen mode if nothing was read in and the
             // config remains the default.
-            updateConfigAndZenModeLocked(mConfig, "init", true /*setRingerMode*/,
-                    Process.SYSTEM_UID /* callingUid */, true /* is system */,
-                    false /* no broadcasts*/);
+            updateConfigAndZenModeLocked(mConfig, UPDATE_ORIGIN_INIT, "init",
+                    true /*setRingerMode*/, Process.SYSTEM_UID /* callingUid */);
         }
     }
 
@@ -297,24 +285,20 @@
     /**
      * Set the {@link DeviceEffectsApplier} used to apply the consolidated effects.
      *
-     * <p>If effects were calculated previously (for example, when we loaded a {@link ZenModeConfig}
-     * that includes activated rules), they will be applied immediately.
+     * <p>Previously calculated effects (as loaded from the user's {@link ZenModeConfig}) will be
+     * applied immediately.
      */
     void setDeviceEffectsApplier(@NonNull DeviceEffectsApplier deviceEffectsApplier) {
         if (!Flags.modesApi()) {
             return;
         }
-        ZenDeviceEffects consolidatedDeviceEffects;
         synchronized (mConfigLock) {
             if (mDeviceEffectsApplier != null) {
                 throw new IllegalStateException("Already set up a DeviceEffectsApplier!");
             }
             mDeviceEffectsApplier = deviceEffectsApplier;
-            consolidatedDeviceEffects = mConsolidatedDeviceEffects;
         }
-        if (consolidatedDeviceEffects.hasEffects()) {
-            applyConsolidatedDeviceEffects();
-        }
+        applyConsolidatedDeviceEffects(UPDATE_ORIGIN_INIT);
     }
 
     public void onUserSwitched(int user) {
@@ -353,7 +337,8 @@
             config.user = user;
         }
         synchronized (mConfigLock) {
-            setConfigLocked(config, null, reason, Process.SYSTEM_UID, true);
+            setConfigLocked(config, null, UPDATE_ORIGIN_INIT_USER, reason,
+                    Process.SYSTEM_UID);
         }
         cleanUpZenRules();
     }
@@ -366,9 +351,11 @@
             boolean fromSystemOrSystemUi) {
         final int newZen = NotificationManager.zenModeFromInterruptionFilter(filter, -1);
         if (newZen != -1) {
-            setManualZenMode(newZen, null, name != null ? name.getPackageName() : null,
-                    "listener:" + (name != null ? name.flattenToShortString() : null),
-                    callingUid, fromSystemOrSystemUi);
+            setManualZenMode(newZen, null,
+                    fromSystemOrSystemUi ? UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI : UPDATE_ORIGIN_APP,
+                    /* reason= */ "listener:" + (name != null ? name.flattenToShortString() : null),
+                    /* caller= */ name != null ? name.getPackageName() : null,
+                    callingUid);
         }
     }
 
@@ -428,7 +415,7 @@
     }
 
     public String addAutomaticZenRule(String pkg, AutomaticZenRule automaticZenRule,
-            String reason, int callingUid, @ChangeOrigin int origin) {
+            @ConfigChangeOrigin int origin, String reason, int callingUid) {
         if (!ZenModeConfig.SYSTEM_AUTHORITY.equals(pkg)) {
             PackageItemInfo component = getServiceInfo(automaticZenRule.getOwner());
             if (component == null) {
@@ -462,10 +449,9 @@
             }
             newConfig = mConfig.copy();
             ZenRule rule = new ZenRule();
-            populateZenRule(pkg, automaticZenRule, rule, true, origin);
+            populateZenRule(pkg, automaticZenRule, rule, origin, /* isNew= */ true);
             newConfig.automaticRules.put(rule.id, rule);
-            if (setConfigLocked(newConfig, reason, rule.component, true, callingUid,
-                    origin == FROM_SYSTEM_OR_SYSTEMUI)) {
+            if (setConfigLocked(newConfig, origin, reason, rule.component, true, callingUid)) {
                 return rule.id;
             } else {
                 throw new AndroidRuntimeException("Could not create rule");
@@ -474,7 +460,7 @@
     }
 
     public boolean updateAutomaticZenRule(String ruleId, AutomaticZenRule automaticZenRule,
-            String reason, int callingUid, @ChangeOrigin int origin) {
+            @ConfigChangeOrigin int origin, String reason, int callingUid) {
         ZenModeConfig newConfig;
         synchronized (mConfigLock) {
             if (mConfig == null) return false;
@@ -502,9 +488,9 @@
                 }
             }
 
-            populateZenRule(rule.pkg, automaticZenRule, rule, false, origin);
-            return setConfigLocked(newConfig, reason, rule.component, true, callingUid,
-                    origin == FROM_SYSTEM_OR_SYSTEMUI);
+            populateZenRule(rule.pkg, automaticZenRule, rule, origin, /* isNew= */ false);
+            return setConfigLocked(newConfig, origin, reason,
+                    rule.component, true, callingUid);
         }
     }
 
@@ -541,8 +527,7 @@
                     Condition deactivated = new Condition(rule.conditionId,
                             mContext.getString(R.string.zen_mode_implicit_deactivated),
                             Condition.STATE_FALSE);
-                    setAutomaticZenRuleState(rule.id, deactivated,
-                            callingUid, /* fromSystemOrSystemUi= */ false);
+                    setAutomaticZenRuleState(rule.id, deactivated, UPDATE_ORIGIN_APP, callingUid);
                 }
             } else {
                 // Either create a new rule with a default ZenPolicy, or update an existing rule's
@@ -558,9 +543,8 @@
                 rule.condition = new Condition(rule.conditionId,
                         mContext.getString(R.string.zen_mode_implicit_activated),
                         Condition.STATE_TRUE);
-                setConfigLocked(newConfig, /* triggeringComponent= */ null,
-                        "applyGlobalZenModeAsImplicitZenRule",
-                        callingUid, /* fromSystemOrSystemUi= */ false);
+                setConfigLocked(newConfig, /* triggeringComponent= */ null, UPDATE_ORIGIN_APP,
+                        "applyGlobalZenModeAsImplicitZenRule", callingUid);
             }
         }
     }
@@ -595,9 +579,8 @@
             }
             // TODO: b/308673679 - Keep user customization of this rule!
             rule.zenPolicy = ZenAdapters.notificationPolicyToZenPolicy(policy);
-            setConfigLocked(newConfig, /* triggeringComponent= */ null,
-                    "applyGlobalPolicyAsImplicitZenRule",
-                    callingUid, /* fromSystemOrSystemUi= */ false);
+            setConfigLocked(newConfig, /* triggeringComponent= */ null, UPDATE_ORIGIN_APP,
+                    "applyGlobalPolicyAsImplicitZenRule", callingUid);
         }
     }
 
@@ -644,6 +627,7 @@
             try {
                 ApplicationInfo applicationInfo = mPm.getApplicationInfo(pkg, 0);
                 rule.name = applicationInfo.loadLabel(mPm).toString();
+                rule.iconResName = drawableResIdToResName(pkg, applicationInfo.icon);
             } catch (PackageManager.NameNotFoundException e) {
                 // Should not happen, since it's the app calling us (?)
                 Log.w(TAG, "Package not found for creating implicit zen rule");
@@ -651,6 +635,9 @@
             }
         });
 
+        rule.type = AutomaticZenRule.TYPE_OTHER;
+        rule.triggerDescription = mContext.getString(R.string.zen_mode_implicit_trigger_description,
+                rule.name);
         rule.condition = null;
         rule.conditionId = new Uri.Builder()
                 .scheme(Condition.SCHEME)
@@ -669,8 +656,8 @@
         return "implicit_" + forPackage;
     }
 
-    public boolean removeAutomaticZenRule(String id, String reason, int callingUid,
-            boolean fromSystemOrSystemUi) {
+    boolean removeAutomaticZenRule(String id, @ConfigChangeOrigin int origin, String reason,
+            int callingUid) {
         ZenModeConfig newConfig;
         synchronized (mConfigLock) {
             if (mConfig == null) return false;
@@ -695,13 +682,12 @@
             }
             dispatchOnAutomaticRuleStatusChanged(
                     mConfig.user, ruleToRemove.getPkg(), id, AUTOMATIC_RULE_STATUS_REMOVED);
-            return setConfigLocked(newConfig, reason, null, true, callingUid,
-                    fromSystemOrSystemUi);
+            return setConfigLocked(newConfig, origin, reason, null, true, callingUid);
         }
     }
 
-    public boolean removeAutomaticZenRules(String packageName, String reason, int callingUid,
-            boolean fromSystemOrSystemUi) {
+    boolean removeAutomaticZenRules(String packageName, @ConfigChangeOrigin int origin,
+            String reason, int callingUid) {
         ZenModeConfig newConfig;
         synchronized (mConfigLock) {
             if (mConfig == null) return false;
@@ -712,13 +698,12 @@
                     newConfig.automaticRules.removeAt(i);
                 }
             }
-            return setConfigLocked(newConfig, reason, null, true, callingUid,
-                    fromSystemOrSystemUi);
+            return setConfigLocked(newConfig, origin, reason, null, true, callingUid);
         }
     }
 
-    public void setAutomaticZenRuleState(String id, Condition condition, int callingUid,
-            boolean fromSystemOrSystemUi) {
+    void setAutomaticZenRuleState(String id, Condition condition, @ConfigChangeOrigin int origin,
+            int callingUid) {
         ZenModeConfig newConfig;
         synchronized (mConfigLock) {
             if (mConfig == null) return;
@@ -726,13 +711,12 @@
             newConfig = mConfig.copy();
             ArrayList<ZenRule> rules = new ArrayList<>();
             rules.add(newConfig.automaticRules.get(id));
-            setAutomaticZenRuleStateLocked(newConfig, rules, condition, callingUid,
-                    fromSystemOrSystemUi);
+            setAutomaticZenRuleStateLocked(newConfig, rules, condition, origin, callingUid);
         }
     }
 
-    public void setAutomaticZenRuleState(Uri ruleDefinition, Condition condition, int callingUid,
-            boolean fromSystemOrSystemUi) {
+    void setAutomaticZenRuleState(Uri ruleDefinition, Condition condition,
+            @ConfigChangeOrigin int origin, int callingUid) {
         ZenModeConfig newConfig;
         synchronized (mConfigLock) {
             if (mConfig == null) return;
@@ -740,20 +724,23 @@
 
             setAutomaticZenRuleStateLocked(newConfig,
                     findMatchingRules(newConfig, ruleDefinition, condition),
-                    condition, callingUid, fromSystemOrSystemUi);
+                    condition, origin, callingUid);
         }
     }
 
     @GuardedBy("mConfigLock")
     private void setAutomaticZenRuleStateLocked(ZenModeConfig config, List<ZenRule> rules,
-            Condition condition, int callingUid, boolean fromSystemOrSystemUi) {
+            Condition condition, @ConfigChangeOrigin int origin, int callingUid) {
         if (rules == null || rules.isEmpty()) return;
 
+        if (Flags.modesApi() && condition.source == Condition.SOURCE_USER_ACTION) {
+            origin = UPDATE_ORIGIN_USER; // Although coming from app, it's actually a user action.
+        }
+
         for (ZenRule rule : rules) {
             rule.condition = condition;
             updateSnoozing(rule);
-            setConfigLocked(config, rule.component, "conditionChanged", callingUid,
-                    fromSystemOrSystemUi);
+            setConfigLocked(config, rule.component, origin, "conditionChanged", callingUid);
         }
     }
 
@@ -857,7 +844,7 @@
                         // update default rule (if locale changed, name of rule will change)
                         currRule.name = defaultRule.name;
                         updateAutomaticZenRule(defaultRule.id, zenRuleToAutomaticZenRule(currRule),
-                                "locale changed", callingUid, FROM_SYSTEM_OR_SYSTEMUI);
+                                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "locale changed", callingUid);
                     }
                 }
             }
@@ -899,13 +886,12 @@
         return null;
     }
 
-    @VisibleForTesting
     void populateZenRule(String pkg, AutomaticZenRule automaticZenRule, ZenRule rule,
-            boolean isNew, @ChangeOrigin int origin) {
-            // TODO: b/308671593,b/311406021 - Handle origins more precisely:
-            //  - FROM_USER can override anything and updates bitmask of user-modified fields;
-            //  - FROM_SYSTEM_OR_SYSTEMUI can override anything and preserves bitmask;
-            //  - FROM_APP can only update if not user-modified.
+            @ConfigChangeOrigin int origin, boolean isNew) {
+        // TODO: b/308671593,b/311406021 - Handle origins more precisely:
+        //  - USER can override anything and updates bitmask of user-modified fields;
+        //  - SYSTEM_OR_SYSTEMUI can override anything and preserves bitmask;
+        //  - APP can only update if not user-modified.
         if (rule.enabled != automaticZenRule.isEnabled()) {
             rule.snoozing = false;
         }
@@ -951,12 +937,12 @@
      */
     @Nullable
     private static ZenDeviceEffects fixZenDeviceEffects(@Nullable ZenDeviceEffects oldEffects,
-            @Nullable ZenDeviceEffects newEffects, @ChangeOrigin int origin) {
+            @Nullable ZenDeviceEffects newEffects, @ConfigChangeOrigin int origin) {
         // TODO: b/308671593,b/311406021 - Handle origins more precisely:
-        //  - FROM_USER can override anything and updates bitmask of user-modified fields;
-        //  - FROM_SYSTEM_OR_SYSTEMUI can override anything and preserves bitmask;
-        //  - FROM_APP can only update if not user-modified.
-        if (origin == FROM_SYSTEM_OR_SYSTEMUI || origin == FROM_USER) {
+        //  - USER can override anything and updates bitmask of user-modified fields;
+        //  - SYSTEM_OR_SYSTEMUI can override anything and preserves bitmask;
+        //  - APP can only update if not user-modified.
+        if (origin != UPDATE_ORIGIN_APP) {
             return newEffects;
         }
 
@@ -1033,16 +1019,16 @@
                 : AUTOMATIC_RULE_STATUS_DISABLED);
     }
 
-    public void setManualZenMode(int zenMode, Uri conditionId, String caller, String reason,
-            int callingUid, boolean fromSystemOrSystemUi) {
-        setManualZenMode(zenMode, conditionId, reason, caller, true /*setRingerMode*/, callingUid,
-                fromSystemOrSystemUi);
+    void setManualZenMode(int zenMode, Uri conditionId, @ConfigChangeOrigin int origin,
+            String reason, @Nullable String caller, int callingUid) {
+        setManualZenMode(zenMode, conditionId, origin, reason, caller, true /*setRingerMode*/,
+                callingUid);
         Settings.Secure.putInt(mContext.getContentResolver(),
                 Settings.Secure.SHOW_ZEN_SETTINGS_SUGGESTION, 0);
     }
 
-    private void setManualZenMode(int zenMode, Uri conditionId, String reason, String caller,
-            boolean setRingerMode, int callingUid, boolean fromSystemOrSystemUi) {
+    private void setManualZenMode(int zenMode, Uri conditionId, @ConfigChangeOrigin int origin,
+            String reason, @Nullable String caller, boolean setRingerMode, int callingUid) {
         ZenModeConfig newConfig;
         synchronized (mConfigLock) {
             if (mConfig == null) return;
@@ -1069,8 +1055,7 @@
                 }
                 newConfig.manualRule = newRule;
             }
-            setConfigLocked(newConfig, reason, null, setRingerMode, callingUid,
-                    fromSystemOrSystemUi);
+            setConfigLocked(newConfig, origin, reason, null, setRingerMode, callingUid);
         }
     }
 
@@ -1199,7 +1184,9 @@
             }
             if (DEBUG) Log.d(TAG, reason);
             synchronized (mConfigLock) {
-                setConfigLocked(config, null, reason, Process.SYSTEM_UID, true);
+                setConfigLocked(config, null,
+                        forRestore ? UPDATE_ORIGIN_RESTORE_BACKUP : UPDATE_ORIGIN_INIT, reason,
+                        Process.SYSTEM_UID);
             }
         }
     }
@@ -1233,13 +1220,13 @@
     /**
      * Sets the global notification policy used for priority only do not disturb
      */
-    public void setNotificationPolicy(Policy policy, int callingUid, boolean fromSystemOrSystemUi) {
+    public void setNotificationPolicy(Policy policy, @ConfigChangeOrigin int origin,
+            int callingUid) {
         synchronized (mConfigLock) {
             if (policy == null || mConfig == null) return;
             final ZenModeConfig newConfig = mConfig.copy();
             newConfig.applyNotificationPolicy(policy);
-            setConfigLocked(newConfig, null, "setNotificationPolicy", callingUid,
-                    fromSystemOrSystemUi);
+            setConfigLocked(newConfig, null, origin, "setNotificationPolicy", callingUid);
         }
     }
 
@@ -1264,8 +1251,8 @@
                     }
                 }
             }
-            setConfigLocked(newConfig, null, "cleanUpZenRules", Process.SYSTEM_UID,
-                    true);
+            setConfigLocked(newConfig, null, UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "cleanUpZenRules",
+                    Process.SYSTEM_UID);
         }
     }
 
@@ -1287,22 +1274,22 @@
 
     @GuardedBy("mConfigLock")
     private boolean setConfigLocked(ZenModeConfig config, ComponentName triggeringComponent,
-            String reason, int callingUid, boolean fromSystemOrSystemUi) {
-        return setConfigLocked(config, reason, triggeringComponent, true /*setRingerMode*/,
-                callingUid, fromSystemOrSystemUi);
+            @ConfigChangeOrigin int origin, String reason, int callingUid) {
+        return setConfigLocked(config, origin, reason, triggeringComponent, true /*setRingerMode*/,
+                callingUid);
     }
 
-    public void setConfig(ZenModeConfig config, ComponentName triggeringComponent, String reason,
-            int callingUid, boolean fromSystemOrSystemUi) {
+    void setConfig(ZenModeConfig config, ComponentName triggeringComponent,
+            @ConfigChangeOrigin int origin, String reason, int callingUid) {
         synchronized (mConfigLock) {
-            setConfigLocked(config, triggeringComponent, reason, callingUid, fromSystemOrSystemUi);
+            setConfigLocked(config, triggeringComponent, origin, reason, callingUid);
         }
     }
 
     @GuardedBy("mConfigLock")
-    private boolean setConfigLocked(ZenModeConfig config, String reason,
-            ComponentName triggeringComponent, boolean setRingerMode, int callingUid,
-            boolean fromSystemOrSystemUi) {
+    private boolean setConfigLocked(ZenModeConfig config, @ConfigChangeOrigin int origin,
+            String reason, ComponentName triggeringComponent, boolean setRingerMode,
+            int callingUid) {
         final long identity = Binder.clearCallingIdentity();
         try {
             if (config == null || !config.isValid()) {
@@ -1332,8 +1319,7 @@
             if (policyChanged) {
                 dispatchOnPolicyChanged();
             }
-            updateConfigAndZenModeLocked(config, reason, setRingerMode, callingUid,
-                    fromSystemOrSystemUi, true);
+            updateConfigAndZenModeLocked(config, origin, reason, setRingerMode, callingUid);
             mConditions.evaluateConfig(config, triggeringComponent, true /*processSubscriptions*/);
             return true;
         } catch (SecurityException e) {
@@ -1349,17 +1335,16 @@
      * If logging is enabled, will also request logging of the outcome of this change if needed.
      */
     @GuardedBy("mConfigLock")
-    private void updateConfigAndZenModeLocked(ZenModeConfig config, String reason,
-            boolean setRingerMode, int callingUid, boolean fromSystemOrSystemUi,
-            boolean sendBroadcasts) {
+    private void updateConfigAndZenModeLocked(ZenModeConfig config, @ConfigChangeOrigin int origin,
+            String reason, boolean setRingerMode, int callingUid) {
         final boolean logZenModeEvents = mFlagResolver.isEnabled(
                 SystemUiSystemPropertiesFlags.NotificationFlags.LOG_DND_STATE_EVENTS);
         // Store (a copy of) all config and zen mode info prior to any changes taking effect
         ZenModeEventLogger.ZenModeInfo prevInfo = new ZenModeEventLogger.ZenModeInfo(
                 mZenMode, mConfig, mConsolidatedPolicy);
         if (!config.equals(mConfig)) {
-            // schedule broadcasts
-            if (Flags.modesApi() && sendBroadcasts) {
+            // Schedule broadcasts. Cannot be sent during boot, though.
+            if (Flags.modesApi() && origin != UPDATE_ORIGIN_INIT) {
                 for (ZenRule rule : config.automaticRules.values()) {
                     ZenRule original = mConfig.automaticRules.get(rule.id);
                     if (original != null) {
@@ -1377,15 +1362,19 @@
 
             mConfig = config;
             dispatchOnConfigChanged();
-            updateAndApplyConsolidatedPolicyAndDeviceEffects(reason);
+            updateAndApplyConsolidatedPolicyAndDeviceEffects(origin, reason);
         }
         final String val = Integer.toString(config.hashCode());
         Global.putString(mContext.getContentResolver(), Global.ZEN_MODE_CONFIG_ETAG, val);
-        evaluateZenModeLocked(reason, setRingerMode);
+        evaluateZenModeLocked(origin, reason, setRingerMode);
         // After all changes have occurred, log if requested
         if (logZenModeEvents) {
             ZenModeEventLogger.ZenModeInfo newInfo = new ZenModeEventLogger.ZenModeInfo(
                     mZenMode, mConfig, mConsolidatedPolicy);
+            boolean fromSystemOrSystemUi = origin == UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI
+                    || origin == UPDATE_ORIGIN_INIT
+                    || origin == UPDATE_ORIGIN_INIT_USER
+                    || origin == UPDATE_ORIGIN_RESTORE_BACKUP;
             mZenModeEventLogger.maybeLogZenChange(prevInfo, newInfo, callingUid,
                     fromSystemOrSystemUi);
         }
@@ -1416,7 +1405,8 @@
 
     @VisibleForTesting
     @GuardedBy("mConfigLock")
-    protected void evaluateZenModeLocked(String reason, boolean setRingerMode) {
+    protected void evaluateZenModeLocked(@ConfigChangeOrigin int origin, String reason,
+            boolean setRingerMode) {
         if (DEBUG) Log.d(TAG, "evaluateZenMode");
         if (mConfig == null) return;
         final int policyHashBefore = mConsolidatedPolicy == null ? 0
@@ -1426,7 +1416,7 @@
         ZenLog.traceSetZenMode(zen, reason);
         mZenMode = zen;
         setZenModeSetting(mZenMode);
-        updateAndApplyConsolidatedPolicyAndDeviceEffects(reason);
+        updateAndApplyConsolidatedPolicyAndDeviceEffects(origin, reason);
         boolean shouldApplyToRinger = setRingerMode && (zen != zenBefore || (
                 zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
                         && policyHashBefore != mConsolidatedPolicy.hashCode()));
@@ -1468,6 +1458,7 @@
         }
     }
 
+    @GuardedBy("mConfigLock")
     private void applyCustomPolicy(ZenPolicy policy, ZenRule rule) {
         if (rule.zenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) {
             policy.apply(new ZenPolicy.Builder()
@@ -1487,7 +1478,9 @@
         }
     }
 
-    private void updateAndApplyConsolidatedPolicyAndDeviceEffects(String reason) {
+    @GuardedBy("mConfigLock")
+    private void updateAndApplyConsolidatedPolicyAndDeviceEffects(@ConfigChangeOrigin int origin,
+            String reason) {
         synchronized (mConfigLock) {
             if (mConfig == null) return;
             ZenPolicy policy = new ZenPolicy();
@@ -1519,13 +1512,13 @@
                 ZenDeviceEffects deviceEffects = deviceEffectsBuilder.build();
                 if (!deviceEffects.equals(mConsolidatedDeviceEffects)) {
                     mConsolidatedDeviceEffects = deviceEffects;
-                    mHandler.postApplyDeviceEffects();
+                    mHandler.postApplyDeviceEffects(origin);
                 }
             }
         }
     }
 
-    private void applyConsolidatedDeviceEffects() {
+    private void applyConsolidatedDeviceEffects(@ConfigChangeOrigin int source) {
         if (!Flags.modesApi()) {
             return;
         }
@@ -1536,7 +1529,7 @@
             effects = mConsolidatedDeviceEffects;
         }
         if (applier != null) {
-            applier.apply(effects);
+            applier.apply(effects, source);
         }
     }
 
@@ -1801,8 +1794,8 @@
         }
 
         @Override
-        public int onSetRingerModeInternal(int ringerModeOld, int ringerModeNew, String caller,
-                int ringerModeExternal, VolumePolicy policy) {
+        public int onSetRingerModeInternal(int ringerModeOld, int ringerModeNew,
+                @Nullable String caller, int ringerModeExternal, VolumePolicy policy) {
             final boolean isChange = ringerModeOld != ringerModeNew;
 
             int ringerModeExternalOut = ringerModeNew;
@@ -1839,8 +1832,9 @@
             }
 
             if (newZen != -1) {
-                setManualZenMode(newZen, null, "ringerModeInternal", null,
-                        false /*setRingerMode*/, Process.SYSTEM_UID, true);
+                setManualZenMode(newZen, null, UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI,
+                        "ringerModeInternal", /* caller= */ null, /* setRingerMode= */ false,
+                        Process.SYSTEM_UID);
             }
             if (isChange || newZen != -1 || ringerModeExternal != ringerModeExternalOut) {
                 ZenLog.traceSetRingerModeInternal(ringerModeOld, ringerModeNew, caller,
@@ -1856,8 +1850,8 @@
         }
 
         @Override
-        public int onSetRingerModeExternal(int ringerModeOld, int ringerModeNew, String caller,
-                int ringerModeInternal, VolumePolicy policy) {
+        public int onSetRingerModeExternal(int ringerModeOld, int ringerModeNew,
+                @Nullable String caller, int ringerModeInternal, VolumePolicy policy) {
             int ringerModeInternalOut = ringerModeNew;
             final boolean isChange = ringerModeOld != ringerModeNew;
             final boolean isVibrate = ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE;
@@ -1883,8 +1877,8 @@
                     break;
             }
             if (newZen != -1) {
-                setManualZenMode(newZen, null, "ringerModeExternal", caller,
-                        false /*setRingerMode*/, Process.SYSTEM_UID, true);
+                setManualZenMode(newZen, null, UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI,
+                        "ringerModeExternal", caller, false /*setRingerMode*/, Process.SYSTEM_UID);
             }
 
             ZenLog.traceSetRingerModeExternal(ringerModeOld, ringerModeNew, caller,
@@ -2024,11 +2018,9 @@
         }
         try {
             final Resources res = mPm.getResourcesForApplication(packageName);
-            final String fullName = res.getResourceName(resId);
-
-            return fullName;
+            return res.getResourceName(resId);
         } catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) {
-            Log.e(TAG, "Resource name for ID=" + resId + " not found in package " + packageName
+            Slog.e(TAG, "Resource name for ID=" + resId + " not found in package " + packageName
                     + ". Resource IDs may change when the application is upgraded, and the system"
                     + " may not be able to find the correct resource.");
             return null;
@@ -2149,9 +2141,9 @@
             sendMessage(obtainMessage(MSG_RINGER_AUDIO, shouldApplyToRinger));
         }
 
-        private void postApplyDeviceEffects() {
+        private void postApplyDeviceEffects(@ConfigChangeOrigin int origin) {
             removeMessages(MSG_APPLY_EFFECTS);
-            sendEmptyMessage(MSG_APPLY_EFFECTS);
+            sendMessage(obtainMessage(MSG_APPLY_EFFECTS, origin, 0));
         }
 
         @Override
@@ -2168,7 +2160,8 @@
                     updateRingerAndAudio(shouldApplyToRinger);
                     break;
                 case MSG_APPLY_EFFECTS:
-                    applyConsolidatedDeviceEffects();
+                    @ConfigChangeOrigin int origin = msg.arg1;
+                    applyConsolidatedDeviceEffects(origin);
                     break;
             }
         }
diff --git a/services/core/java/com/android/server/notification/flags.aconfig b/services/core/java/com/android/server/notification/flags.aconfig
index dcac8c9..da01745 100644
--- a/services/core/java/com/android/server/notification/flags.aconfig
+++ b/services/core/java/com/android/server/notification/flags.aconfig
@@ -20,3 +20,17 @@
   description: "This flag controls the refactoring of NMS to NotificationAttentionHelper"
   bug: "291907312"
 }
+
+flag {
+  name: "cross_app_polite_notifications"
+  namespace: "systemui"
+  description: "This flag controls the cross-app effect of polite notifications"
+  bug: "270456865"
+}
+
+flag {
+  name: "vibrate_while_unlocked"
+  namespace: "systemui"
+  description: "This flag controls the vibrate while unlocked setting of polite notifications"
+  bug: "270456865"
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/os/NativeTombstoneManager.java b/services/core/java/com/android/server/os/NativeTombstoneManager.java
index f6e7ef3..9ce3cb3 100644
--- a/services/core/java/com/android/server/os/NativeTombstoneManager.java
+++ b/services/core/java/com/android/server/os/NativeTombstoneManager.java
@@ -41,14 +41,13 @@
 import android.system.StructStat;
 import android.util.Slog;
 import android.util.SparseArray;
-import android.util.proto.ProtoInputStream;
-import android.util.proto.ProtoParseException;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.server.BootReceiver;
 import com.android.server.ServiceThread;
 import com.android.server.os.TombstoneProtos.Cause;
 import com.android.server.os.TombstoneProtos.Tombstone;
+import com.android.server.os.protobuf.CodedInputStream;
 
 import libcore.io.IoUtils;
 
@@ -130,18 +129,21 @@
             return;
         }
 
-        String processName = "UNKNOWN";
         final boolean isProtoFile = filename.endsWith(".pb");
-        File protoPath = isProtoFile ? path : new File(path.getAbsolutePath() + ".pb");
-
-        Optional<TombstoneFile> parsedTombstone = handleProtoTombstone(protoPath, isProtoFile);
-        if (parsedTombstone.isPresent()) {
-            processName = parsedTombstone.get().getProcessName();
+        if (!isProtoFile) {
+            return;
         }
-        BootReceiver.addTombstoneToDropBox(mContext, path, isProtoFile, processName, mTmpFileLock);
+
+        Optional<ParsedTombstone> parsedTombstone = handleProtoTombstone(path, true);
+        if (parsedTombstone.isPresent()) {
+            BootReceiver.addTombstoneToDropBox(
+                    mContext, path, parsedTombstone.get().getTombstone(),
+                    parsedTombstone.get().getProcessName(), mTmpFileLock);
+        }
     }
 
-    private Optional<TombstoneFile> handleProtoTombstone(File path, boolean addToList) {
+    private Optional<ParsedTombstone> handleProtoTombstone(
+            File path, boolean addToList) {
         final String filename = path.getName();
         if (!filename.endsWith(".pb")) {
             Slog.w(TAG, "unexpected tombstone name: " + path);
@@ -171,7 +173,7 @@
             return Optional.empty();
         }
 
-        final Optional<TombstoneFile> parsedTombstone = TombstoneFile.parse(pfd);
+        final Optional<ParsedTombstone> parsedTombstone = TombstoneFile.parse(pfd);
         if (!parsedTombstone.isPresent()) {
             IoUtils.closeQuietly(pfd);
             return Optional.empty();
@@ -184,7 +186,7 @@
                     previous.dispose();
                 }
 
-                mTombstones.put(number, parsedTombstone.get());
+                mTombstones.put(number, parsedTombstone.get().getTombstoneFile());
             }
         }
 
@@ -332,6 +334,27 @@
         }
     }
 
+    static class ParsedTombstone {
+        TombstoneFile mTombstoneFile;
+        Tombstone mTombstone;
+        ParsedTombstone(TombstoneFile tombstoneFile, Tombstone tombstone) {
+            mTombstoneFile = tombstoneFile;
+            mTombstone = tombstone;
+        }
+
+        public String getProcessName() {
+            return mTombstoneFile.getProcessName();
+        }
+
+        public TombstoneFile getTombstoneFile() {
+            return mTombstoneFile;
+        }
+
+        public Tombstone getTombstone() {
+            return mTombstone;
+        }
+    }
+
     static class TombstoneFile {
         final ParcelFileDescriptor mPfd;
 
@@ -414,67 +437,21 @@
             }
         }
 
-        static Optional<TombstoneFile> parse(ParcelFileDescriptor pfd) {
-            final FileInputStream is = new FileInputStream(pfd.getFileDescriptor());
-            final ProtoInputStream stream = new ProtoInputStream(is);
+        static Optional<ParsedTombstone> parse(ParcelFileDescriptor pfd) {
+            Tombstone tombstoneProto;
+            try (FileInputStream is = new FileInputStream(pfd.getFileDescriptor())) {
+                final byte[] tombstoneBytes = is.readAllBytes();
 
-            int pid = 0;
-            int uid = 0;
-            String processName = null;
-            String crashReason = "";
-            String selinuxLabel = "";
-
-            try {
-                while (stream.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
-                    switch (stream.getFieldNumber()) {
-                        case (int) Tombstone.PID:
-                            pid = stream.readInt(Tombstone.PID);
-                            break;
-
-                        case (int) Tombstone.UID:
-                            uid = stream.readInt(Tombstone.UID);
-                            break;
-
-                        case (int) Tombstone.COMMAND_LINE:
-                            if (processName == null) {
-                                processName = stream.readString(Tombstone.COMMAND_LINE);
-                            }
-                            break;
-
-                        case (int) Tombstone.CAUSES:
-                            if (!crashReason.equals("")) {
-                                // Causes appear in decreasing order of likelihood. For now we only
-                                // want the most likely crash reason here, so ignore all others.
-                                break;
-                            }
-                            long token = stream.start(Tombstone.CAUSES);
-                        cause:
-                            while (stream.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
-                                switch (stream.getFieldNumber()) {
-                                    case (int) Cause.HUMAN_READABLE:
-                                        crashReason = stream.readString(Cause.HUMAN_READABLE);
-                                        break cause;
-
-                                    default:
-                                        break;
-                                }
-                            }
-                            stream.end(token);
-                            break;
-
-                        case (int) Tombstone.SELINUX_LABEL:
-                            selinuxLabel = stream.readString(Tombstone.SELINUX_LABEL);
-                            break;
-
-                        default:
-                            break;
-                    }
-                }
-            } catch (IOException | ProtoParseException ex) {
+                tombstoneProto = Tombstone.parseFrom(
+                        CodedInputStream.newInstance(tombstoneBytes));
+            } catch (IOException ex) {
                 Slog.e(TAG, "Failed to parse tombstone", ex);
                 return Optional.empty();
             }
 
+            int pid = tombstoneProto.getPid();
+            int uid = tombstoneProto.getUid();
+
             if (!UserHandle.isApp(uid)) {
                 Slog.e(TAG, "Tombstone's UID (" + uid + ") not an app, ignoring");
                 return Optional.empty();
@@ -491,6 +468,7 @@
             final int userId = UserHandle.getUserId(uid);
             final int appId = UserHandle.getAppId(uid);
 
+            String selinuxLabel = tombstoneProto.getSelinuxLabel();
             if (!selinuxLabel.startsWith("u:r:untrusted_app")) {
                 Slog.e(TAG, "Tombstone has invalid selinux label (" + selinuxLabel + "), ignoring");
                 return Optional.empty();
@@ -502,11 +480,30 @@
             result.mAppId = appId;
             result.mPid = pid;
             result.mUid = uid;
-            result.mProcessName = processName == null ? "" : processName;
+            result.mProcessName = getCmdLineProcessName(tombstoneProto);
             result.mTimestampMs = timestampMs;
-            result.mCrashReason = crashReason;
+            result.mCrashReason = getCrashReason(tombstoneProto);
 
-            return Optional.of(result);
+            return Optional.of(new ParsedTombstone(result, tombstoneProto));
+        }
+
+        private static String getCmdLineProcessName(Tombstone tombstoneProto) {
+            for (String cmdline : tombstoneProto.getCommandLineList()) {
+                if (cmdline != null) {
+                    return cmdline;
+                }
+            }
+            return "";
+        }
+
+        private static String getCrashReason(Tombstone tombstoneProto) {
+            for (Cause cause : tombstoneProto.getCausesList()) {
+                if (cause.getHumanReadable() != null
+                        && !cause.getHumanReadable().equals("")) {
+                    return cause.getHumanReadable();
+                }
+            }
+            return "";
         }
 
         public IParcelFileDescriptorRetriever getPfdRetriever() {
diff --git a/services/core/java/com/android/server/pdb/PersistentDataBlockService.java b/services/core/java/com/android/server/pdb/PersistentDataBlockService.java
index f985b5b..b9b09fb 100644
--- a/services/core/java/com/android/server/pdb/PersistentDataBlockService.java
+++ b/services/core/java/com/android/server/pdb/PersistentDataBlockService.java
@@ -754,9 +754,9 @@
         }
     };
 
-    private PersistentDataBlockManagerInternal mInternalService =
-            new PersistentDataBlockManagerInternal() {
+    private InternalService mInternalService = new InternalService();
 
+    private class InternalService implements PersistentDataBlockManagerInternal {
         @Override
         public void setFrpCredentialHandle(byte[] handle) {
             writeInternal(handle, getFrpCredentialDataOffset(), MAX_FRP_CREDENTIAL_HANDLE_SIZE);
diff --git a/services/core/java/com/android/server/pm/AppDataHelper.java b/services/core/java/com/android/server/pm/AppDataHelper.java
index 167c17c..79d1753 100644
--- a/services/core/java/com/android/server/pm/AppDataHelper.java
+++ b/services/core/java/com/android/server/pm/AppDataHelper.java
@@ -17,6 +17,7 @@
 package com.android.server.pm;
 
 import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
+
 import static com.android.server.pm.PackageManagerService.TAG;
 import static com.android.server.pm.PackageManagerServiceUtils.getPackageManagerLocal;
 import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo;
@@ -25,7 +26,6 @@
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.content.pm.PackageManager;
-import android.content.pm.UserInfo;
 import android.os.CreateAppDataArgs;
 import android.os.Environment;
 import android.os.FileUtils;
@@ -49,7 +49,6 @@
 import com.android.server.pm.dex.ArtManagerService;
 import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
 import com.android.server.pm.pkg.AndroidPackage;
-import com.android.server.pm.pkg.PackageState;
 import com.android.server.pm.pkg.PackageStateInternal;
 import com.android.server.pm.pkg.SELinuxUtil;
 
@@ -57,6 +56,7 @@
 
 import java.io.File;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.Future;
@@ -93,25 +93,42 @@
      */
     @GuardedBy("mPm.mInstallLock")
     public void prepareAppDataAfterInstallLIF(AndroidPackage pkg) {
-        prepareAppDataPostCommitLIF(pkg, 0 /* previousAppId */);
+        final PackageSetting ps;
+        synchronized (mPm.mLock) {
+            ps = mPm.mSettings.getPackageLPr(pkg.getPackageName());
+        }
+
+        prepareAppDataPostCommitLIF(ps, 0 /* previousAppId */, getInstalledUsersForPackage(ps));
+    }
+
+    private int[] getInstalledUsersForPackage(PackageSetting ps) {
+        UserManagerInternal umInternal = mInjector.getUserManagerInternal();
+        var users = umInternal.getUsers(false /*excludeDying*/);
+        int[] userIds = new int[users.size()];
+        int userIdsCount = 0;
+        for (int i = 0, size = users.size(); i < size; ++i) {
+            int userId = users.get(i).id;
+            if (ps.getInstalled(userId)) {
+                userIds[userIdsCount++] = userId;
+            }
+        }
+        return Arrays.copyOf(userIds, userIdsCount);
     }
 
     /**
      * For more details about data verification and previousAppId, check
-     * {@link #prepareAppData(Installer.Batch, AndroidPackage, int, int, int)}
-     * @see #prepareAppDataAfterInstallLIF(AndroidPackage)
+     * {@link #prepareAppData}
+     * @see #prepareAppDataAfterInstallLIF
      */
     @GuardedBy("mPm.mInstallLock")
-    public void prepareAppDataPostCommitLIF(AndroidPackage pkg, int previousAppId) {
-        final PackageSetting ps;
+    public void prepareAppDataPostCommitLIF(PackageSetting ps, int previousAppId, int[] userIds) {
         synchronized (mPm.mLock) {
-            ps = mPm.mSettings.getPackageLPr(pkg.getPackageName());
             mPm.mSettings.writeKernelMappingLPr(ps);
         }
 
         // TODO(b/211761016): should we still create the profile dirs?
-        if (!shouldHaveAppStorage(pkg)) {
-            Slog.w(TAG, "Skipping preparing app data for " + pkg.getPackageName());
+        if (ps.getPkg() != null && !shouldHaveAppStorage(ps.getPkg())) {
+            Slog.w(TAG, "Skipping preparing app data for " + ps.getPackageName());
             return;
         }
 
@@ -119,31 +136,29 @@
         UserManagerInternal umInternal = mInjector.getUserManagerInternal();
         StorageManagerInternal smInternal = mInjector.getLocalService(
                 StorageManagerInternal.class);
-        for (UserInfo user : umInternal.getUsers(false /*excludeDying*/)) {
+        for (int userId : userIds) {
             final int flags;
-            if (StorageManager.isCeStorageUnlocked(user.id)
-                    && smInternal.isCeStoragePrepared(user.id)) {
+            if (StorageManager.isCeStorageUnlocked(userId)
+                    && smInternal.isCeStoragePrepared(userId)) {
                 flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
-            } else if (umInternal.isUserRunning(user.id)) {
+            } else if (umInternal.isUserRunning(userId)) {
                 flags = StorageManager.FLAG_STORAGE_DE;
             } else {
                 continue;
             }
 
-            if (ps.getInstalled(user.id)) {
-                // TODO: when user data is locked, mark that we're still dirty
-                prepareAppData(batch, pkg, previousAppId, user.id, flags).thenRun(() -> {
-                    // Note: this code block is executed with the Installer lock
-                    // already held, since it's invoked as a side-effect of
-                    // executeBatchLI()
-                    if (umInternal.isUserUnlockingOrUnlocked(user.id)) {
-                        // Prepare app data on external storage; currently this is used to
-                        // setup any OBB dirs that were created by the installer correctly.
-                        int uid = UserHandle.getUid(user.id, UserHandle.getAppId(pkg.getUid()));
-                        smInternal.prepareAppDataAfterInstall(pkg.getPackageName(), uid);
-                    }
-                });
-            }
+            // TODO: when user data is locked, mark that we're still dirty
+            prepareAppData(batch, ps, previousAppId, userId, flags).thenRun(() -> {
+                // Note: this code block is executed with the Installer lock
+                // already held, since it's invoked as a side-effect of
+                // executeBatchLI()
+                if (umInternal.isUserUnlockingOrUnlocked(userId)) {
+                    // Prepare app data on external storage; currently this is used to
+                    // setup any OBB dirs that were created by the installer correctly.
+                    int uid = UserHandle.getUid(userId, ps.getAppId());
+                    smInternal.prepareAppDataAfterInstall(ps.getPackageName(), uid);
+                }
+            });
         }
         executeBatchLI(batch);
     }
@@ -156,6 +171,35 @@
         }
     }
 
+    private void prepareAppDataAndMigrate(@NonNull Installer.Batch batch,
+            @NonNull AndroidPackage pkg, @UserIdInt int userId,
+            @StorageManager.StorageFlags int flags, boolean maybeMigrateAppData) {
+        if (pkg == null) {
+            Slog.wtf(TAG, "Package was null!", new Throwable());
+            return;
+        }
+        if (!shouldHaveAppStorage(pkg)) {
+            Slog.w(TAG, "Skipping preparing app data for " + pkg.getPackageName());
+            return;
+        }
+        final PackageSetting ps;
+        synchronized (mPm.mLock) {
+            ps = mPm.mSettings.getPackageLPr(pkg.getPackageName());
+        }
+        prepareAppData(batch, ps, Process.INVALID_UID, userId, flags).thenRun(() -> {
+            // Note: this code block is executed with the Installer lock
+            // already held, since it's invoked as a side-effect of
+            // executeBatchLI()
+            if (maybeMigrateAppData && maybeMigrateAppDataLIF(ps, userId)) {
+                // We may have just shuffled around app data directories, so
+                // prepare them one more time
+                final Installer.Batch batchInner = new Installer.Batch();
+                prepareAppData(batchInner, ps, Process.INVALID_UID, userId, flags);
+                executeBatchLI(batchInner);
+            }
+        });
+    }
+
     /**
      * Prepare app data for the given app.
      * <p>
@@ -168,61 +212,29 @@
      * </ul>
      */
     private @NonNull CompletableFuture<?> prepareAppData(@NonNull Installer.Batch batch,
-            @Nullable AndroidPackage pkg, int previousAppId, int userId,
-            @StorageManager.StorageFlags int flags) {
-        if (pkg == null) {
-            Slog.wtf(TAG, "Package was null!", new Throwable());
-            return CompletableFuture.completedFuture(null);
-        }
-        if (!shouldHaveAppStorage(pkg)) {
-            Slog.w(TAG, "Skipping preparing app data for " + pkg.getPackageName());
-            return CompletableFuture.completedFuture(null);
-        }
-        return prepareAppDataLeaf(batch, pkg, previousAppId, userId, flags);
-    }
+            @NonNull PackageSetting ps, int previousAppId, int userId, int flags) {
+        final String packageName = ps.getPackageName();
 
-    private void prepareAppDataAndMigrate(@NonNull Installer.Batch batch,
-            @NonNull PackageState packageState, @NonNull AndroidPackage pkg, @UserIdInt int userId,
-            @StorageManager.StorageFlags int flags, boolean maybeMigrateAppData) {
-        prepareAppData(batch, pkg, Process.INVALID_UID, userId, flags).thenRun(() -> {
-            // Note: this code block is executed with the Installer lock
-            // already held, since it's invoked as a side-effect of
-            // executeBatchLI()
-            if (maybeMigrateAppData && maybeMigrateAppDataLIF(packageState, pkg, userId)) {
-                // We may have just shuffled around app data directories, so
-                // prepare them one more time
-                final Installer.Batch batchInner = new Installer.Batch();
-                prepareAppData(batchInner, pkg, Process.INVALID_UID, userId, flags);
-                executeBatchLI(batchInner);
-            }
-        });
-    }
-
-    private @NonNull CompletableFuture<?> prepareAppDataLeaf(@NonNull Installer.Batch batch,
-            @NonNull AndroidPackage pkg, int previousAppId, int userId, int flags) {
         if (DEBUG_APP_DATA) {
-            Slog.v(TAG, "prepareAppData for " + pkg.getPackageName() + " u" + userId + " 0x"
+            Slog.v(TAG, "prepareAppData for " + packageName + " u" + userId + " 0x"
                     + Integer.toHexString(flags));
         }
 
-        final PackageSetting ps;
         final String seInfoUser;
         synchronized (mPm.mLock) {
-            ps = mPm.mSettings.getPackageLPr(pkg.getPackageName());
             seInfoUser = SELinuxUtil.getSeinfoUser(ps.readUserState(userId));
         }
-        final String volumeUuid = pkg.getVolumeUuid();
-        final String packageName = pkg.getPackageName();
 
-        final int appId = UserHandle.getAppId(pkg.getUid());
+        final AndroidPackage pkg = ps.getPkg();
+        final String volumeUuid = ps.getVolumeUuid();
+        final int appId = ps.getAppId();
 
         String pkgSeInfo = ps.getSeInfo();
-
         Preconditions.checkNotNull(pkgSeInfo);
 
         final String seInfo = pkgSeInfo + seInfoUser;
-        final int targetSdkVersion = pkg.getTargetSdkVersion();
-        final boolean usesSdk = !pkg.getUsesSdkLibraries().isEmpty();
+        final int targetSdkVersion = ps.getTargetSdkVersion();
+        final boolean usesSdk = ps.getUsesSdkLibraries().length > 0;
         final CreateAppDataArgs args = Installer.buildCreateAppDataArgs(volumeUuid, packageName,
                 userId, flags, appId, seInfo, targetSdkVersion, usesSdk);
         args.previousAppId = previousAppId;
@@ -234,7 +246,7 @@
             if (e != null) {
                 logCriticalInfo(Log.WARN, "Failed to create app data for " + packageName
                         + ", but trying to recover: " + e);
-                destroyAppDataLeafLIF(pkg, userId, flags);
+                destroyAppDataLeafLIF(packageName, volumeUuid, userId, flags);
                 try {
                     createAppDataResult = mInstaller.createAppData(args);
                     logCriticalInfo(Log.DEBUG, "Recovery succeeded!");
@@ -267,8 +279,8 @@
                 // #performDexOptUpgrade. When we do that we should have a
                 // more granular check here and only update the existing
                 // profiles.
-                if (mPm.isDeviceUpgrading() || mPm.isFirstBoot()
-                        || (userId != UserHandle.USER_SYSTEM)) {
+                if (pkg != null && (mPm.isDeviceUpgrading() || mPm.isFirstBoot()
+                        || (userId != UserHandle.USER_SYSTEM))) {
                     try {
                         mArtManagerService.prepareAppProfiles(pkg, userId,
                                 /* updateReferenceProfileContent= */ false);
@@ -292,7 +304,9 @@
                 }
             }
 
-            prepareAppDataContentsLeafLIF(pkg, ps, userId, flags);
+            if (pkg != null) {
+                prepareAppDataContentsLeafLIF(pkg, ps, userId, flags);
+            }
         });
     }
 
@@ -336,18 +350,17 @@
      * CE/DE data to match the {@code defaultToDeviceProtectedStorage} flag
      * requested by the app.
      */
-    private boolean maybeMigrateAppDataLIF(@NonNull PackageState packageState,
-            @NonNull AndroidPackage pkg, @UserIdInt int userId) {
-        if (packageState.isSystem() && !StorageManager.isFileEncrypted()
+    private boolean maybeMigrateAppDataLIF(@NonNull PackageSetting ps, @UserIdInt int userId) {
+        if (ps.isSystem() && !StorageManager.isFileEncrypted()
                 && PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) {
-            final int storageTarget = pkg.isDefaultToDeviceProtectedStorage()
+            final int storageTarget = ps.isDefaultToDeviceProtectedStorage()
                     ? StorageManager.FLAG_STORAGE_DE : StorageManager.FLAG_STORAGE_CE;
             try {
-                mInstaller.migrateAppData(pkg.getVolumeUuid(), pkg.getPackageName(), userId,
+                mInstaller.migrateAppData(ps.getVolumeUuid(), ps.getPackageName(), userId,
                         storageTarget);
             } catch (Installer.InstallerException e) {
                 logCriticalInfo(Log.WARN,
-                        "Failed to migrate " + pkg.getPackageName() + ": " + e.getMessage());
+                        "Failed to migrate " + ps.getPackageName() + ": " + e.getMessage());
             }
             return true;
         } else {
@@ -471,7 +484,7 @@
             }
 
             if (ps.getUserStateOrDefault(userId).isInstalled()) {
-                prepareAppDataAndMigrate(batch, ps, ps.getPkg(), userId, flags, migrateAppData);
+                prepareAppDataAndMigrate(batch, ps.getPkg(), userId, flags, migrateAppData);
                 preparedCount++;
             }
         }
@@ -550,7 +563,7 @@
                         && packageStateInternal.getUserStateOrDefault(
                                 UserHandle.USER_SYSTEM).isInstalled()) {
                     AndroidPackage pkg = packageStateInternal.getPkg();
-                    prepareAppDataAndMigrate(batch, packageStateInternal, pkg,
+                    prepareAppDataAndMigrate(batch, pkg,
                             UserHandle.USER_SYSTEM, storageFlags, true /* maybeMigrateAppData */);
                     count++;
                 }
@@ -568,22 +581,22 @@
         if (pkg == null) {
             return;
         }
-        clearAppDataLeafLIF(pkg, userId, flags);
+        clearAppDataLeafLIF(pkg.getPackageName(), pkg.getVolumeUuid(), userId, flags);
 
         if ((flags & Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES) == 0) {
             clearAppProfilesLIF(pkg);
         }
     }
 
-    private void clearAppDataLeafLIF(AndroidPackage pkg, int userId, int flags) {
+    void clearAppDataLeafLIF(String packageName, String volumeUuid, int userId, int flags) {
         final Computer snapshot = mPm.snapshotComputer();
         final PackageStateInternal packageStateInternal =
-                snapshot.getPackageStateInternal(pkg.getPackageName());
+                snapshot.getPackageStateInternal(packageName);
         for (int realUserId : mPm.resolveUserIds(userId)) {
             final long ceDataInode = (packageStateInternal != null)
                     ? packageStateInternal.getUserStateOrDefault(realUserId).getCeDataInode() : 0;
             try {
-                mInstaller.clearAppData(pkg.getVolumeUuid(), pkg.getPackageName(), realUserId,
+                mInstaller.clearAppData(volumeUuid, packageName, realUserId,
                         flags, ceDataInode);
             } catch (Installer.InstallerException e) {
                 Slog.w(TAG, String.valueOf(e));
@@ -597,7 +610,7 @@
             return;
         }
         if (DexOptHelper.useArtService()) {
-            destroyAppProfilesWithArtService(pkg);
+            destroyAppProfilesWithArtService(pkg.getPackageName());
         } else {
             try {
                 mArtManagerService.clearAppProfiles(pkg);
@@ -612,41 +625,37 @@
             Slog.wtf(TAG, "Package was null!", new Throwable());
             return;
         }
-        destroyAppDataLeafLIF(pkg, userId, flags);
+        destroyAppDataLeafLIF(pkg.getPackageName(), pkg.getVolumeUuid(), userId, flags);
     }
 
-    private void destroyAppDataLeafLIF(AndroidPackage pkg, int userId, int flags) {
+    private void destroyAppDataLeafLIF(
+            String packageName, String volumeUuid, int userId, int flags) {
         final Computer snapshot = mPm.snapshotComputer();
         final PackageStateInternal packageStateInternal =
-                snapshot.getPackageStateInternal(pkg.getPackageName());
+                snapshot.getPackageStateInternal(packageName);
         for (int realUserId : mPm.resolveUserIds(userId)) {
             final long ceDataInode = (packageStateInternal != null)
                     ? packageStateInternal.getUserStateOrDefault(realUserId).getCeDataInode() : 0;
             try {
-                mInstaller.destroyAppData(pkg.getVolumeUuid(), pkg.getPackageName(), realUserId,
+                mInstaller.destroyAppData(volumeUuid, packageName, realUserId,
                         flags, ceDataInode);
             } catch (Installer.InstallerException e) {
                 Slog.w(TAG, String.valueOf(e));
             }
-            mPm.getDexManager().notifyPackageDataDestroyed(pkg.getPackageName(), userId);
-            mPm.getDynamicCodeLogger().notifyPackageDataDestroyed(pkg.getPackageName(), userId);
+            mPm.getDexManager().notifyPackageDataDestroyed(packageName, userId);
+            mPm.getDynamicCodeLogger().notifyPackageDataDestroyed(packageName, userId);
         }
     }
 
-    public void destroyAppProfilesLIF(AndroidPackage pkg) {
-        if (pkg == null) {
-            Slog.wtf(TAG, "Package was null!", new Throwable());
-            return;
-        }
-        destroyAppProfilesLeafLIF(pkg);
-    }
-
-    private void destroyAppProfilesLeafLIF(AndroidPackage pkg) {
+    /**
+     * Destroy ART app profiles for the package.
+     */
+    void destroyAppProfilesLIF(String packageName) {
         if (DexOptHelper.useArtService()) {
-            destroyAppProfilesWithArtService(pkg);
+            destroyAppProfilesWithArtService(packageName);
         } else {
             try {
-                mInstaller.destroyAppProfiles(pkg.getPackageName());
+                mInstaller.destroyAppProfiles(packageName);
             } catch (LegacyDexoptDisabledException e) {
                 throw new RuntimeException(e);
             } catch (Installer.InstallerException e) {
@@ -655,7 +664,7 @@
         }
     }
 
-    private void destroyAppProfilesWithArtService(AndroidPackage pkg) {
+    private void destroyAppProfilesWithArtService(String packageName) {
         if (!DexOptHelper.artManagerLocalIsInitialized()) {
             // This function may get called while PackageManagerService is constructed (via e.g.
             // InitAppsHelper.initSystemApps), and ART Service hasn't yet been started then (it
@@ -668,7 +677,7 @@
         try (PackageManagerLocal.FilteredSnapshot snapshot =
                         getPackageManagerLocal().withFilteredSnapshot()) {
             try {
-                DexOptHelper.getArtManagerLocal().clearAppProfiles(snapshot, pkg.getPackageName());
+                DexOptHelper.getArtManagerLocal().clearAppProfiles(snapshot, packageName);
             } catch (IllegalArgumentException e) {
                 // Package isn't found, but that should only happen due to race.
                 Slog.w(TAG, e);
diff --git a/services/core/java/com/android/server/pm/AppsFilterImpl.java b/services/core/java/com/android/server/pm/AppsFilterImpl.java
index bdcec3a..82622d9 100644
--- a/services/core/java/com/android/server/pm/AppsFilterImpl.java
+++ b/services/core/java/com/android/server/pm/AppsFilterImpl.java
@@ -54,6 +54,7 @@
 import android.util.ArraySet;
 import android.util.Slog;
 import android.util.SparseBooleanArray;
+import android.util.SparseSetArray;
 
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
@@ -1030,14 +1031,18 @@
     private void recomputeComponentVisibility(
             ArrayMap<String, ? extends PackageStateInternal> existingSettings) {
         final WatchedArraySet<String> protectedBroadcasts;
+        final WatchedArraySet<Integer> forceQueryable;
         synchronized (mProtectedBroadcastsLock) {
             protectedBroadcasts = mProtectedBroadcasts.snapshot();
         }
+        synchronized (mForceQueryableLock) {
+            forceQueryable = mForceQueryable.snapshot();
+        }
         final ParallelComputeComponentVisibility computer = new ParallelComputeComponentVisibility(
-                existingSettings, mForceQueryable, protectedBroadcasts);
+                existingSettings, forceQueryable, protectedBroadcasts);
+        SparseSetArray<Integer> queriesViaComponent = computer.execute();
         synchronized (mQueriesViaComponentLock) {
-            mQueriesViaComponent.clear();
-            computer.execute(mQueriesViaComponent);
+            mQueriesViaComponent.copyFrom(queriesViaComponent);
         }
 
         mQueriesViaComponentRequireRecompute.set(false);
diff --git a/services/core/java/com/android/server/pm/AppsFilterUtils.java b/services/core/java/com/android/server/pm/AppsFilterUtils.java
index f3f64c5..200734b 100644
--- a/services/core/java/com/android/server/pm/AppsFilterUtils.java
+++ b/services/core/java/com/android/server/pm/AppsFilterUtils.java
@@ -26,6 +26,7 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Pair;
+import android.util.SparseSetArray;
 
 import com.android.internal.pm.pkg.component.ParsedComponent;
 import com.android.internal.pm.pkg.component.ParsedIntentInfo;
@@ -37,7 +38,6 @@
 import com.android.server.pm.pkg.PackageState;
 import com.android.server.pm.pkg.PackageStateInternal;
 import com.android.server.utils.WatchedArraySet;
-import com.android.server.utils.WatchedSparseSetArray;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -213,7 +213,9 @@
         /**
          * Computes component visibility of all packages in parallel from a thread pool.
          */
-        void execute(@NonNull WatchedSparseSetArray<Integer> outQueriesViaComponent) {
+        @NonNull
+        SparseSetArray<Integer> execute() {
+            final SparseSetArray<Integer> queriesViaComponent = new SparseSetArray<>();
             final ExecutorService pool = ConcurrentUtils.newFixedThreadPool(
                     MAX_THREADS, ParallelComputeComponentVisibility.class.getSimpleName(),
                     THREAD_PRIORITY_DEFAULT);
@@ -239,7 +241,7 @@
                     try {
                         final ArraySet<Integer> visibleList = future.get();
                         if (visibleList.size() != 0) {
-                            outQueriesViaComponent.addAll(appId, visibleList);
+                            queriesViaComponent.addAll(appId, visibleList);
                         }
                     } catch (InterruptedException | ExecutionException e) {
                         throw new IllegalStateException(e);
@@ -248,6 +250,7 @@
             } finally {
                 pool.shutdownNow();
             }
+            return queriesViaComponent;
         }
 
         /**
diff --git a/services/core/java/com/android/server/pm/BroadcastHelper.java b/services/core/java/com/android/server/pm/BroadcastHelper.java
index 7b35589..7f58e75e 100644
--- a/services/core/java/com/android/server/pm/BroadcastHelper.java
+++ b/services/core/java/com/android/server/pm/BroadcastHelper.java
@@ -837,13 +837,11 @@
         }
 
         final String removedPackage = packageRemovedInfo.mRemovedPackage;
-        final int removedAppId = packageRemovedInfo.mRemovedAppId;
-        final int uid = packageRemovedInfo.mUid;
         final String installerPackageName = packageRemovedInfo.mInstallerPackageName;
         final SparseArray<int[]> broadcastAllowList = packageRemovedInfo.mBroadcastAllowList;
 
         Bundle extras = new Bundle(2);
-        extras.putInt(Intent.EXTRA_UID, removedAppId >= 0 ? removedAppId : uid);
+        extras.putInt(Intent.EXTRA_UID, packageRemovedInfo.mUid);
         extras.putBoolean(Intent.EXTRA_REPLACING, true);
         sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_ADDED, removedPackage, extras,
                 0, null /*targetPackage*/, null, null, null, broadcastAllowList, null);
@@ -888,8 +886,6 @@
             boolean removedBySystem,
             boolean isArchived) {
         final String removedPackage = packageRemovedInfo.mRemovedPackage;
-        final int removedAppId = packageRemovedInfo.mRemovedAppId;
-        final int uid = packageRemovedInfo.mUid;
         final String installerPackageName = packageRemovedInfo.mInstallerPackageName;
         final int[] broadcastUserIds = packageRemovedInfo.mBroadcastUsers;
         final int[] instantUserIds = packageRemovedInfo.mInstantUserIds;
@@ -902,8 +898,7 @@
         final boolean isStaticSharedLib = packageRemovedInfo.mIsStaticSharedLib;
 
         Bundle extras = new Bundle();
-        final int removedUid = removedAppId >= 0  ? removedAppId : uid;
-        extras.putInt(Intent.EXTRA_UID, removedUid);
+        extras.putInt(Intent.EXTRA_UID, packageRemovedInfo.mUid);
         extras.putBoolean(Intent.EXTRA_DATA_REMOVED, dataRemoved);
         extras.putBoolean(Intent.EXTRA_SYSTEM_UPDATE_UNINSTALL, isRemovedPackageSystemUpdate);
         extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, !killApp);
@@ -940,10 +935,10 @@
                 sendPackageBroadcastAndNotify(Intent.ACTION_PACKAGE_FULLY_REMOVED,
                         removedPackage, extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, null,
                         null, broadcastUserIds, instantUserIds, broadcastAllowList, null);
-                packageSender.notifyPackageRemoved(removedPackage, removedUid);
+                packageSender.notifyPackageRemoved(removedPackage, packageRemovedInfo.mUid);
             }
         }
-        if (removedAppId >= 0) {
+        if (packageRemovedInfo.mIsAppIdRemoved) {
             // If a system app's updates are uninstalled the UID is not actually removed. Some
             // services need to know the package name affected.
             if (isReplace) {
diff --git a/services/core/java/com/android/server/pm/Computer.java b/services/core/java/com/android/server/pm/Computer.java
index 92d469c..27f4e11 100644
--- a/services/core/java/com/android/server/pm/Computer.java
+++ b/services/core/java/com/android/server/pm/Computer.java
@@ -405,9 +405,19 @@
     boolean isInstallDisabledForPackage(@NonNull String packageName, int uid,
             @UserIdInt int userId);
 
-    @Nullable
-    List<VersionedPackage> getPackagesUsingSharedLibrary(@NonNull SharedLibraryInfo libInfo,
-            @PackageManager.PackageInfoFlagsBits long flags, int callingUid, @UserIdInt int userId);
+    /**
+     * Returns a Pair that contains a list of packages that depend on the target library and the
+     * package library dependency information. The List&lt;VersionedPackage&gt; indicates a list of
+     * packages that depend on the target library, it may be null if no package depends on
+     * the target library. The List&lt;Boolean&gt; indicates whether each VersionedPackage in
+     * the List&lt;VersionedPackage&gt; optionally depends on the target library, where true means
+     * optional and false means required. It may be null if no package depends on
+     * the target library or without dependency information, e.g. uses-static-library.
+     */
+    @NonNull
+    Pair<List<VersionedPackage>, List<Boolean>> getPackagesUsingSharedLibrary(
+            @NonNull SharedLibraryInfo libInfo, @PackageManager.PackageInfoFlagsBits long flags,
+            int callingUid, @UserIdInt int userId);
 
     @Nullable
     ParceledListSlice<SharedLibraryInfo> getDeclaredSharedLibraries(
@@ -467,7 +477,7 @@
     @NonNull
     List<ApplicationInfo> getInstalledApplications(
             @PackageManager.ApplicationInfoFlagsBits long flags, @UserIdInt int userId,
-            int callingUid);
+            int callingUid, boolean forceAllowCrossUser);
 
     @Nullable
     ProviderInfo resolveContentProvider(@NonNull String name,
@@ -498,12 +508,15 @@
 
     boolean getApplicationHiddenSettingAsUser(@NonNull String packageName, @UserIdInt int userId);
 
-    boolean isPackageSuspendedForUser(@NonNull String packageName, @UserIdInt int userId);
+    boolean isPackageSuspendedForUser(@NonNull String packageName, @UserIdInt int userId)
+            throws PackageManager.NameNotFoundException;
 
-    boolean isPackageQuarantinedForUser(@NonNull String packageName, @UserIdInt int userId);
+    boolean isPackageQuarantinedForUser(@NonNull String packageName, @UserIdInt int userId)
+            throws PackageManager.NameNotFoundException;
 
     /** Check if the package is in a stopped state for a given user. */
-    boolean isPackageStoppedForUser(@NonNull String packageName, @UserIdInt int userId);
+    boolean isPackageStoppedForUser(@NonNull String packageName, @UserIdInt int userId)
+            throws PackageManager.NameNotFoundException;
 
     boolean isSuspendingAnyPackages(@NonNull String suspendingPackage, @UserIdInt int userId);
 
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index 7c425b82..744c946 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -895,6 +895,9 @@
             @PackageManager.ResolveInfoFlagsBits long flags, int filterCallingUid, int userId) {
         ParsedActivity a = mComponentResolver.getActivity(component);
 
+        // Allow to match activities of quarantined packages.
+        flags |= PackageManager.MATCH_QUARANTINED_COMPONENTS;
+
         if (DEBUG_PACKAGE_INFO) Log.v(TAG, "getActivityInfo " + component + ": " + a);
 
         AndroidPackage pkg = a == null ? null : mPackages.get(a.getPackageName());
@@ -1500,14 +1503,15 @@
                     state.getFirstInstallTimeMillis(), ps.getLastUpdateTime(), installedPermissions,
                     grantedPermissions, state, userId, ps);
 
-            if (packageInfo != null) {
-                packageInfo.packageName = packageInfo.applicationInfo.packageName =
-                        resolveExternalPackageName(p);
-                return packageInfo;
+            if (packageInfo == null) {
+                return null;
             }
-        }
-        // TODO(b/314808978): Set ps.setPkg to null during install-archived.
-        if ((flags & (MATCH_UNINSTALLED_PACKAGES | MATCH_ARCHIVED_PACKAGES)) != 0
+
+            packageInfo.packageName = packageInfo.applicationInfo.packageName =
+                    resolveExternalPackageName(p);
+
+            return packageInfo;
+        } else if ((flags & (MATCH_UNINSTALLED_PACKAGES | MATCH_ARCHIVED_PACKAGES)) != 0
                 && PackageUserStateUtils.isAvailable(state, flags)) {
             PackageInfo pi = new PackageInfo();
             pi.packageName = ps.getPackageName();
@@ -1541,8 +1545,9 @@
                         + ps.getPackageName() + "]. Provides a minimum info.");
             }
             return pi;
+        } else {
+            return null;
         }
-        return null;
     }
 
     public final PackageInfo getPackageInfo(String packageName,
@@ -3859,17 +3864,15 @@
                 } finally {
                     Binder.restoreCallingIdentity(identity);
                 }
-
                 SharedLibraryInfo resLibInfo = new SharedLibraryInfo(libInfo.getPath(),
                         libInfo.getPackageName(), libInfo.getAllCodePaths(),
                         libInfo.getName(), libInfo.getLongVersion(),
                         libInfo.getType(), declaringPackage,
-                        getPackagesUsingSharedLibrary(libInfo, flags, callingUid, userId),
                         (libInfo.getDependencies() == null
                                 ? null
                                 : new ArrayList<>(libInfo.getDependencies())),
-                        libInfo.isNative());
-
+                        libInfo.isNative(),
+                        getPackagesUsingSharedLibrary(libInfo, flags, callingUid, userId));
                 if (result == null) {
                     result = new ArrayList<>();
                 }
@@ -3933,13 +3936,15 @@
         return false;
     }
 
+
     @Override
-    public List<VersionedPackage> getPackagesUsingSharedLibrary(@NonNull SharedLibraryInfo libInfo,
-            @PackageManager.PackageInfoFlagsBits long flags, int callingUid,
-            @UserIdInt int userId) {
+    public Pair<List<VersionedPackage>, List<Boolean>> getPackagesUsingSharedLibrary(
+            @NonNull SharedLibraryInfo libInfo, @PackageManager.PackageInfoFlagsBits long flags,
+            int callingUid, @UserIdInt int userId) {
         List<VersionedPackage> versionedPackages = null;
         final ArrayMap<String, ? extends PackageStateInternal> packageStates = getPackageStates();
         final int packageCount = packageStates.size();
+        List<Boolean> usesLibsOptional = null;
         for (int i = 0; i < packageCount; i++) {
             PackageStateInternal ps = packageStates.valueAt(i);
             if (ps == null) {
@@ -3956,12 +3961,15 @@
                         libInfo.isStatic() ? ps.getUsesStaticLibraries() : ps.getUsesSdkLibraries();
                 final long[] libsVersions = libInfo.isStatic() ? ps.getUsesStaticLibrariesVersions()
                         : ps.getUsesSdkLibrariesVersionsMajor();
+                final boolean[] libsOptional = libInfo.isSdk()
+                        ? ps.getUsesSdkLibrariesOptional() : null;
 
                 final int libIdx = ArrayUtils.indexOf(libs, libName);
                 if (libIdx < 0) {
                     continue;
                 }
                 if (libsVersions[libIdx] != libInfo.getLongVersion()) {
+                    // Not expected StaticLib/SdkLib version
                     continue;
                 }
                 if (shouldFilterApplication(ps, callingUid, userId)) {
@@ -3970,6 +3978,9 @@
                 if (versionedPackages == null) {
                     versionedPackages = new ArrayList<>();
                 }
+                if (usesLibsOptional == null) {
+                    usesLibsOptional = new ArrayList<>();
+                }
                 // If the dependent is a static shared lib, use the public package name
                 String dependentPackageName = ps.getPackageName();
                 if (ps.getPkg() != null && ps.getPkg().isStaticSharedLibrary()) {
@@ -3977,6 +3988,7 @@
                 }
                 versionedPackages.add(new VersionedPackage(dependentPackageName,
                         ps.getVersionCode()));
+                usesLibsOptional.add(libsOptional != null && libsOptional[libIdx]);
             } else if (ps.getPkg() != null) {
                 if (ArrayUtils.contains(ps.getPkg().getUsesLibraries(), libName)
                         || ArrayUtils.contains(ps.getPkg().getUsesOptionalLibraries(), libName)) {
@@ -3992,7 +4004,7 @@
             }
         }
 
-        return versionedPackages;
+        return new Pair<>(versionedPackages, usesLibsOptional);
     }
 
     @Nullable
@@ -4051,13 +4063,14 @@
                     Binder.restoreCallingIdentity(identity);
                 }
 
+                var usingSharedLibraryPair =
+                        getPackagesUsingSharedLibrary(libraryInfo, flags, callingUid, userId);
                 SharedLibraryInfo resultLibraryInfo = new SharedLibraryInfo(
                         libraryInfo.getPath(), libraryInfo.getPackageName(),
                         libraryInfo.getAllCodePaths(), libraryInfo.getName(),
                         libraryInfo.getLongVersion(), libraryInfo.getType(),
                         libraryInfo.getDeclaringPackage(),
-                        getPackagesUsingSharedLibrary(
-                                libraryInfo, flags, callingUid, userId),
+                        usingSharedLibraryPair.first,
                         libraryInfo.getDependencies() == null
                                 ? null : new ArrayList<>(libraryInfo.getDependencies()),
                         libraryInfo.isNative());
@@ -4623,7 +4636,7 @@
     @Override
     public List<ApplicationInfo> getInstalledApplications(
             @PackageManager.ApplicationInfoFlagsBits long flags, @UserIdInt int userId,
-            int callingUid) {
+            int callingUid, boolean forceAllowCrossUser) {
         if (getInstantAppPackageName(callingUid) != null) {
             return Collections.emptyList();
         }
@@ -4633,12 +4646,14 @@
         final boolean listApex = (flags & MATCH_APEX) != 0;
         final boolean listArchivedOnly = !listUninstalled && (flags & MATCH_ARCHIVED_PACKAGES) != 0;
 
-        enforceCrossUserPermission(
-                callingUid,
-                userId,
-                false /* requireFullPermission */,
-                false /* checkShell */,
-                "get installed application info");
+        if (!forceAllowCrossUser) {
+            enforceCrossUserPermission(
+                    callingUid,
+                    userId,
+                    false /* requireFullPermission */,
+                    false /* checkShell */,
+                    "get installed application info");
+        }
 
         ArrayList<ApplicationInfo> list;
         final ArrayMap<String, ? extends PackageStateInternal> packageStates =
@@ -4961,31 +4976,34 @@
         }
     }
 
-    private PackageUserStateInternal getUserStageOrDefaultForUser(@NonNull String packageName,
-            int userId) {
+    private PackageUserStateInternal getUserStateOrDefaultForUser(@NonNull String packageName,
+            int userId) throws PackageManager.NameNotFoundException {
         final int callingUid = Binder.getCallingUid();
         enforceCrossUserPermission(callingUid, userId, true /* requireFullPermission */,
                 false /* checkShell */, "when asking about packages for user " + userId);
         final PackageStateInternal ps = mSettings.getPackage(packageName);
         if (ps == null || shouldFilterApplicationIncludingUninstalled(ps, callingUid, userId)) {
-            throw new IllegalArgumentException("Unknown target package: " + packageName);
+            throw new PackageManager.NameNotFoundException(packageName);
         }
         return ps.getUserStateOrDefault(userId);
     }
 
     @Override
-    public boolean isPackageSuspendedForUser(@NonNull String packageName, int userId) {
-        return getUserStageOrDefaultForUser(packageName, userId).isSuspended();
+    public boolean isPackageSuspendedForUser(@NonNull String packageName, int userId)
+            throws PackageManager.NameNotFoundException {
+        return getUserStateOrDefaultForUser(packageName, userId).isSuspended();
     }
 
     @Override
-    public boolean isPackageQuarantinedForUser(@NonNull String packageName, @UserIdInt int userId) {
-        return getUserStageOrDefaultForUser(packageName, userId).isQuarantined();
+    public boolean isPackageQuarantinedForUser(@NonNull String packageName, @UserIdInt int userId)
+            throws PackageManager.NameNotFoundException {
+        return getUserStateOrDefaultForUser(packageName, userId).isQuarantined();
     }
 
     @Override
-    public boolean isPackageStoppedForUser(@NonNull String packageName, @UserIdInt int userId) {
-        return getUserStageOrDefaultForUser(packageName, userId).isStopped();
+    public boolean isPackageStoppedForUser(@NonNull String packageName, @UserIdInt int userId)
+            throws PackageManager.NameNotFoundException {
+        return getUserStateOrDefaultForUser(packageName, userId).isStopped();
     }
 
     @Override
diff --git a/services/core/java/com/android/server/pm/DeletePackageAction.java b/services/core/java/com/android/server/pm/DeletePackageAction.java
index 8ef6601..31544d5 100644
--- a/services/core/java/com/android/server/pm/DeletePackageAction.java
+++ b/services/core/java/com/android/server/pm/DeletePackageAction.java
@@ -16,17 +16,19 @@
 
 package com.android.server.pm;
 
+import android.annotation.NonNull;
 import android.os.UserHandle;
 
 final class DeletePackageAction {
     public final PackageSetting mDeletingPs;
     public final PackageSetting mDisabledPs;
+    @NonNull
     public final PackageRemovedInfo mRemovedInfo;
     public final int mFlags;
     public final UserHandle mUser;
 
     DeletePackageAction(PackageSetting deletingPs, PackageSetting disabledPs,
-            PackageRemovedInfo removedInfo, int flags, UserHandle user) {
+            @NonNull PackageRemovedInfo removedInfo, int flags, UserHandle user) {
         mDeletingPs = deletingPs;
         mDisabledPs = disabledPs;
         mRemovedInfo = removedInfo;
diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java
index 80e6c83..aa7f0d3 100644
--- a/services/core/java/com/android/server/pm/DeletePackageHelper.java
+++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java
@@ -18,7 +18,6 @@
 
 import static android.Manifest.permission.CONTROL_KEYGUARD;
 import static android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS;
-import static android.content.pm.Flags.sdkLibIndependence;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
 import static android.content.pm.PackageManager.DELETE_KEEP_DATA;
@@ -40,6 +39,7 @@
 import android.app.ApplicationPackageManager;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.Flags;
 import android.content.pm.IPackageDeleteObserver2;
 import android.content.pm.PackageInstaller;
 import android.content.pm.PackageManager;
@@ -72,8 +72,6 @@
 
 import dalvik.system.VMRuntime;
 
-import java.util.List;
-
 /**
  * Deletes a package. Uninstall if installed, or at least deletes the base directory if it's called
  * from a failed installation. Fixes user state after deletion.
@@ -181,16 +179,36 @@
                 }
 
                 if (libraryInfo != null) {
+                    boolean flagSdkLibIndependence = Flags.sdkLibIndependence();
                     for (int currUserId : allUsers) {
                         if (removeUser != UserHandle.USER_ALL && removeUser != currUserId) {
                             continue;
                         }
-                        List<VersionedPackage> libClientPackages =
-                                computer.getPackagesUsingSharedLibrary(libraryInfo,
-                                        MATCH_KNOWN_PACKAGES, Process.SYSTEM_UID, currUserId);
-                        boolean allowSdkLibIndependence =
-                                (pkg.getSdkLibraryName() != null) && sdkLibIndependence();
-                        if (!ArrayUtils.isEmpty(libClientPackages) && !allowSdkLibIndependence) {
+                        var libClientPackagesPair = computer.getPackagesUsingSharedLibrary(
+                                libraryInfo, MATCH_KNOWN_PACKAGES, Process.SYSTEM_UID, currUserId);
+                        var libClientPackages = libClientPackagesPair.first;
+                        var libClientOptional = libClientPackagesPair.second;
+                        // We by default don't allow removing a package if the host lib is still be
+                        // used by other client packages
+                        boolean allowLibIndependence = false;
+                        // Only when the sdkLibIndependence flag is enabled we will respect the
+                        // "optional" attr in uses-sdk-library. Only allow to remove sdk-lib host
+                        // package if no required clients depend on it
+                        if ((pkg.getSdkLibraryName() != null)
+                                && !ArrayUtils.isEmpty(libClientPackages)
+                                && !ArrayUtils.isEmpty(libClientOptional)
+                                && (libClientPackages.size() == libClientOptional.size())
+                                && flagSdkLibIndependence) {
+                            allowLibIndependence = true;
+                            for (int i = 0; i < libClientPackages.size(); i++) {
+                                boolean usesSdkLibOptional = libClientOptional.get(i);
+                                if (!usesSdkLibOptional) {
+                                    allowLibIndependence = false;
+                                    break;
+                                }
+                            }
+                        }
+                        if (!ArrayUtils.isEmpty(libClientPackages) && !allowLibIndependence) {
                             Slog.w(TAG, "Not removing package " + pkg.getManifestPackageName()
                                     + " hosting lib " + libraryInfo.getName() + " version "
                                     + libraryInfo.getLongVersion() + " used by " + libClientPackages
@@ -352,7 +370,7 @@
     @GuardedBy("mPm.mInstallLock")
     public boolean deletePackageLIF(@NonNull String packageName, UserHandle user,
             boolean deleteCodeAndResources, @NonNull int[] allUserHandles, int flags,
-            PackageRemovedInfo outInfo, boolean writeSettings) {
+            @NonNull PackageRemovedInfo outInfo, boolean writeSettings) {
         final DeletePackageAction action;
         synchronized (mPm.mLock) {
             final PackageSetting ps = mPm.mSettings.getPackageLPr(packageName);
@@ -392,8 +410,8 @@
      * deleted, {@code null} otherwise.
      */
     @Nullable
-    public static DeletePackageAction mayDeletePackageLocked(
-            PackageRemovedInfo outInfo, PackageSetting ps, @Nullable PackageSetting disabledPs,
+    public static DeletePackageAction mayDeletePackageLocked(@NonNull PackageRemovedInfo outInfo,
+            PackageSetting ps, @Nullable PackageSetting disabledPs,
             int flags, UserHandle user) {
         if (ps == null) {
             return null;
@@ -442,12 +460,18 @@
         }
 
         final int userId = user == null ? UserHandle.USER_ALL : user.getIdentifier();
-        if (outInfo != null) {
-            // Remember which users are affected, before the installed states are modified
-            outInfo.mRemovedUsers = (systemApp || userId == UserHandle.USER_ALL)
-                    ? ps.queryUsersInstalledOrHasData(allUserHandles)
-                    : new int[]{userId};
-        }
+        // Remember which users are affected, before the installed states are modified
+        outInfo.mRemovedUsers = (systemApp || userId == UserHandle.USER_ALL)
+                ? ps.queryUsersInstalledOrHasData(allUserHandles)
+                : new int[]{userId};
+        outInfo.populateBroadcastUsers(ps);
+        outInfo.mDataRemoved = (flags & PackageManager.DELETE_KEEP_DATA) == 0;
+        outInfo.mRemovedPackage = ps.getPackageName();
+        outInfo.mInstallerPackageName = ps.getInstallSource().mInstallerPackageName;
+        outInfo.mIsStaticSharedLib =
+                ps.getPkg() != null && ps.getPkg().getStaticSharedLibraryName() != null;
+        outInfo.mIsExternal = ps.isExternalStorage();
+        outInfo.mRemovedPackageVersionCode = ps.getVersionCode();
 
         if ((!systemApp || (flags & PackageManager.DELETE_SYSTEM_APP) != 0)
                 && userId != UserHandle.USER_ALL) {
@@ -485,7 +509,11 @@
                 }
             }
             if (clearPackageStateAndReturn) {
-                mRemovePackageHelper.clearPackageStateForUserLIF(ps, userId, outInfo, flags);
+                mRemovePackageHelper.clearPackageStateForUserLIF(ps, userId, flags);
+                // Legacy behavior to report appId as UID here.
+                // The final broadcasts will contain a per-user UID.
+                outInfo.mUid = ps.getAppId();
+                outInfo.mIsAppIdRemoved = true;
                 mPm.scheduleWritePackageRestrictions(user);
                 return;
             }
@@ -511,12 +539,8 @@
 
         // If the package removed had SUSPEND_APPS, unset any restrictions that might have been in
         // place for all affected users.
-        int[] affectedUserIds = (outInfo != null) ? outInfo.mRemovedUsers : null;
-        if (affectedUserIds == null) {
-            affectedUserIds = mPm.resolveUserIds(userId);
-        }
         final Computer snapshot = mPm.snapshotComputer();
-        for (final int affectedUserId : affectedUserIds) {
+        for (final int affectedUserId : outInfo.mRemovedUsers) {
             if (hadSuspendAppsPermission.get(affectedUserId)) {
                 mPm.unsuspendForSuspendingPackage(snapshot, packageName, affectedUserId);
                 mPm.removeAllDistractingPackageRestrictions(snapshot, affectedUserId);
@@ -524,24 +548,21 @@
         }
 
         // Take a note whether we deleted the package for all users
-        if (outInfo != null) {
-            synchronized (mPm.mLock) {
-                outInfo.mRemovedForAllUsers = mPm.mPackages.get(ps.getPackageName()) == null;
-            }
+        synchronized (mPm.mLock) {
+            outInfo.mRemovedForAllUsers = mPm.mPackages.get(ps.getPackageName()) == null;
         }
     }
 
     @GuardedBy("mPm.mInstallLock")
     private void deleteInstalledPackageLIF(PackageSetting ps,
             boolean deleteCodeAndResources, int flags, @NonNull int[] allUserHandles,
-            PackageRemovedInfo outInfo, boolean writeSettings) {
+            @NonNull PackageRemovedInfo outInfo, boolean writeSettings) {
         synchronized (mPm.mLock) {
-            if (outInfo != null) {
-                outInfo.mUid = ps.getAppId();
-                outInfo.mBroadcastAllowList = mPm.mAppsFilter.getVisibilityAllowList(
-                        mPm.snapshotComputer(), ps, allUserHandles,
-                        mPm.mSettings.getPackagesLocked());
-            }
+            // Since the package is being deleted in all users, report appId as the uid
+            outInfo.mUid = ps.getAppId();
+            outInfo.mBroadcastAllowList = mPm.mAppsFilter.getVisibilityAllowList(
+                    mPm.snapshotComputer(), ps, allUserHandles,
+                    mPm.mSettings.getPackagesLocked());
         }
 
         // Delete package data from internal structures and also remove data if flag is set
@@ -549,7 +570,7 @@
                 ps, allUserHandles, outInfo, flags, writeSettings);
 
         // Delete application code and resources only for parent packages
-        if (deleteCodeAndResources && (outInfo != null)) {
+        if (deleteCodeAndResources) {
             outInfo.mArgs = new InstallArgs(
                     ps.getPathString(), getAppDexInstructionSets(
                             ps.getPrimaryCpuAbiLegacy(), ps.getSecondaryCpuAbiLegacy()));
@@ -621,7 +642,7 @@
         int flags = action.mFlags;
         final PackageSetting deletedPs = action.mDeletingPs;
         final PackageRemovedInfo outInfo = action.mRemovedInfo;
-        final boolean applyUserRestrictions = outInfo != null && (outInfo.mOrigUsers != null);
+        final boolean applyUserRestrictions = outInfo.mOrigUsers != null;
         final AndroidPackage deletedPkg = deletedPs.getPkg();
         // Confirm if the system package has been updated
         // An updated system app can be deleted. This will also have to restore
@@ -644,10 +665,8 @@
             }
         }
 
-        if (outInfo != null) {
-            // Delete the updated package
-            outInfo.mIsRemovedPackageSystemUpdate = true;
-        }
+        // Delete the updated package
+        outInfo.mIsRemovedPackageSystemUpdate = true;
 
         if (disabledPs.getVersionCode() < deletedPs.getVersionCode()
                 || disabledPs.getAppId() != deletedPs.getAppId()) {
diff --git a/services/core/java/com/android/server/pm/IPackageManagerBase.java b/services/core/java/com/android/server/pm/IPackageManagerBase.java
index 9a0306b..e3bbd2d 100644
--- a/services/core/java/com/android/server/pm/IPackageManagerBase.java
+++ b/services/core/java/com/android/server/pm/IPackageManagerBase.java
@@ -476,7 +476,8 @@
             @PackageManager.ApplicationInfoFlagsBits long flags, int userId) {
         final int callingUid = Binder.getCallingUid();
         return new ParceledListSlice<>(
-                snapshot().getInstalledApplications(flags, userId, callingUid));
+                snapshot().getInstalledApplications(flags, userId, callingUid,
+                        /* forceAllowCrossUser= */ false));
     }
 
     @Override
@@ -950,20 +951,32 @@
     @Deprecated
     public final boolean isPackageSuspendedForUser(@NonNull String packageName,
             @UserIdInt int userId) {
-        return snapshot().isPackageSuspendedForUser(packageName, userId);
+        try {
+            return snapshot().isPackageSuspendedForUser(packageName, userId);
+        } catch (PackageManager.NameNotFoundException e) {
+            throw new IllegalArgumentException("Unknown target package: " + packageName);
+        }
     }
 
     @Override
     @Deprecated
     public final boolean isPackageQuarantinedForUser(@NonNull String packageName,
             @UserIdInt int userId) {
-        return snapshot().isPackageQuarantinedForUser(packageName, userId);
+        try {
+            return snapshot().isPackageQuarantinedForUser(packageName, userId);
+        } catch (PackageManager.NameNotFoundException e) {
+            throw new IllegalArgumentException("Unknown target package: " + packageName);
+        }
     }
 
     @Override
     public final boolean isPackageStoppedForUser(@NonNull String packageName,
             @UserIdInt int userId) {
-        return snapshot().isPackageStoppedForUser(packageName, userId);
+        try {
+            return snapshot().isPackageStoppedForUser(packageName, userId);
+        } catch (PackageManager.NameNotFoundException e) {
+            throw new IllegalArgumentException("Unknown target package: " + packageName);
+        }
     }
 
     @Override
diff --git a/services/core/java/com/android/server/pm/InitAppsHelper.java b/services/core/java/com/android/server/pm/InitAppsHelper.java
index 5c4447e..3b9f9c8 100644
--- a/services/core/java/com/android/server/pm/InitAppsHelper.java
+++ b/services/core/java/com/android/server/pm/InitAppsHelper.java
@@ -18,6 +18,7 @@
 
 import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
 
+import static com.android.internal.pm.pkg.parsing.ParsingPackageUtils.PARSE_APK_IN_APEX;
 import static com.android.internal.util.FrameworkStatsLog.BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_DATA_APP_AVG_SCAN_TIME;
 import static com.android.internal.util.FrameworkStatsLog.BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_SYSTEM_APP_AVG_SCAN_TIME;
 import static com.android.server.pm.PackageManagerService.SCAN_AS_APK_IN_APEX;
@@ -30,7 +31,6 @@
 import static com.android.server.pm.PackageManagerService.SCAN_REQUIRE_KNOWN;
 import static com.android.server.pm.PackageManagerService.SYSTEM_PARTITIONS;
 import static com.android.server.pm.PackageManagerService.TAG;
-import static com.android.server.pm.pkg.parsing.ParsingPackageUtils.PARSE_APK_IN_APEX;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -46,12 +46,12 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.content.om.OverlayConfig;
+import com.android.internal.pm.pkg.parsing.ParsingPackageUtils;
 import com.android.internal.util.FrameworkStatsLog;
 import com.android.server.EventLogTags;
 import com.android.server.pm.parsing.PackageCacher;
 import com.android.server.pm.parsing.PackageParser2;
 import com.android.server.pm.pkg.AndroidPackage;
-import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
 import com.android.server.utils.WatchedArrayMap;
 
 import java.io.File;
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 8270481..0fa7aa5 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -154,12 +154,16 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.content.F2fsUtils;
+import com.android.internal.pm.parsing.PackageParserException;
+import com.android.internal.pm.parsing.pkg.AndroidPackageLegacyUtils;
 import com.android.internal.pm.parsing.pkg.ParsedPackage;
+import com.android.internal.pm.pkg.component.ComponentMutateUtils;
 import com.android.internal.pm.pkg.component.ParsedActivity;
 import com.android.internal.pm.pkg.component.ParsedInstrumentation;
 import com.android.internal.pm.pkg.component.ParsedIntentInfo;
 import com.android.internal.pm.pkg.component.ParsedPermission;
 import com.android.internal.pm.pkg.component.ParsedPermissionGroup;
+import com.android.internal.pm.pkg.parsing.ParsingPackageUtils;
 import com.android.internal.security.VerityUtils;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.CollectionUtils;
@@ -181,8 +185,6 @@
 import com.android.server.pm.pkg.AndroidPackage;
 import com.android.server.pm.pkg.PackageStateInternal;
 import com.android.server.pm.pkg.SharedLibraryWrapper;
-import com.android.server.pm.pkg.component.ComponentMutateUtils;
-import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
 import com.android.server.rollback.RollbackManagerInternal;
 import com.android.server.security.FileIntegrityService;
 import com.android.server.utils.WatchedArrayMap;
@@ -731,7 +733,8 @@
 
                     synchronized (mPm.mInstallLock) {
                         // We don't need to freeze for a brand new install
-                        mAppDataHelper.prepareAppDataAfterInstallLIF(pkgSetting.getPkg());
+                        mAppDataHelper.prepareAppDataPostCommitLIF(
+                                pkgSetting, /* previousAppId= */0, new int[] { userId });
                     }
                 }
                 // TODO(b/278553670) Store archive state for the user.
@@ -1164,7 +1167,7 @@
                         parseFlags);
                 archivedPackage = request.getPackageLite().getArchivedPackage();
             }
-        } catch (PackageManagerException e) {
+        } catch (PackageManagerException | PackageParserException e) {
             throw new PrepareFailure("Failed parse during installPackageLI", e);
         } finally {
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
@@ -2432,9 +2435,9 @@
             final boolean instantApp = ((installRequest.getScanFlags() & SCAN_AS_INSTANT_APP) != 0);
             final boolean isApex = ((installRequest.getScanFlags() & SCAN_AS_APEX) != 0);
             final PackageSetting ps = installRequest.getScannedPackageSetting();
+            final String packageName = ps.getPackageName();
+            final String codePath = ps.getPathString();
             final AndroidPackage pkg = ps.getPkg();
-            final String packageName = pkg.getPackageName();
-            final String codePath = pkg.getPath();
             final boolean onIncremental = mIncrementalManager != null
                     && isIncrementalPath(codePath);
             if (onIncremental) {
@@ -2447,18 +2450,19 @@
             }
 
             // Hardcode previousAppId to 0 to disable any data migration (http://b/221088088)
-            mAppDataHelper.prepareAppDataPostCommitLIF(pkg, 0);
+            mAppDataHelper.prepareAppDataPostCommitLIF(ps, 0, installRequest.getNewUsers());
             if (installRequest.isClearCodeCache()) {
-                mAppDataHelper.clearAppDataLIF(pkg, UserHandle.USER_ALL,
+                mAppDataHelper.clearAppDataLIF(ps.getPkg(), UserHandle.USER_ALL,
                         FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL
                                 | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
             }
-            if (installRequest.isInstallReplace()) {
-                mDexManager.notifyPackageUpdated(pkg.getPackageName(),
+            if (installRequest.isInstallReplace() && pkg != null) {
+                mDexManager.notifyPackageUpdated(packageName,
                         pkg.getBaseApkPath(), pkg.getSplitCodePaths());
             }
 
-            if (!useArtService()) { // ART Service handles this on demand instead.
+            // ART Service handles this on demand instead.
+            if (!useArtService() && pkg != null) {
                 // Prepare the application profiles for the new code paths.
                 // This needs to be done before invoking dexopt so that any install-time profile
                 // can be used for optimizations.
@@ -2523,6 +2527,7 @@
                     (!instantApp || android.provider.Settings.Global.getInt(
                             mContext.getContentResolver(),
                             android.provider.Settings.Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0)
+                            && pkg != null
                             && !pkg.isDebuggable()
                             && (!onIncremental)
                             && dexoptOptions.isCompilationEnabled()
@@ -2907,7 +2912,8 @@
                 info.mInstallerPackageName = request.getInstallerPackageName();
                 info.mRemovedUsers = firstUserIds;
                 info.mBroadcastUsers = firstUserIds;
-                info.mRemovedAppId = request.getAppId();
+                info.mUid = request.getAppId();
+                info.mIsAppIdRemoved = true;
                 info.mRemovedPackageVersionCode = request.getPkg().getLongVersionCode();
                 info.mRemovedForAllUsers = true;
 
@@ -3853,7 +3859,7 @@
 
         synchronized (mPm.mLock) {
             platformPackage = mPm.getPlatformPackage();
-            var isSystemApp = AndroidPackageUtils.isSystem(parsedPackage);
+            var isSystemApp = AndroidPackageLegacyUtils.isSystem(parsedPackage);
             final String renamedPkgName = mPm.mSettings.getRenamedPackageLPr(
                     AndroidPackageUtils.getRealPackageOrNull(parsedPackage, isSystemApp));
             realPkgName = ScanPackageUtils.getRealPackageName(parsedPackage, renamedPkgName,
@@ -4123,7 +4129,7 @@
                         null /* request */)) {
                     mDeletePackageHelper.deletePackageLIF(
                             parsedPackage.getPackageName(), null, true,
-                            mPm.mUserManager.getUserIds(), 0, null, false);
+                            mPm.mUserManager.getUserIds(), 0, new PackageRemovedInfo(), false);
                 }
             } else if (newPkgVersionGreater || newSharedUserSetting) {
                 // The application on /system is newer than the application on /data.
@@ -4571,7 +4577,7 @@
 
     private void assertPackageWithSharedUserIdIsPrivileged(AndroidPackage pkg)
             throws PackageManagerException {
-        if (!AndroidPackageUtils.isPrivileged(pkg) && (pkg.getSharedUserId() != null)) {
+        if (!AndroidPackageLegacyUtils.isPrivileged(pkg) && (pkg.getSharedUserId() != null)) {
             SharedUserSetting sharedUserSetting = null;
             try {
                 synchronized (mPm.mLock) {
@@ -4609,7 +4615,7 @@
         final boolean skipVendorPrivilegeScan = ((scanFlags & SCAN_AS_VENDOR) != 0)
                 && ScanPackageUtils.getVendorPartitionVersion() < 28;
         if (((scanFlags & SCAN_AS_PRIVILEGED) == 0)
-                && !AndroidPackageUtils.isPrivileged(pkg)
+                && !AndroidPackageLegacyUtils.isPrivileged(pkg)
                 && (pkg.getSharedUserId() != null)
                 && !skipVendorPrivilegeScan) {
             SharedUserSetting sharedUserSetting = null;
diff --git a/services/core/java/com/android/server/pm/InstallRequest.java b/services/core/java/com/android/server/pm/InstallRequest.java
index 5494bd9..ee780d9 100644
--- a/services/core/java/com/android/server/pm/InstallRequest.java
+++ b/services/core/java/com/android/server/pm/InstallRequest.java
@@ -51,12 +51,12 @@
 import android.util.Slog;
 
 import com.android.internal.pm.parsing.pkg.ParsedPackage;
+import com.android.internal.pm.pkg.parsing.ParsingPackageUtils;
 import com.android.internal.util.ArrayUtils;
 import com.android.server.art.model.DexoptResult;
 import com.android.server.pm.pkg.AndroidPackage;
 import com.android.server.pm.pkg.PackageState;
 import com.android.server.pm.pkg.PackageStateInternal;
-import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
 
 import java.io.File;
 import java.util.ArrayList;
@@ -818,7 +818,8 @@
 
     public void setRemovedAppId(int appId) {
         if (mRemovedInfo != null) {
-            mRemovedInfo.mRemovedAppId = appId;
+            mRemovedInfo.mUid = appId;
+            mRemovedInfo.mIsAppIdRemoved = true;
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/KnownPackages.java b/services/core/java/com/android/server/pm/KnownPackages.java
index 154709a..83831ca 100644
--- a/services/core/java/com/android/server/pm/KnownPackages.java
+++ b/services/core/java/com/android/server/pm/KnownPackages.java
@@ -77,6 +77,8 @@
     // Please note the numbers should be continuous.
     public static final int LAST_KNOWN_PACKAGE = PACKAGE_WEARABLE_SENSING;
 
+    static final String SYSTEM_PACKAGE_NAME = "android";
+
     private final DefaultAppProvider mDefaultAppProvider;
     private final String mRequiredInstallerPackage;
     private final String mRequiredUninstallerPackage;
@@ -186,7 +188,7 @@
             case PACKAGE_SETUP_WIZARD:
                 return snapshot.filterOnlySystemPackages(mSetupWizardPackage);
             case PACKAGE_SYSTEM:
-                return new String[]{"android"};
+                return new String[]{SYSTEM_PACKAGE_NAME};
             case PACKAGE_VERIFIER:
                 return snapshot.filterOnlySystemPackages(mRequiredVerifierPackages);
             case PACKAGE_SYSTEM_TEXT_CLASSIFIER:
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index b80c009..127bf49 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -769,6 +769,9 @@
         @NonNull
         private List<LauncherActivityInfoInternal> generateLauncherActivitiesForArchivedApp(
                 @Nullable String packageName, UserHandle user) {
+            if (!canAccessProfile(user.getIdentifier(), "Cannot retrieve activities")) {
+                return List.of();
+            }
             List<ApplicationInfo> applicationInfoList =
                     (packageName == null)
                             ? getApplicationInfoListForAllArchivedApps(user)
@@ -819,7 +822,7 @@
             return new LauncherActivityInfoInternal(
                     activityInfo,
                     new IncrementalStatesInfo(
-                            false /* isLoading */, 1 /* progress */, 0 /* loadingCompletedTime */),
+                            false /* isLoading */, 0 /* progress */, 0 /* loadingCompletedTime */),
                     user);
         }
 
@@ -827,7 +830,7 @@
         private List<ApplicationInfo> getApplicationInfoListForAllArchivedApps(UserHandle user) {
             final int callingUid = injectBinderCallingUid();
             List<ApplicationInfo> installedApplicationInfoList =
-                    mPackageManagerInternal.getInstalledApplications(
+                    mPackageManagerInternal.getInstalledApplicationsCrossUser(
                             PackageManager.MATCH_ARCHIVED_PACKAGES,
                             user.getIdentifier(),
                             callingUid);
@@ -845,11 +848,12 @@
         private List<ApplicationInfo> getApplicationInfoForArchivedApp(
                 @NonNull String packageName, UserHandle user) {
             final int callingUid = injectBinderCallingUid();
-            ApplicationInfo applicationInfo = mPackageManagerInternal.getApplicationInfo(
-                    packageName,
-                    PackageManager.MATCH_ARCHIVED_PACKAGES,
-                    callingUid,
-                    user.getIdentifier());
+            ApplicationInfo applicationInfo = Binder.withCleanCallingIdentity(() ->
+                    mPackageManagerInternal.getApplicationInfo(
+                            packageName,
+                            PackageManager.MATCH_ARCHIVED_PACKAGES,
+                            callingUid,
+                            user.getIdentifier()));
             if (applicationInfo == null || !applicationInfo.isArchived) {
                 return Collections.EMPTY_LIST;
             }
@@ -1571,6 +1575,57 @@
         }
 
         @Override
+        public List<String> getPreInstalledSystemPackages(UserHandle user) {
+            // Only system launchers, which have access to recents should have access to this API.
+            // TODO(b/303803157): Update access control for this API to default Launcher app.
+            if (!mActivityTaskManagerInternal.isCallerRecents(Binder.getCallingUid())) {
+                throw new SecurityException("Caller is not the recents app");
+            }
+            if (!canAccessProfile(user.getIdentifier(),
+                    "Can't access preinstalled packages for another user")) {
+                return null;
+            }
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                String userType = mUm.getUserInfo(user.getIdentifier()).userType;
+                Set<String> preInstalledPackages = mUm.getPreInstallableSystemPackages(userType);
+                if (preInstalledPackages == null) {
+                    return new ArrayList<>();
+                }
+                return List.copyOf(preInstalledPackages);
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
+        public @Nullable IntentSender getAppMarketActivityIntent(@NonNull String callingPackage,
+                @Nullable String packageName, @NonNull UserHandle user) {
+            // Only system launchers, which have access to recents should have access to this API.
+            // TODO(b/303803157): Update access control for this API to default Launcher app.
+            if (!mActivityTaskManagerInternal.isCallerRecents(Binder.getCallingUid())) {
+                throw new SecurityException("Caller is not the recents app");
+            }
+            if (!canAccessProfile(user.getIdentifier(),
+                    "Can't access AppMarketActivity for another user")) {
+                return null;
+            }
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                // TODO(b/316118005): Add code to launch the app installer for the packageName.
+                Intent appMarketIntent = new Intent(Intent.ACTION_MAIN);
+                appMarketIntent.addCategory(Intent.CATEGORY_APP_MARKET);
+                final PendingIntent pi = PendingIntent.getActivityAsUser(
+                        mContext, /* requestCode */ 0, appMarketIntent, PendingIntent.FLAG_ONE_SHOT
+                                | PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_CANCEL_CURRENT,
+                        /* options */ null, user);
+                return pi == null ? null : pi.getIntentSender();
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
         public void startActivityAsUser(IApplicationThread caller, String callingPackage,
                 String callingFeatureId, ComponentName component, Rect sourceBounds,
                 Bundle opts, UserHandle user) throws RemoteException {
diff --git a/services/core/java/com/android/server/pm/PackageArchiver.java b/services/core/java/com/android/server/pm/PackageArchiver.java
index e3bab3f..2864a8b 100644
--- a/services/core/java/com/android/server/pm/PackageArchiver.java
+++ b/services/core/java/com/android/server/pm/PackageArchiver.java
@@ -165,7 +165,7 @@
         Computer snapshot = mPm.snapshotComputer();
         int userId = userHandle.getIdentifier();
         int binderUid = Binder.getCallingUid();
-        if (!PackageManagerServiceUtils.isRootOrShell(binderUid)) {
+        if (!PackageManagerServiceUtils.isSystemOrRootOrShell(binderUid)) {
             verifyCaller(snapshot.getPackageUid(callerPackageName, 0, userId), binderUid);
         }
         snapshot.enforceCrossUserPermission(binderUid, userId, true, true,
@@ -323,6 +323,7 @@
         PackageStateInternal ps = getPackageState(packageName, snapshot,
                 Binder.getCallingUid(), userId);
         verifyNotSystemApp(ps.getFlags());
+        verifyInstalled(ps, userId);
         String responsibleInstallerPackage = getResponsibleInstallerPackage(ps);
         verifyInstaller(responsibleInstallerPackage, userId);
         ApplicationInfo installerInfo = snapshot.getApplicationInfo(
@@ -476,6 +477,14 @@
         }
     }
 
+    private void verifyInstalled(PackageStateInternal ps, int userId)
+            throws PackageManager.NameNotFoundException {
+        if (!ps.getUserStateOrDefault(userId).isInstalled()) {
+            throw new PackageManager.NameNotFoundException(
+                    TextUtils.formatSimple("%s is not installed.", ps.getPackageName()));
+        }
+    }
+
     /**
      * Returns true if the app is archivable.
      */
@@ -519,11 +528,11 @@
     /**
      * Returns true if user has opted the app out of archiving through system settings.
      */
-    // TODO(b/304256918) Switch this to a separate OP code for archiving.
     private boolean isAppOptedOutOfArchiving(String packageName, int uid) {
         return Binder.withCleanCallingIdentity(() ->
-                getAppOpsManager().checkOp(AppOpsManager.OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED,
-                        uid, packageName) == MODE_IGNORED);
+                getAppOpsManager().checkOpNoThrow(
+                        AppOpsManager.OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, uid, packageName)
+                        == MODE_IGNORED);
     }
 
     private void verifyOptOutStatus(String packageName, int uid)
@@ -676,23 +685,51 @@
         PackageStateInternal ps;
         try {
             ps = getPackageState(packageName, snapshot, callingUid, userId);
-            snapshot.enforceCrossUserPermission(callingUid, userId, true, false,
-                    "getArchivedAppIcon");
-            verifyArchived(ps, userId);
         } catch (PackageManager.NameNotFoundException e) {
-            throw new ParcelableException(e);
+            Slog.e(TAG, TextUtils.formatSimple("Package %s couldn't be found.", packageName), e);
+            return null;
         }
 
-        List<ArchiveActivityInfo> activityInfos = ps.getUserStateOrDefault(
-                userId).getArchiveState().getActivityInfos();
-        if (activityInfos.size() == 0) {
+        ArchiveState archiveState = getAnyArchiveState(ps, userId);
+        if (archiveState == null || archiveState.getActivityInfos().size() == 0) {
             return null;
         }
 
         // TODO(b/298452477) Handle monochrome icons.
         // In the rare case the archived app defined more than two launcher activities, we choose
         // the first one arbitrarily.
-        return includeCloudOverlay(decodeIcon(activityInfos.get(0)));
+        return includeCloudOverlay(decodeIcon(archiveState.getActivityInfos().get(0)));
+    }
+
+    /**
+     * This method first checks the ArchiveState for the provided userId and then tries to fallback
+     * to other users if the current user is not archived.
+     *
+     * <p> This fallback behaviour is required for archived apps to fit into the multi-user world
+     * where APKs are shared across users. E.g. current ways of fetching icons for apps that are
+     * only installed on the work profile also work when executed on the personal profile if you're
+     * using {@link PackageManager#MATCH_UNINSTALLED_PACKAGES}. Resource fetching from APKs is for
+     * the most part userId-agnostic, which we need to mimic here in order for existing methods
+     * like {@link PackageManager#getApplicationIcon} to continue working.
+     *
+     * @return {@link ArchiveState} for {@code userId} if present. If not present, false back to an
+     * arbitrary userId. If no user is archived, returns null.
+     */
+    @Nullable
+    private ArchiveState getAnyArchiveState(PackageStateInternal ps, int userId) {
+        PackageUserStateInternal userState = ps.getUserStateOrDefault(userId);
+        if (isArchived(userState)) {
+            return userState.getArchiveState();
+        }
+
+        for (int i = 0; i < ps.getUserStates().size(); i++) {
+            userState = ps.getUserStates().valueAt(i);
+            if (isArchived(userState)) {
+                return userState.getArchiveState();
+            }
+        }
+
+        return null;
     }
 
     @VisibleForTesting
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 7d6dd62..2942bbb 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -821,6 +821,18 @@
             params.installFlags &= ~PackageManager.INSTALL_BYPASS_LOW_TARGET_SDK_BLOCK;
         }
 
+        params.installFlags &= ~PackageManager.INSTALL_UNARCHIVE;
+        if (Flags.archiving() && params.appPackageName != null) {
+            PackageStateInternal ps = mPm.snapshotComputer().getPackageStateInternal(
+                    params.appPackageName, SYSTEM_UID);
+            if (ps != null
+                    && PackageArchiver.isArchived(ps.getUserStateOrDefault(userId))
+                    && PackageArchiver.getResponsibleInstallerPackage(ps)
+                            .equals(requestedInstallerPackageName)) {
+                params.installFlags |= PackageManager.INSTALL_UNARCHIVE;
+            }
+        }
+
         if ((params.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0
                 && !PackageManagerServiceUtils.isSystemOrRootOrShell(callingUid)
                 && (snapshot.getFlagsForUid(callingUid) & ApplicationInfo.FLAG_SYSTEM)
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 47d1df5..4adb60c 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -168,6 +168,7 @@
 import com.android.internal.content.NativeLibraryHelper;
 import com.android.internal.messages.nano.SystemMessageProto;
 import com.android.internal.os.SomeArgs;
+import com.android.internal.pm.pkg.parsing.ParsingPackageUtils;
 import com.android.internal.security.VerityUtils;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.CollectionUtils;
@@ -181,7 +182,6 @@
 import com.android.server.pm.dex.DexManager;
 import com.android.server.pm.pkg.AndroidPackage;
 import com.android.server.pm.pkg.PackageStateInternal;
-import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
 
 import libcore.io.IoUtils;
 import libcore.util.EmptyArray;
diff --git a/services/core/java/com/android/server/pm/PackageManagerInternalBase.java b/services/core/java/com/android/server/pm/PackageManagerInternalBase.java
index b281808..c737b45 100644
--- a/services/core/java/com/android/server/pm/PackageManagerInternalBase.java
+++ b/services/core/java/com/android/server/pm/PackageManagerInternalBase.java
@@ -97,7 +97,16 @@
     @Deprecated
     public final List<ApplicationInfo> getInstalledApplications(
             @PackageManager.ApplicationInfoFlagsBits long flags, int userId, int callingUid) {
-        return snapshot().getInstalledApplications(flags, userId, callingUid);
+        return snapshot().getInstalledApplications(flags, userId, callingUid,
+                /* forceAllowCrossUser= */ false);
+    }
+
+    @Override
+    @Deprecated
+    public final List<ApplicationInfo> getInstalledApplicationsCrossUser(
+            @PackageManager.ApplicationInfoFlagsBits long flags, int userId, int callingUid) {
+        return snapshot().getInstalledApplications(flags, userId, callingUid,
+                /* forceAllowCrossUser= */ true);
     }
 
     @Override
@@ -753,13 +762,14 @@
     }
 
     @Override
-    public boolean isPackageQuarantined(@NonNull String packageName,
-            @UserIdInt int userId) {
+    public boolean isPackageQuarantined(@NonNull String packageName, @UserIdInt int userId)
+            throws PackageManager.NameNotFoundException {
         return snapshot().isPackageQuarantinedForUser(packageName, userId);
     }
 
     @Override
-    public boolean isPackageStopped(@NonNull String packageName, @UserIdInt int userId) {
+    public boolean isPackageStopped(@NonNull String packageName, @UserIdInt int userId)
+            throws PackageManager.NameNotFoundException {
         return snapshot().isPackageStoppedForUser(packageName, userId);
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 968ea66..56365b6 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -185,6 +185,7 @@
 import com.android.internal.pm.parsing.pkg.ParsedPackage;
 import com.android.internal.pm.pkg.component.ParsedInstrumentation;
 import com.android.internal.pm.pkg.component.ParsedMainComponent;
+import com.android.internal.pm.pkg.parsing.ParsingPackageUtils;
 import com.android.internal.telephony.CarrierAppUtils;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.CollectionUtils;
@@ -238,7 +239,6 @@
 import com.android.server.pm.pkg.mutate.PackageStateMutator;
 import com.android.server.pm.pkg.mutate.PackageStateWrite;
 import com.android.server.pm.pkg.mutate.PackageUserStateWrite;
-import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
 import com.android.server.pm.resolution.ComponentResolver;
 import com.android.server.pm.resolution.ComponentResolverApi;
 import com.android.server.pm.verify.domain.DomainVerificationManagerInternal;
@@ -1540,6 +1540,7 @@
                 continue;
             }
             pkgSetting
+                    .setPkg(null)
                     .modifyUserState(userId)
                     .setInstalled(false)
                     .setArchiveState(archiveState);
@@ -2012,6 +2013,16 @@
             public boolean hasFeature(String feature) {
                 return PackageManagerService.this.hasSystemFeature(feature, 0);
             }
+
+            @Override
+            public Set<String> getHiddenApiWhitelistedApps() {
+                return SystemConfig.getInstance().getHiddenApiWhitelistedApps();
+            }
+
+            @Override
+            public Set<String> getInstallConstraintsAllowlist() {
+                return SystemConfig.getInstance().getInstallConstraintsAllowlist();
+            }
         };
 
         // CHECKSTYLE:ON IndentationCheck
@@ -3043,6 +3054,7 @@
         }
     }
 
+    @NonNull
     int[] resolveUserIds(int userId) {
         return (userId == UserHandle.USER_ALL) ? mUserManager.getUserIds() : new int[] { userId };
     }
@@ -4604,6 +4616,9 @@
                             userIds, null, broadcastAllowList, null,
                             null);
                 });
+                mPackageMonitorCallbackHelper.notifyPackageMonitor(Intent.ACTION_PACKAGE_UNSTOPPED,
+                        packageName, extras, userIds, null /* instantUserIds */,
+                        broadcastAllowList, mHandler);
             }
         }
     }
@@ -5237,14 +5252,18 @@
 
         @Override
         public String getSuspendingPackage(String packageName, int userId) {
-            final int callingUid = Binder.getCallingUid();
-            final Computer snapshot = snapshot();
-            // This will do visibility checks as well.
-            if (!snapshot.isPackageSuspendedForUser(packageName, userId)) {
+            try {
+                final int callingUid = Binder.getCallingUid();
+                final Computer snapshot = snapshot();
+                // This will do visibility checks as well.
+                if (!snapshot.isPackageSuspendedForUser(packageName, userId)) {
+                    return null;
+                }
+                return mSuspendPackageHelper.getSuspendingPackage(snapshot, packageName, userId,
+                        callingUid);
+            } catch (PackageManager.NameNotFoundException e) {
                 return null;
             }
-            return mSuspendPackageHelper.getSuspendingPackage(snapshot, packageName, userId,
-                    callingUid);
         }
 
         @Override
@@ -7109,9 +7128,9 @@
                         if (info == null) {
                             continue;
                         }
-                        final List<VersionedPackage> dependents =
-                                computer.getPackagesUsingSharedLibrary(info, 0, Process.SYSTEM_UID,
-                                        userId);
+                        var usingSharedLibraryPair = computer.getPackagesUsingSharedLibrary(info, 0,
+                                Process.SYSTEM_UID, userId);
+                        final List<VersionedPackage> dependents = usingSharedLibraryPair.first;
                         if (dependents == null) {
                             continue;
                         }
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 215e952..322557b 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -2872,16 +2872,16 @@
                 UserHandle.USER_NULL, "runGrantRevokePermission"));
 
         List<PackageInfo> packageInfos;
+        PackageManager pm = mContext.createContextAsUser(translatedUser, 0).getPackageManager();
         if (pkg == null) {
-            packageInfos = mContext.getPackageManager().getInstalledPackages(
-                    PackageManager.GET_PERMISSIONS);
+            packageInfos = pm.getInstalledPackages(PackageManager.GET_PERMISSIONS);
         } else {
             try {
-                packageInfos = Collections.singletonList(
-                        mContext.getPackageManager().getPackageInfo(pkg,
-                                PackageManager.GET_PERMISSIONS));
+                packageInfos = Collections.singletonList(pm.getPackageInfo(pkg,
+                        PackageManager.GET_PERMISSIONS));
             } catch (NameNotFoundException e) {
                 getErrPrintWriter().println("Error: package not found");
+                getOutPrintWriter().println("Failure [package not found]");
                 return 1;
             }
         }
diff --git a/services/core/java/com/android/server/pm/PackageMonitorCallbackHelper.java b/services/core/java/com/android/server/pm/PackageMonitorCallbackHelper.java
index fa9409f..1bb0730 100644
--- a/services/core/java/com/android/server/pm/PackageMonitorCallbackHelper.java
+++ b/services/core/java/com/android/server/pm/PackageMonitorCallbackHelper.java
@@ -188,7 +188,9 @@
                 || TextUtils.equals(action, Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE)
                 || TextUtils.equals(action, Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)
                 || TextUtils.equals(action, Intent.ACTION_PACKAGE_DATA_CLEARED)
-                || TextUtils.equals(action, Intent.ACTION_PACKAGE_RESTARTED);
+                || TextUtils.equals(action, Intent.ACTION_PACKAGE_RESTARTED)
+                || TextUtils.equals(action, Intent.ACTION_PACKAGE_UNSTOPPED);
+
     }
 
     private void doNotifyCallbacksByIntent(Intent intent, int userId,
diff --git a/services/core/java/com/android/server/pm/PackageRemovedInfo.java b/services/core/java/com/android/server/pm/PackageRemovedInfo.java
index 7ee1772..881b0b3 100644
--- a/services/core/java/com/android/server/pm/PackageRemovedInfo.java
+++ b/services/core/java/com/android/server/pm/PackageRemovedInfo.java
@@ -25,7 +25,7 @@
     String mRemovedPackage;
     String mInstallerPackageName;
     int mUid = -1;
-    int mRemovedAppId = -1;
+    boolean mIsAppIdRemoved = false;
     int[] mOrigUsers;
     int[] mRemovedUsers = null;
     int[] mBroadcastUsers = null;
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 174df44..7d0a1f6 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -123,11 +123,15 @@
     @Nullable
     private Map<String, Set<String>> mimeGroups;
 
+    // TODO(b/314036181): encapsulate all these fields for usesSdk, instead of having three
+    //  separate arrays.
     @Nullable
     private String[] usesSdkLibraries;
 
     @Nullable
     private long[] usesSdkLibrariesVersionsMajor;
+    @Nullable
+    private boolean[] usesSdkLibrariesOptional;
 
     @Nullable
     private String[] usesStaticLibraries;
@@ -701,6 +705,9 @@
         usesSdkLibrariesVersionsMajor = other.usesSdkLibrariesVersionsMajor != null
                 ? Arrays.copyOf(other.usesSdkLibrariesVersionsMajor,
                 other.usesSdkLibrariesVersionsMajor.length) : null;
+        usesSdkLibrariesOptional = other.usesSdkLibrariesOptional != null
+                ? Arrays.copyOf(other.usesSdkLibrariesOptional,
+                other.usesSdkLibrariesOptional.length) : null;
 
         usesStaticLibraries = other.usesStaticLibraries != null
                 ? Arrays.copyOf(other.usesStaticLibraries,
@@ -1344,6 +1351,12 @@
 
     @NonNull
     @Override
+    public boolean[] getUsesSdkLibrariesOptional() {
+        return usesSdkLibrariesOptional == null ? EmptyArray.BOOLEAN : usesSdkLibrariesOptional;
+    }
+
+    @NonNull
+    @Override
     public String[] getUsesStaticLibraries() {
         return usesStaticLibraries == null ? EmptyArray.STRING : usesStaticLibraries;
     }
@@ -1444,6 +1457,12 @@
         return this;
     }
 
+    public PackageSetting setUsesSdkLibrariesOptional(boolean[] usesSdkLibrariesOptional) {
+        this.usesSdkLibrariesOptional = usesSdkLibrariesOptional;
+        onChanged();
+        return this;
+    }
+
     public PackageSetting setUsesStaticLibraries(String[] usesStaticLibraries) {
         this.usesStaticLibraries = usesStaticLibraries;
         onChanged();
diff --git a/services/core/java/com/android/server/pm/ReconcilePackageUtils.java b/services/core/java/com/android/server/pm/ReconcilePackageUtils.java
index bb0017c..5e8778d 100644
--- a/services/core/java/com/android/server/pm/ReconcilePackageUtils.java
+++ b/services/core/java/com/android/server/pm/ReconcilePackageUtils.java
@@ -20,19 +20,23 @@
 import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
 import static android.content.pm.SigningDetails.CapabilityMergeRule.MERGE_RESTRICTED_CAPABILITY;
 
+import static com.android.server.pm.PackageManagerService.SCAN_AS_APEX;
 import static com.android.server.pm.PackageManagerService.SCAN_BOOTING;
 import static com.android.server.pm.PackageManagerService.SCAN_DONT_KILL_APP;
+import static com.android.server.pm.PackageManagerService.TAG;
 
 import android.content.pm.PackageManager;
 import android.content.pm.SharedLibraryInfo;
 import android.content.pm.SigningDetails;
+import android.os.Build;
 import android.os.SystemProperties;
 import android.util.ArrayMap;
 import android.util.Log;
+import android.util.Slog;
 
 import com.android.internal.pm.parsing.pkg.ParsedPackage;
+import com.android.internal.pm.pkg.parsing.ParsingPackageUtils;
 import com.android.server.pm.pkg.AndroidPackage;
-import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
 import com.android.server.utils.WatchedLongSparseArray;
 
 import java.util.ArrayList;
@@ -49,6 +53,8 @@
  * as install) led to the request.
  */
 final class ReconcilePackageUtils {
+    private static final boolean ALLOW_NON_PRELOADS_SYSTEM_SIGNATURE = Build.IS_DEBUGGABLE;
+
     public static List<ReconciledPackage> reconcilePackages(
             List<InstallRequest> installRequests,
             Map<String, AndroidPackage> allPackages,
@@ -90,6 +96,8 @@
             }
         }
 
+        final AndroidPackage systemPackage = allPackages.get(KnownPackages.SYSTEM_PACKAGE_NAME);
+
         for (InstallRequest installRequest : installRequests) {
             final String installPackageName = installRequest.getParsedPackage().getPackageName();
             final List<SharedLibraryInfo> allowedSharedLibInfos =
@@ -133,6 +141,9 @@
             if (parsedPackage != null) {
                 signingDetails = parsedPackage.getSigningDetails();
             }
+            final boolean isSystemPackage =
+                    ((parseFlags & ParsingPackageUtils.PARSE_IS_SYSTEM_DIR) != 0);
+            final boolean isApex = (scanFlags & SCAN_AS_APEX) != 0;
             SharedUserSetting sharedUserSetting = settings.getSharedUserSettingLPr(
                     signatureCheckPs);
             if (ksms.shouldCheckUpgradeKeySetLocked(
@@ -141,7 +152,7 @@
                     // We just determined the app is signed correctly, so bring
                     // over the latest parsed certs.
                 } else {
-                    if ((parseFlags & ParsingPackageUtils.PARSE_IS_SYSTEM_DIR) == 0) {
+                    if (!isSystemPackage) {
                         throw new ReconcileFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
                                 "Package " + parsedPackage.getPackageName()
                                         + " upgrade keys do not match the previously installed"
@@ -168,9 +179,24 @@
                         removeAppKeySetData = true;
                     }
 
+                    if (!installRequest.isInstallSystem() && !isSystemPackage && !isApex
+                            && signingDetails != null
+                            && systemPackage != null && systemPackage.getSigningDetails() != null
+                            && systemPackage.getSigningDetails().checkCapability(
+                                    signingDetails,
+                                    SigningDetails.CertCapabilities.PERMISSION)) {
+                        Slog.d(TAG, "Non-preload app associated with system signature: "
+                                + signatureCheckPs.getPackageName());
+                        if (!ALLOW_NON_PRELOADS_SYSTEM_SIGNATURE) {
+                            throw new ReconcileFailure(
+                                    INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
+                                    "Non-preload app associated with system signature: "
+                                            + signatureCheckPs.getPackageName());
+                        }
+                    }
+
                     // if this is is a sharedUser, check to see if the new package is signed by a
-                    // newer
-                    // signing certificate than the existing one, and if so, copy over the new
+                    // newer signing certificate than the existing one, and if so, copy over the new
                     // details
                     if (sharedUserSetting != null) {
                         // Attempt to merge the existing lineage for the shared SigningDetails with
@@ -203,7 +229,7 @@
                         }
                     }
                 } catch (PackageManagerException e) {
-                    if ((parseFlags & ParsingPackageUtils.PARSE_IS_SYSTEM_DIR) == 0) {
+                    if (!isSystemPackage) {
                         throw new ReconcileFailure(e);
                     }
                     signingDetails = parsedPackage.getSigningDetails();
diff --git a/services/core/java/com/android/server/pm/RemovePackageHelper.java b/services/core/java/com/android/server/pm/RemovePackageHelper.java
index 7ee32fb..f42b43f 100644
--- a/services/core/java/com/android/server/pm/RemovePackageHelper.java
+++ b/services/core/java/com/android/server/pm/RemovePackageHelper.java
@@ -44,12 +44,12 @@
 import android.util.SparseBooleanArray;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.pm.parsing.pkg.AndroidPackageLegacyUtils;
+import com.android.internal.pm.parsing.pkg.PackageImpl;
 import com.android.internal.pm.pkg.component.ParsedInstrumentation;
 import com.android.internal.util.ArrayUtils;
 import com.android.server.pm.Installer.LegacyDexoptDisabledException;
 import com.android.server.pm.parsing.PackageCacher;
-import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
-import com.android.server.pm.parsing.pkg.PackageImpl;
 import com.android.server.pm.permission.PermissionManagerServiceInternal;
 import com.android.server.pm.pkg.AndroidPackage;
 import com.android.server.pm.pkg.PackageStateInternal;
@@ -167,7 +167,7 @@
             if (removedPackage != null) {
                 // TODO: Use PackageState for isSystem
                 cleanPackageDataStructuresLILPw(removedPackage,
-                        AndroidPackageUtils.isSystem(removedPackage), chatty);
+                        AndroidPackageLegacyUtils.isSystem(removedPackage), chatty);
             }
         }
     }
@@ -252,88 +252,129 @@
         }
     }
 
-    public void clearPackageStateForUserLIF(PackageSetting ps, int userId,
-            PackageRemovedInfo outInfo, int flags) {
+    /**
+     * This method clears the data and states stored in the system that are related to the
+     * package being deleted and the target user, including the data directory.
+     * If the DELETE_KEEP_DATA flag is set, everything is preserved except ART profiles.
+     * Make sure this flag is set for partially installed apps. If not it's meaningless to
+     * delete a partially installed application.
+     */
+    public void clearPackageStateForUserLIF(PackageSetting ps, int userId, int flags) {
+        final String packageName = ps.getPackageName();
+        // Step 1: always destroy app profiles.
+        mAppDataHelper.destroyAppProfilesLIF(packageName);
+
+        // Everything else is preserved if the DELETE_KEEP_DATA flag is on
+        if ((flags & PackageManager.DELETE_KEEP_DATA) != 0) {
+            return;
+        }
+
         final AndroidPackage pkg;
         final SharedUserSetting sus;
         synchronized (mPm.mLock) {
-            pkg = mPm.mPackages.get(ps.getPackageName());
+            pkg = mPm.mPackages.get(packageName);
             sus = mPm.mSettings.getSharedUserSettingLPr(ps);
         }
 
-        mAppDataHelper.destroyAppProfilesLIF(pkg);
+        final AndroidPackage resolvedPkg;
+        if (pkg != null) {
+            resolvedPkg = pkg;
+        } else {
+            // We don't have a parsed package when it lives on an ejected
+            // adopted storage device, so fake something together
+            resolvedPkg = PackageImpl.buildFakeForDeletion(packageName, ps.getVolumeUuid());
+        }
 
-        final List<AndroidPackage> sharedUserPkgs =
-                sus != null ? sus.getPackages() : Collections.emptyList();
+        // Step 2: destroy app data.
+        mAppDataHelper.destroyAppDataLIF(resolvedPkg, userId,
+                FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL);
+        if (userId != UserHandle.USER_ALL) {
+            ps.setCeDataInode(-1, userId);
+            ps.setDeDataInode(-1, userId);
+        }
+
         final PreferredActivityHelper preferredActivityHelper = new PreferredActivityHelper(mPm,
                 mBroadcastHelper);
-        final int[] userIds = (userId == UserHandle.USER_ALL) ? mUserManagerInternal.getUserIds()
-                : new int[] {userId};
-        for (int nextUserId : userIds) {
+        if (userId == UserHandle.USER_ALL) {
             if (DEBUG_REMOVE) {
-                Slog.d(TAG, "Updating package:" + ps.getPackageName() + " install state for user:"
-                        + nextUserId);
+                Slog.d(TAG, "Clear package:" + packageName + " state for all users");
             }
-            if ((flags & PackageManager.DELETE_KEEP_DATA) == 0) {
-                mAppDataHelper.destroyAppDataLIF(pkg, nextUserId,
-                        FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL);
-                ps.setCeDataInode(-1, nextUserId);
-                ps.setDeDataInode(-1, nextUserId);
+            // Step 3: inform DomainVerificationManager.
+            mPm.mDomainVerificationManager.clearPackage(packageName);
+            synchronized (mPm.mLock) {
+                // Step 3.1 (only for USER_ALL): notify KeySetManagerService.
+                mPm.mSettings.getKeySetManagerService().removeAppKeySetDataLPw(packageName);
+                // Step 3.2 (only for USER_ALL): update installer ownership.
+                mPm.mInjector.getUpdateOwnershipHelper().removeUpdateOwnerDenyList(packageName);
+                // Step 3.3 (only for USER_ALL): update AppsFilter.
+                final Computer snapshot = mPm.snapshotComputer();
+                mPm.mAppsFilter.removePackage(snapshot,
+                        snapshot.getPackageStateInternal(packageName));
+                // Step 4: clear perferred activities.
+                final SparseBooleanArray changedUsers = new SparseBooleanArray();
+                mPm.clearPackagePreferredActivitiesLPw(
+                        packageName, changedUsers, UserHandle.USER_ALL);
+                mPm.mInjector.getBackgroundHandler().post(() -> {
+                    if (changedUsers.size() > 0) {
+                        preferredActivityHelper.updateDefaultHomeNotLocked(mPm.snapshotComputer(),
+                                changedUsers);
+                        mBroadcastHelper.sendPreferredActivityChangedBroadcast(UserHandle.USER_ALL);
+                    }
+                });
+                // Step 5: inform PermissionManager.
+                // This has to be done after the removal from mSettings in removePackageDataLIF.
             }
-            mAppDataHelper.clearKeystoreData(nextUserId, ps.getAppId());
-            preferredActivityHelper.clearPackagePreferredActivities(ps.getPackageName(),
-                    nextUserId);
-            mPm.mDomainVerificationManager.clearPackageForUser(ps.getPackageName(), nextUserId);
+        } else {
+            if (DEBUG_REMOVE) {
+                Slog.d(TAG, "Clear package:" + packageName + " state for user:" + userId);
+            }
+            // Step 3: inform DomainVerificationManager.
+            mPm.mDomainVerificationManager.clearPackageForUser(packageName, userId);
+            // Step 4: clear perferred activities.
+            preferredActivityHelper.clearPackagePreferredActivities(packageName, userId);
+            // Step 5: inform PermissionManager.
+            List<AndroidPackage> sharedUserPkgs =
+                    sus != null ? sus.getPackages() : Collections.emptyList();
+            mPermissionManager.onPackageUninstalled(packageName, ps.getAppId(), ps, pkg,
+                    sharedUserPkgs, userId);
         }
-        mPermissionManager.onPackageUninstalled(ps.getPackageName(), ps.getAppId(), ps, pkg,
-                sharedUserPkgs, userId);
 
-        if (outInfo != null) {
-            if ((flags & PackageManager.DELETE_KEEP_DATA) == 0) {
-                outInfo.mDataRemoved = true;
+        // Step 6: detroy keystore data.
+        mPm.mInjector.getBackgroundHandler().post(() -> {
+            try {
+                Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER,
+                        "clearKeystoreData:" + ps.getAppId() + " for user: " + userId);
+                mAppDataHelper.clearKeystoreData(userId, ps.getAppId());
+            } finally {
+                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
             }
-            outInfo.mRemovedPackage = ps.getPackageName();
-            outInfo.mInstallerPackageName = ps.getInstallSource().mInstallerPackageName;
-            outInfo.mIsStaticSharedLib = pkg != null && pkg.getStaticSharedLibraryName() != null;
-            outInfo.mRemovedAppId = ps.getAppId();
-            outInfo.mBroadcastUsers = outInfo.mRemovedUsers;
-            outInfo.mIsExternal = ps.isExternalStorage();
-            outInfo.mRemovedPackageVersionCode = ps.getVersionCode();
-        }
+        });
     }
 
     // Called to clean up disabled system packages
     public void removePackageData(final PackageSetting deletedPs, @NonNull int[] allUserHandles) {
         synchronized (mPm.mInstallLock) {
-            removePackageDataLIF(deletedPs, allUserHandles, /* outInfo= */ null,
+            removePackageDataLIF(deletedPs, allUserHandles, new PackageRemovedInfo(),
                     /* flags= */ 0, /* writeSettings= */ false);
         }
     }
 
     /*
-     * This method deletes the package from internal data structures. If the DELETE_KEEP_DATA
-     * flag is not set, the data directory is removed as well.
-     * make sure this flag is set for partially installed apps. If not it's meaningless to
-     * delete a partially installed application.
+     * This method deletes the package from internal data structures such as mPackages / mSettings.
      */
     @GuardedBy("mPm.mInstallLock")
     public void removePackageDataLIF(final PackageSetting deletedPs, @NonNull int[] allUserHandles,
-            PackageRemovedInfo outInfo, int flags, boolean writeSettings) {
+            @NonNull PackageRemovedInfo outInfo, int flags, boolean writeSettings) {
         String packageName = deletedPs.getPackageName();
         if (DEBUG_REMOVE) Slog.d(TAG, "removePackageDataLI: " + deletedPs);
         // Retrieve object to delete permissions for shared user later on
         final AndroidPackage deletedPkg = deletedPs.getPkg();
-        if (outInfo != null) {
-            outInfo.mRemovedPackage = packageName;
-            outInfo.mInstallerPackageName = deletedPs.getInstallSource().mInstallerPackageName;
-            outInfo.mIsStaticSharedLib = deletedPkg != null
-                    && deletedPkg.getStaticSharedLibraryName() != null;
-            outInfo.populateBroadcastUsers(deletedPs);
-            outInfo.mIsExternal = deletedPs.isExternalStorage();
-            outInfo.mRemovedPackageVersionCode = deletedPs.getVersionCode();
-        }
 
-        removePackageLI(deletedPs.getPackageName(), (flags & PackageManager.DELETE_CHATTY) != 0);
+        // Delete all the data and states related to this package.
+        clearPackageStateForUserLIF(deletedPs, UserHandle.USER_ALL, flags);
+
+        // Delete from mPackages
+        removePackageLI(packageName, (flags & PackageManager.DELETE_CHATTY) != 0);
         if (!deletedPs.isSystem()) {
             // A non-system app's AndroidPackage object has been removed from the service.
             // Explicitly nullify the corresponding app's PackageSetting's pkg object to
@@ -343,44 +384,16 @@
         }
 
         if ((flags & PackageManager.DELETE_KEEP_DATA) == 0) {
-            final AndroidPackage resolvedPkg;
-            if (deletedPkg != null) {
-                resolvedPkg = deletedPkg;
-            } else {
-                // We don't have a parsed package when it lives on an ejected
-                // adopted storage device, so fake something together
-                resolvedPkg = PackageImpl.buildFakeForDeletion(deletedPs.getPackageName(),
-                        deletedPs.getVolumeUuid());
-            }
-            mAppDataHelper.destroyAppDataLIF(resolvedPkg, UserHandle.USER_ALL,
-                    FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL);
-            mAppDataHelper.destroyAppProfilesLIF(resolvedPkg);
-            if (outInfo != null) {
-                outInfo.mDataRemoved = true;
-            }
-        }
-
-        int removedAppId = -1;
-
-        // writer
-        if ((flags & PackageManager.DELETE_KEEP_DATA) == 0) {
+            // Delete from mSettings
             final SparseBooleanArray changedUsers = new SparseBooleanArray();
             synchronized (mPm.mLock) {
-                mPm.mDomainVerificationManager.clearPackage(deletedPs.getPackageName());
-                mPm.mSettings.getKeySetManagerService().removeAppKeySetDataLPw(packageName);
-                mPm.mInjector.getUpdateOwnershipHelper().removeUpdateOwnerDenyList(packageName);
-                final Computer snapshot = mPm.snapshotComputer();
-                mPm.mAppsFilter.removePackage(snapshot,
-                        snapshot.getPackageStateInternal(packageName));
-                removedAppId = mPm.mSettings.removePackageLPw(packageName);
-                if (outInfo != null) {
-                    outInfo.mRemovedAppId = removedAppId;
-                }
+                mPm.mSettings.removePackageLPw(packageName);
+                outInfo.mIsAppIdRemoved = true;
                 if (!mPm.mSettings.isDisabledSystemPackageLPr(packageName)) {
+                    final SharedUserSetting sus = mPm.mSettings.getSharedUserSettingLPr(deletedPs);
                     // If we don't have a disabled system package to reinstall, the package is
                     // really gone and its permission state should be removed.
-                    SharedUserSetting sus = mPm.mSettings.getSharedUserSettingLPr(deletedPs);
-                    List<AndroidPackage> sharedUserPkgs =
+                    final List<AndroidPackage> sharedUserPkgs =
                             sus != null ? sus.getPackages() : Collections.emptyList();
                     mPermissionManager.onPackageUninstalled(packageName, deletedPs.getAppId(),
                             deletedPs, deletedPkg, sharedUserPkgs, UserHandle.USER_ALL);
@@ -389,22 +402,10 @@
                         mPm.mSettings.checkAndConvertSharedUserSettingsLPw(sus);
                     }
                 }
-                mPm.clearPackagePreferredActivitiesLPw(
-                        deletedPs.getPackageName(), changedUsers, UserHandle.USER_ALL);
-
                 mPm.mSettings.removeRenamedPackageLPw(deletedPs.getRealName());
             }
-            if (changedUsers.size() > 0) {
-                mPm.mInjector.getBackgroundHandler().post(() -> {
-                    final PreferredActivityHelper preferredActivityHelper =
-                            new PreferredActivityHelper(mPm, mBroadcastHelper);
-                    preferredActivityHelper.updateDefaultHomeNotLocked(mPm.snapshotComputer(),
-                            changedUsers);
-                    mBroadcastHelper.sendPreferredActivityChangedBroadcast(UserHandle.USER_ALL);
-                });
-            }
-        } else if (!deletedPs.isSystem() && outInfo != null && !outInfo.mIsUpdate
-                && outInfo.mRemovedUsers != null && !outInfo.mIsExternal) {
+        } else if (!deletedPs.isSystem() && !outInfo.mIsUpdate
+                && outInfo.mRemovedUsers != null && !deletedPs.isExternalStorage()) {
             // For non-system uninstalls with DELETE_KEEP_DATA, set the installed state to false
             // for affected users. This does not apply to app updates where the old apk is replaced
             // but the old data remains.
@@ -421,10 +422,11 @@
                 deletedPs.setInstalled(/* installed= */ false, userId);
             }
         }
+
         // make sure to preserve per-user installed state if this removal was just
         // a downgrade of a system app to the factory package
         boolean installedStateChanged = false;
-        if (outInfo != null && outInfo.mOrigUsers != null && deletedPs.isSystem()) {
+        if (outInfo.mOrigUsers != null && deletedPs.isSystem()) {
             if (DEBUG_REMOVE) {
                 Slog.d(TAG, "Propagating install state across downgrade");
             }
@@ -452,20 +454,6 @@
                 mPm.mSettings.writeKernelMappingLPr(deletedPs);
             }
         }
-
-        if (removedAppId != -1) {
-            // A user ID was deleted here. Go through all users and remove it from KeyStore.
-            final int appIdToRemove = removedAppId;
-            mPm.mInjector.getBackgroundHandler().post(() -> {
-                try {
-                    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER,
-                            "clearKeystoreData:" + appIdToRemove);
-                    mAppDataHelper.clearKeystoreData(UserHandle.USER_ALL, appIdToRemove);
-                } finally {
-                    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
-                }
-            });
-        }
     }
 
     void cleanUpResources(File codeFile, String[] instructionSets) {
diff --git a/services/core/java/com/android/server/pm/ScanPackageUtils.java b/services/core/java/com/android/server/pm/ScanPackageUtils.java
index 53b84e6..5c6d61e 100644
--- a/services/core/java/com/android/server/pm/ScanPackageUtils.java
+++ b/services/core/java/com/android/server/pm/ScanPackageUtils.java
@@ -74,11 +74,13 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.pm.parsing.pkg.ParsedPackage;
+import com.android.internal.pm.pkg.component.ComponentMutateUtils;
 import com.android.internal.pm.pkg.component.ParsedActivity;
 import com.android.internal.pm.pkg.component.ParsedMainComponent;
 import com.android.internal.pm.pkg.component.ParsedProcess;
 import com.android.internal.pm.pkg.component.ParsedProvider;
 import com.android.internal.pm.pkg.component.ParsedService;
+import com.android.internal.pm.pkg.parsing.ParsingPackageUtils;
 import com.android.internal.util.ArrayUtils;
 import com.android.server.SystemConfig;
 import com.android.server.pm.parsing.PackageInfoUtils;
@@ -86,8 +88,6 @@
 import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
 import com.android.server.pm.pkg.AndroidPackage;
 import com.android.server.pm.pkg.PackageStateUtils;
-import com.android.server.pm.pkg.component.ComponentMutateUtils;
-import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
 import com.android.server.utils.WatchedArraySet;
 
 import dalvik.system.VMRuntime;
@@ -218,7 +218,8 @@
                     parsedPackage.getLongVersionCode(), pkgFlags, pkgPrivateFlags, user,
                     true /*allowInstall*/, instantApp, virtualPreload, isStoppedSystemApp,
                     UserManagerService.getInstance(), usesSdkLibraries,
-                    parsedPackage.getUsesSdkLibrariesVersionsMajor(), usesStaticLibraries,
+                    parsedPackage.getUsesSdkLibrariesVersionsMajor(),
+                    parsedPackage.getUsesSdkLibrariesOptional(), usesStaticLibraries,
                     parsedPackage.getUsesStaticLibrariesVersions(), parsedPackage.getMimeGroups(),
                     newDomainSetId,
                     parsedPackage.getTargetSdkVersion(), parsedPackage.getRestrictUpdateHash());
@@ -240,6 +241,7 @@
                     PackageInfoUtils.appInfoPrivateFlags(parsedPackage, pkgSetting),
                     UserManagerService.getInstance(),
                     usesSdkLibraries, parsedPackage.getUsesSdkLibrariesVersionsMajor(),
+                    parsedPackage.getUsesSdkLibrariesOptional(),
                     usesStaticLibraries, parsedPackage.getUsesStaticLibrariesVersions(),
                     parsedPackage.getMimeGroups(), newDomainSetId,
                     parsedPackage.getTargetSdkVersion(), parsedPackage.getRestrictUpdateHash());
diff --git a/services/core/java/com/android/server/pm/ScanRequest.java b/services/core/java/com/android/server/pm/ScanRequest.java
index 37cf30b..41e2a3f 100644
--- a/services/core/java/com/android/server/pm/ScanRequest.java
+++ b/services/core/java/com/android/server/pm/ScanRequest.java
@@ -22,8 +22,8 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.pm.parsing.pkg.ParsedPackage;
+import com.android.internal.pm.pkg.parsing.ParsingPackageUtils;
 import com.android.server.pm.pkg.AndroidPackage;
-import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
 
 /** A package to be scanned */
 @VisibleForTesting
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 2cbf714..460bbb7 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -89,6 +89,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.BackgroundThread;
+import com.android.internal.pm.parsing.pkg.PackageImpl;
 import com.android.internal.pm.pkg.component.ParsedComponent;
 import com.android.internal.pm.pkg.component.ParsedIntentInfo;
 import com.android.internal.pm.pkg.component.ParsedPermission;
@@ -339,6 +340,8 @@
     private static final String ATTR_DISTRACTION_FLAGS = "distraction_flags";
     private static final String ATTR_SUSPENDED = "suspended";
     private static final String ATTR_SUSPENDING_PACKAGE = "suspending-package";
+
+    private static final String ATTR_OPTIONAL = "optional";
     /**
      * @deprecated Legacy attribute, kept only for upgrading from P builds.
      */
@@ -942,6 +945,7 @@
             ret.setLongVersionCode(p.getVersionCode());
             ret.setUsesSdkLibraries(p.getUsesSdkLibraries());
             ret.setUsesSdkLibrariesVersionsMajor(p.getUsesSdkLibrariesVersionsMajor());
+            ret.setUsesSdkLibrariesOptional(p.getUsesSdkLibrariesOptional());
             ret.setUsesStaticLibraries(p.getUsesStaticLibraries());
             ret.setUsesStaticLibrariesVersions(p.getUsesStaticLibrariesVersions());
             ret.setMimeGroups(p.getMimeGroups());
@@ -1061,9 +1065,9 @@
             UserHandle installUser, boolean allowInstall, boolean instantApp,
             boolean virtualPreload, boolean isStoppedSystemApp, UserManagerService userManager,
             String[] usesSdkLibraries, long[] usesSdkLibrariesVersions,
-            String[] usesStaticLibraries, long[] usesStaticLibrariesVersions,
-            Set<String> mimeGroupNames, @NonNull UUID domainSetId,
-            int targetSdkVersion, byte[] restrictUpdatedHash) {
+            boolean[] usesSdkLibrariesOptional, String[] usesStaticLibraries,
+            long[] usesStaticLibrariesVersions, Set<String> mimeGroupNames,
+            @NonNull UUID domainSetId, int targetSdkVersion, byte[] restrictUpdatedHash) {
         final PackageSetting pkgSetting;
         if (originalPkg != null) {
             if (PackageManagerService.DEBUG_UPGRADE) Log.v(PackageManagerService.TAG, "Package "
@@ -1079,6 +1083,7 @@
                     .setLongVersionCode(versionCode)
                     .setUsesSdkLibraries(usesSdkLibraries)
                     .setUsesSdkLibrariesVersionsMajor(usesSdkLibrariesVersions)
+                    .setUsesSdkLibrariesOptional(usesSdkLibrariesOptional)
                     .setUsesStaticLibraries(usesStaticLibraries)
                     .setUsesStaticLibrariesVersions(usesStaticLibrariesVersions)
                     // Update new package state.
@@ -1096,6 +1101,7 @@
                     pkgPrivateFlags, domainSetId)
                     .setUsesSdkLibraries(usesSdkLibraries)
                     .setUsesSdkLibrariesVersionsMajor(usesSdkLibrariesVersions)
+                    .setUsesSdkLibrariesOptional(usesSdkLibrariesOptional)
                     .setUsesStaticLibraries(usesStaticLibraries)
                     .setUsesStaticLibrariesVersions(usesStaticLibrariesVersions)
                     .setLegacyNativeLibraryPath(legacyNativeLibraryPath)
@@ -1218,6 +1224,7 @@
             @Nullable String primaryCpuAbi, @Nullable String secondaryCpuAbi, int pkgFlags,
             int pkgPrivateFlags, @NonNull UserManagerService userManager,
             @Nullable String[] usesSdkLibraries, @Nullable long[] usesSdkLibrariesVersions,
+            @Nullable boolean[] usesSdkLibrariesOptional,
             @Nullable String[] usesStaticLibraries, @Nullable long[] usesStaticLibrariesVersions,
             @Nullable Set<String> mimeGroupNames, @NonNull UUID domainSetId,
             int targetSdkVersion, byte[] restrictUpdatedHash)
@@ -1277,12 +1284,17 @@
                 .setRestrictUpdateHash(restrictUpdatedHash);
         // Update SDK library dependencies if needed.
         if (usesSdkLibraries != null && usesSdkLibrariesVersions != null
-                && usesSdkLibraries.length == usesSdkLibrariesVersions.length) {
+                && usesSdkLibrariesOptional != null
+                && usesSdkLibraries.length == usesSdkLibrariesVersions.length
+                && usesSdkLibraries.length == usesSdkLibrariesOptional.length) {
             pkgSetting.setUsesSdkLibraries(usesSdkLibraries)
-                    .setUsesSdkLibrariesVersionsMajor(usesSdkLibrariesVersions);
+                    .setUsesSdkLibrariesVersionsMajor(usesSdkLibrariesVersions)
+                    .setUsesSdkLibrariesOptional(usesSdkLibrariesOptional);
         } else {
             pkgSetting.setUsesSdkLibraries(null)
-                    .setUsesSdkLibrariesVersionsMajor(null);
+                    .setUsesSdkLibrariesVersionsMajor(null)
+                    .setUsesSdkLibrariesOptional(null);
+
         }
 
         // Update static shared library dependencies if needed.
@@ -2537,12 +2549,15 @@
             throws IOException, XmlPullParserException {
         String libName = parser.getAttributeValue(null, ATTR_NAME);
         long libVersion = parser.getAttributeLong(null, ATTR_VERSION, -1);
+        boolean optional = parser.getAttributeBoolean(null, ATTR_OPTIONAL, true);
 
         if (libName != null && libVersion >= 0) {
             outPs.setUsesSdkLibraries(ArrayUtils.appendElement(String.class,
                     outPs.getUsesSdkLibraries(), libName));
             outPs.setUsesSdkLibrariesVersionsMajor(ArrayUtils.appendLong(
                     outPs.getUsesSdkLibrariesVersionsMajor(), libVersion));
+            outPs.setUsesSdkLibrariesOptional(ArrayUtils.appendBoolean(
+                    outPs.getUsesSdkLibrariesOptional(), optional));
         }
 
         XmlUtils.skipCurrentTag(parser);
@@ -2564,7 +2579,7 @@
     }
 
     void writeUsesSdkLibLPw(TypedXmlSerializer serializer, String[] usesSdkLibraries,
-            long[] usesSdkLibraryVersions) throws IOException {
+            long[] usesSdkLibraryVersions, boolean[] usesSdkLibrariesOptional) throws IOException {
         if (ArrayUtils.isEmpty(usesSdkLibraries) || ArrayUtils.isEmpty(usesSdkLibraryVersions)
                 || usesSdkLibraries.length != usesSdkLibraryVersions.length) {
             return;
@@ -2573,9 +2588,11 @@
         for (int i = 0; i < libCount; i++) {
             final String libName = usesSdkLibraries[i];
             final long libVersion = usesSdkLibraryVersions[i];
+            boolean libOptional = usesSdkLibrariesOptional[i];
             serializer.startTag(null, TAG_USES_SDK_LIB);
             serializer.attribute(null, ATTR_NAME, libName);
             serializer.attributeLong(null, ATTR_VERSION, libVersion);
+            serializer.attributeBoolean(null, ATTR_OPTIONAL, libOptional);
             serializer.endTag(null, TAG_USES_SDK_LIB);
         }
     }
@@ -3106,7 +3123,8 @@
         }
 
         writeUsesSdkLibLPw(serializer, pkg.getUsesSdkLibraries(),
-                pkg.getUsesSdkLibrariesVersionsMajor());
+                pkg.getUsesSdkLibrariesVersionsMajor(), pkg.getUsesSdkLibrariesOptional());
+
 
         writeUsesStaticLibLPw(serializer, pkg.getUsesStaticLibraries(),
                 pkg.getUsesStaticLibrariesVersions());
@@ -3206,7 +3224,7 @@
         }
 
         writeUsesSdkLibLPw(serializer, pkg.getUsesSdkLibraries(),
-                pkg.getUsesSdkLibrariesVersionsMajor());
+                pkg.getUsesSdkLibrariesVersionsMajor(), pkg.getUsesSdkLibrariesOptional());
 
         writeUsesStaticLibLPw(serializer, pkg.getUsesStaticLibraries(),
                 pkg.getUsesStaticLibrariesVersions());
@@ -5091,12 +5109,14 @@
 
             List<String> usesSdkLibraries = pkg.getUsesSdkLibraries();
             long[] usesSdkLibrariesVersionsMajor = pkg.getUsesSdkLibrariesVersionsMajor();
+            boolean[] usesSdkLibrariesOptional = pkg.getUsesSdkLibrariesOptional();
             if (usesSdkLibraries.size() > 0) {
                 pw.print(prefix); pw.println("  usesSdkLibraries:");
                 for (int i = 0, size = usesSdkLibraries.size(); i < size; ++i) {
                     pw.print(prefix); pw.print("    ");
                     pw.print(usesSdkLibraries.get(i)); pw.print(" version:");
-                    pw.println(usesSdkLibrariesVersionsMajor[i]);
+                    pw.println(usesSdkLibrariesVersionsMajor[i]); pw.print(" optional:");
+                    pw.println(usesSdkLibrariesOptional[i]);
                 }
             }
 
diff --git a/services/core/java/com/android/server/pm/SharedLibrariesImpl.java b/services/core/java/com/android/server/pm/SharedLibrariesImpl.java
index 9384c13..ec8af2e 100644
--- a/services/core/java/com/android/server/pm/SharedLibrariesImpl.java
+++ b/services/core/java/com/android/server/pm/SharedLibrariesImpl.java
@@ -16,7 +16,6 @@
 
 package com.android.server.pm;
 
-import static android.content.pm.Flags.sdkLibIndependence;
 import static android.content.pm.PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
 import static android.content.pm.PackageManager.INSTALL_FAILED_SHARED_LIBRARY_BAD_CERTIFICATE_DIGEST;
 
@@ -28,6 +27,7 @@
 import android.annotation.Nullable;
 import android.compat.annotation.ChangeId;
 import android.compat.annotation.EnabledAfter;
+import android.content.pm.Flags;
 import android.content.pm.PackageManager;
 import android.content.pm.SharedLibraryInfo;
 import android.content.pm.Signature;
@@ -82,6 +82,8 @@
 public final class SharedLibrariesImpl implements SharedLibrariesRead, Watchable, Snappable {
     private static final boolean DEBUG_SHARED_LIBRARIES = false;
 
+    private static final String LIBRARY_TYPE_SDK = "sdk";
+
     /**
      * Apps targeting Android S and above need to declare dependencies to the public native
      * shared libraries that are defined by the device maker using {@code uses-native-library} tag
@@ -729,7 +731,7 @@
                                 ? PackageManager.DELETE_KEEP_DATA : 0;
                         synchronized (mPm.mInstallLock) {
                             mDeletePackageHelper.deletePackageLIF(pkg.getPackageName(), null, true,
-                                    mPm.mUserManager.getUserIds(), flags, null,
+                                    mPm.mUserManager.getUserIds(), flags, new PackageRemovedInfo(),
                                     true);
                         }
                     }
@@ -798,8 +800,9 @@
 
             // Remove the shared library overlays from its dependent packages.
             for (int currentUserId : mPm.mUserManager.getUserIds()) {
-                final List<VersionedPackage> dependents = snapshot.getPackagesUsingSharedLibrary(
-                        libraryInfo, 0, Process.SYSTEM_UID, currentUserId);
+                var usingSharedLibraryPair = snapshot.getPackagesUsingSharedLibrary(libraryInfo, 0,
+                        Process.SYSTEM_UID, currentUserId);
+                final List<VersionedPackage> dependents = usingSharedLibraryPair.first;
                 if (dependents == null) {
                     continue;
                 }
@@ -921,42 +924,43 @@
         // duplicates.
         ArrayList<SharedLibraryInfo> usesLibraryInfos = null;
         if (!pkg.getUsesLibraries().isEmpty()) {
-            usesLibraryInfos = collectSharedLibraryInfos(pkg.getUsesLibraries(), null, null,
+            usesLibraryInfos = collectSharedLibraryInfos(pkg.getUsesLibraries(), null, null, null,
                     pkg.getPackageName(), "shared", true, pkg.getTargetSdkVersion(), null,
                     availablePackages, newLibraries);
         }
         if (!pkg.getUsesStaticLibraries().isEmpty()) {
             usesLibraryInfos = collectSharedLibraryInfos(pkg.getUsesStaticLibraries(),
                     pkg.getUsesStaticLibrariesVersions(), pkg.getUsesStaticLibrariesCertDigests(),
-                    pkg.getPackageName(), "static shared", true, pkg.getTargetSdkVersion(),
-                    usesLibraryInfos, availablePackages, newLibraries);
+                    null, pkg.getPackageName(), "static shared", true,
+                    pkg.getTargetSdkVersion(), usesLibraryInfos, availablePackages, newLibraries);
         }
         if (!pkg.getUsesOptionalLibraries().isEmpty()) {
             usesLibraryInfos = collectSharedLibraryInfos(pkg.getUsesOptionalLibraries(), null, null,
-                    pkg.getPackageName(), "shared", false, pkg.getTargetSdkVersion(),
+                    null, pkg.getPackageName(), "shared", false, pkg.getTargetSdkVersion(),
                     usesLibraryInfos, availablePackages, newLibraries);
         }
         if (platformCompat.isChangeEnabledInternal(ENFORCE_NATIVE_SHARED_LIBRARY_DEPENDENCIES,
                 pkg.getPackageName(), pkg.getTargetSdkVersion())) {
             if (!pkg.getUsesNativeLibraries().isEmpty()) {
                 usesLibraryInfos = collectSharedLibraryInfos(pkg.getUsesNativeLibraries(), null,
-                        null, pkg.getPackageName(), "native shared", true,
+                        null, null, pkg.getPackageName(), "native shared", true,
                         pkg.getTargetSdkVersion(), usesLibraryInfos, availablePackages,
                         newLibraries);
             }
             if (!pkg.getUsesOptionalNativeLibraries().isEmpty()) {
                 usesLibraryInfos = collectSharedLibraryInfos(pkg.getUsesOptionalNativeLibraries(),
-                        null, null, pkg.getPackageName(), "native shared", false,
+                        null, null, null, pkg.getPackageName(), "native shared", false,
                         pkg.getTargetSdkVersion(), usesLibraryInfos, availablePackages,
                         newLibraries);
             }
         }
         if (!pkg.getUsesSdkLibraries().isEmpty()) {
             // Allow installation even if sdk-library dependency doesn't exist
-            boolean required = !sdkLibIndependence();
+            boolean required = !Flags.sdkLibIndependence();
             usesLibraryInfos = collectSharedLibraryInfos(pkg.getUsesSdkLibraries(),
                     pkg.getUsesSdkLibrariesVersionsMajor(), pkg.getUsesSdkLibrariesCertDigests(),
-                    pkg.getPackageName(), "sdk", required, pkg.getTargetSdkVersion(),
+                    pkg.getUsesSdkLibrariesOptional(),
+                    pkg.getPackageName(), LIBRARY_TYPE_SDK, required, pkg.getTargetSdkVersion(),
                     usesLibraryInfos, availablePackages, newLibraries);
         }
         return usesLibraryInfos;
@@ -965,6 +969,7 @@
     private ArrayList<SharedLibraryInfo> collectSharedLibraryInfos(
             @NonNull List<String> requestedLibraries,
             @Nullable long[] requiredVersions, @Nullable String[][] requiredCertDigests,
+            @Nullable boolean[] libsOptional,
             @NonNull String packageName, @NonNull String libraryType, boolean required,
             int targetSdk, @Nullable ArrayList<SharedLibraryInfo> outUsedLibraries,
             @NonNull final Map<String, AndroidPackage> availablePackages,
@@ -981,7 +986,10 @@
                         libName, libVersion, mSharedLibraries, newLibraries);
             }
             if (libraryInfo == null) {
-                if (required) {
+                // Only allow app be installed if the app specifies the sdk-library dependency is
+                // optional
+                if (required || (LIBRARY_TYPE_SDK.equals(libraryType) && (libsOptional != null
+                        && !libsOptional[i]))) {
                     throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY,
                             "Package " + packageName + " requires unavailable " + libraryType
                                     + " library " + libName + "; failing!");
diff --git a/services/core/java/com/android/server/pm/SharedUserSetting.java b/services/core/java/com/android/server/pm/SharedUserSetting.java
index dddc6b0..5c0a15a 100644
--- a/services/core/java/com/android/server/pm/SharedUserSetting.java
+++ b/services/core/java/com/android/server/pm/SharedUserSetting.java
@@ -25,14 +25,14 @@
 import android.util.ArraySet;
 import android.util.proto.ProtoOutputStream;
 
+import com.android.internal.pm.pkg.component.ComponentMutateUtils;
 import com.android.internal.pm.pkg.component.ParsedProcess;
+import com.android.internal.pm.pkg.component.ParsedProcessImpl;
 import com.android.internal.util.ArrayUtils;
 import com.android.server.pm.permission.LegacyPermissionState;
 import com.android.server.pm.pkg.AndroidPackage;
 import com.android.server.pm.pkg.PackageStateInternal;
 import com.android.server.pm.pkg.SharedUserApi;
-import com.android.server.pm.pkg.component.ComponentMutateUtils;
-import com.android.server.pm.pkg.component.ParsedProcessImpl;
 import com.android.server.utils.SnapshotCache;
 import com.android.server.utils.Watchable;
 import com.android.server.utils.WatchedArraySet;
diff --git a/services/core/java/com/android/server/pm/StorageEventHelper.java b/services/core/java/com/android/server/pm/StorageEventHelper.java
index 70aa19a..7d87d1b 100644
--- a/services/core/java/com/android/server/pm/StorageEventHelper.java
+++ b/services/core/java/com/android/server/pm/StorageEventHelper.java
@@ -47,11 +47,11 @@
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.pm.pkg.parsing.ParsingPackageUtils;
 import com.android.internal.policy.AttributeCache;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.pm.pkg.AndroidPackage;
 import com.android.server.pm.pkg.PackageStateInternal;
-import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
 
 import java.io.File;
 import java.io.PrintWriter;
@@ -256,13 +256,12 @@
 
                     final AndroidPackage pkg = ps.getPkg();
                     final int deleteFlags = PackageManager.DELETE_KEEP_DATA;
-                    final PackageRemovedInfo outInfo = new PackageRemovedInfo();
 
                     try (PackageFreezer freezer = mPm.freezePackageForDelete(ps.getPackageName(),
                              UserHandle.USER_ALL, deleteFlags,
                             "unloadPrivatePackagesInner", ApplicationExitInfo.REASON_OTHER)) {
                         if (mDeletePackageHelper.deletePackageLIF(ps.getPackageName(), null, false,
-                                userIds, deleteFlags, outInfo, false)) {
+                                userIds, deleteFlags, new PackageRemovedInfo(), false)) {
                             unloaded.add(pkg);
                         } else {
                             Slog.w(TAG, "Failed to unload " + ps.getPath());
diff --git a/services/core/java/com/android/server/pm/SuspendPackageHelper.java b/services/core/java/com/android/server/pm/SuspendPackageHelper.java
index 71f6c0d..c2a960a 100644
--- a/services/core/java/com/android/server/pm/SuspendPackageHelper.java
+++ b/services/core/java/com/android/server/pm/SuspendPackageHelper.java
@@ -33,7 +33,6 @@
 import android.os.Process;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.provider.DeviceConfig;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.IntArray;
@@ -419,11 +418,24 @@
         }
 
         String suspendingPackage = null;
+        String suspendedBySystem = null;
+        String qasPackage = null;
         for (int i = 0; i < userState.getSuspendParams().size(); i++) {
             suspendingPackage = userState.getSuspendParams().keyAt(i);
+            var suspendParams = userState.getSuspendParams().valueAt(i);
             if (PLATFORM_PACKAGE_NAME.equals(suspendingPackage)) {
-                return suspendingPackage;
+                suspendedBySystem = suspendingPackage;
             }
+            if (suspendParams.isQuarantined() && qasPackage == null) {
+                qasPackage = suspendingPackage;
+            }
+        }
+        // Precedence: quarantined, then system, then suspending.
+        if (qasPackage != null) {
+            return qasPackage;
+        }
+        if (suspendedBySystem != null) {
+            return suspendedBySystem;
         }
         return suspendingPackage;
     }
@@ -504,10 +516,6 @@
             final String requiredPermissionControllerPackage =
                     getKnownPackageName(snapshot, KnownPackages.PACKAGE_PERMISSION_CONTROLLER,
                             userId);
-            final AppOpsManager appOpsManager = mInjector.getSystemService(AppOpsManager.class);
-            final boolean isSystemExemptFlagEnabled = DeviceConfig.getBoolean(
-                    DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
-                    SYSTEM_EXEMPT_FROM_SUSPENSION, /* defaultValue= */ true);
             for (int i = 0; i < packageNames.length; i++) {
                 canSuspend[i] = false;
                 final String packageName = packageNames[i];
@@ -581,9 +589,7 @@
                                 + pkg.getStaticSharedLibraryName());
                         continue;
                     }
-                    if (isSystemExemptFlagEnabled && appOpsManager.checkOpNoThrow(
-                            AppOpsManager.OP_SYSTEM_EXEMPT_FROM_SUSPENSION, uid, packageName)
-                            == AppOpsManager.MODE_ALLOWED) {
+                    if (exemptFromSuspensionByAppOp(uid, packageName)) {
                         Slog.w(TAG, "Cannot suspend package \"" + packageName
                                 + "\": has OP_SYSTEM_EXEMPT_FROM_SUSPENSION set");
                         continue;
@@ -601,6 +607,13 @@
         return canSuspend;
     }
 
+    private boolean exemptFromSuspensionByAppOp(int uid, String packageName) {
+        final AppOpsManager appOpsManager = mInjector.getSystemService(AppOpsManager.class);
+        return appOpsManager.checkOpNoThrow(
+                AppOpsManager.OP_SYSTEM_EXEMPT_FROM_SUSPENSION, uid, packageName)
+                        == AppOpsManager.MODE_ALLOWED;
+    }
+
     /**
      * Suspends packages on behalf of an admin.
      *
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index b53a21c..c48eccf 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -532,9 +532,10 @@
             }
             final IntentSender target = intent.getParcelableExtra(Intent.EXTRA_INTENT, android.content.IntentSender.class);
             final int userId = intent.getIntExtra(Intent.EXTRA_USER_ID, UserHandle.USER_NULL);
+            final String callingPackage = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME);
             // Call setQuietModeEnabled on bg thread to avoid ANR
             BackgroundThread.getHandler().post(() ->
-                    setQuietModeEnabled(userId, false, target, /* callingPackage */ null));
+                    setQuietModeEnabled(userId, false, target, callingPackage));
         }
     };
 
@@ -1410,7 +1411,7 @@
                     if (onlyIfCredentialNotRequired) {
                         return false;
                     }
-                    showConfirmCredentialToDisableQuietMode(userId, target);
+                    showConfirmCredentialToDisableQuietMode(userId, target, callingPackage);
                     return false;
                 }
             }
@@ -1434,7 +1435,7 @@
                 if (onlyIfCredentialNotRequired) {
                     return false;
                 }
-                showConfirmCredentialToDisableQuietMode(userId, target);
+                showConfirmCredentialToDisableQuietMode(userId, target, callingPackage);
                 return false;
             }
             setQuietModeEnabled(userId, false /* enableQuietMode */, target, callingPackage);
@@ -1519,7 +1520,7 @@
 
         try {
             if (enableQuietMode) {
-                ActivityManager.getService().stopUser(userId, /* force= */ true, null);
+                stopUserForQuietMode(userId);
                 LocalServices.getService(ActivityManagerInternal.class)
                         .killForegroundAppsForUser(userId);
             } else {
@@ -1547,6 +1548,18 @@
         }
     }
 
+    private void stopUserForQuietMode(int userId) throws RemoteException {
+        if (android.os.Flags.allowPrivateProfile()
+                && android.multiuser.Flags.enableBiometricsToUnlockPrivateSpace()) {
+            // Allow delayed locking since some profile types want to be able to unlock again via
+            // biometrics.
+            ActivityManager.getService()
+                    .stopUserWithDelayedLocking(userId, /* force= */ true, null);
+            return;
+        }
+        ActivityManager.getService().stopUser(userId, /* force= */ true, null);
+    }
+
     private void logQuietModeEnabled(@UserIdInt int userId, boolean enableQuietMode,
             @Nullable String callingPackage) {
         Slogf.i(LOG_TAG,
@@ -1592,7 +1605,7 @@
      * Show confirm credential screen to unlock user in order to turn off quiet mode.
      */
     private void showConfirmCredentialToDisableQuietMode(
-            @UserIdInt int userId, @Nullable IntentSender target) {
+            @UserIdInt int userId, @Nullable IntentSender target, @Nullable String callingPackage) {
         if (android.app.admin.flags.Flags.quietModeCredentialBugFix()) {
             // TODO (b/308121702) It may be brittle to rely on user states to check profile state
             int state;
@@ -1623,6 +1636,7 @@
         }
         callBackIntent.putExtra(Intent.EXTRA_USER_ID, userId);
         callBackIntent.setPackage(mContext.getPackageName());
+        callBackIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, callingPackage);
         callBackIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
         final PendingIntent pendingIntent = PendingIntent.getBroadcast(
                 mContext,
diff --git a/services/core/java/com/android/server/pm/UserTypeFactory.java b/services/core/java/com/android/server/pm/UserTypeFactory.java
index 4ef8cb7..14db70e 100644
--- a/services/core/java/com/android/server/pm/UserTypeFactory.java
+++ b/services/core/java/com/android/server/pm/UserTypeFactory.java
@@ -160,7 +160,9 @@
                                 UserProperties.SHOW_IN_SHARING_SURFACES_WITH_PARENT)
                         .setMediaSharedWithParent(true)
                         .setCredentialShareableWithParent(true)
-                        .setDeleteAppWithParent(true));
+                        .setDeleteAppWithParent(true)
+                        .setCrossProfileContentSharingStrategy(UserProperties
+                                .CROSS_PROFILE_CONTENT_SHARING_DELEGATE_FROM_PARENT));
     }
 
     /**
@@ -304,11 +306,11 @@
                 .setDarkThemeBadgeColors(
                         R.color.white)
                 .setDefaultRestrictions(getDefaultProfileRestrictions())
-                .setDefaultSecureSettings(getDefaultNonManagedProfileSecureSettings())
                 .setDefaultUserProperties(new UserProperties.Builder()
                         .setStartWithParent(true)
                         .setCredentialShareableWithParent(true)
                         .setAuthAlwaysRequiredToDisableQuietMode(true)
+                        .setAllowStoppingUserWithDelayedLocking(true)
                         .setMediaSharedWithParent(false)
                         .setShowInLauncher(UserProperties.SHOW_IN_LAUNCHER_SEPARATE)
                         .setShowInSettings(UserProperties.SHOW_IN_SETTINGS_SEPARATE)
@@ -318,7 +320,9 @@
                                 UserProperties.SHOW_IN_SHARING_SURFACES_SEPARATE)
                         .setCrossProfileIntentFilterAccessControl(
                                 UserProperties.CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_SYSTEM)
-                        .setInheritDevicePolicy(UserProperties.INHERIT_DEVICE_POLICY_FROM_PARENT));
+                        .setInheritDevicePolicy(UserProperties.INHERIT_DEVICE_POLICY_FROM_PARENT)
+                        .setCrossProfileContentSharingStrategy(
+                                UserProperties.CROSS_PROFILE_CONTENT_SHARING_DELEGATE_FROM_PARENT));
     }
 
     /**
diff --git a/services/core/java/com/android/server/pm/parsing/PackageCacher.java b/services/core/java/com/android/server/pm/parsing/PackageCacher.java
index 459e2cf..79c9c8e 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageCacher.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageCacher.java
@@ -28,9 +28,9 @@
 import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.pm.parsing.pkg.PackageImpl;
 import com.android.internal.pm.parsing.pkg.ParsedPackage;
 import com.android.server.pm.ApexManager;
-import com.android.server.pm.parsing.pkg.PackageImpl;
 
 import libcore.io.IoUtils;
 
diff --git a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
index d642018..d0fe964 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
@@ -28,6 +28,7 @@
 import android.content.pm.FallbackCategoryProvider;
 import android.content.pm.FeatureGroupInfo;
 import android.content.pm.FeatureInfo;
+import android.content.pm.Flags;
 import android.content.pm.InstrumentationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageItemInfo;
@@ -52,6 +53,9 @@
 import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.pm.parsing.pkg.AndroidPackageLegacyUtils;
+import com.android.internal.pm.parsing.pkg.PackageImpl;
+import com.android.internal.pm.pkg.component.ComponentParseUtils;
 import com.android.internal.pm.pkg.component.ParsedActivity;
 import com.android.internal.pm.pkg.component.ParsedAttribution;
 import com.android.internal.pm.pkg.component.ParsedComponent;
@@ -63,11 +67,12 @@
 import com.android.internal.pm.pkg.component.ParsedProvider;
 import com.android.internal.pm.pkg.component.ParsedService;
 import com.android.internal.pm.pkg.component.ParsedUsesPermission;
+import com.android.internal.pm.pkg.parsing.ParsingPackageUtils;
+import com.android.internal.pm.pkg.parsing.ParsingUtils;
 import com.android.internal.util.ArrayUtils;
 import com.android.server.SystemConfig;
 import com.android.server.pm.PackageArchiver;
 import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
-import com.android.server.pm.parsing.pkg.PackageImpl;
 import com.android.server.pm.pkg.AndroidPackage;
 import com.android.server.pm.pkg.PackageStateInternal;
 import com.android.server.pm.pkg.PackageStateUnserialized;
@@ -75,9 +80,6 @@
 import com.android.server.pm.pkg.PackageUserStateInternal;
 import com.android.server.pm.pkg.PackageUserStateUtils;
 import com.android.server.pm.pkg.SELinuxUtil;
-import com.android.server.pm.pkg.component.ComponentParseUtils;
-import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
-import com.android.server.pm.pkg.parsing.ParsingUtils;
 
 import java.io.File;
 import java.util.ArrayList;
@@ -266,17 +268,20 @@
         if ((flags & PackageManager.GET_ACTIVITIES) != 0) {
             final int N = pkg.getActivities().size();
             if (N > 0) {
+                // Allow to match activities of quarantined packages.
+                long aflags = flags | PackageManager.MATCH_QUARANTINED_COMPONENTS;
+
                 int num = 0;
                 final ActivityInfo[] res = new ActivityInfo[N];
                 for (int i = 0; i < N; i++) {
                     final ParsedActivity a = pkg.getActivities().get(i);
-                    if (ComponentParseUtils.isMatch(state, pkgSetting.isSystem(), pkg.isEnabled(), a,
-                            flags)) {
+                    if (PackageUserStateUtils.isMatch(state, pkgSetting.isSystem(), pkg.isEnabled(),
+                            a.isEnabled(), a.isDirectBootAware(), a.getName(), aflags)) {
                         if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(
                                 a.getName())) {
                             continue;
                         }
-                        res[num++] = generateActivityInfo(pkg, a, flags, state,
+                        res[num++] = generateActivityInfo(pkg, a, aflags, state,
                                 applicationInfo, userId, pkgSetting);
                     }
                 }
@@ -290,8 +295,8 @@
                 final ActivityInfo[] res = new ActivityInfo[size];
                 for (int i = 0; i < size; i++) {
                     final ParsedActivity a = pkg.getReceivers().get(i);
-                    if (ComponentParseUtils.isMatch(state, pkgSetting.isSystem(), pkg.isEnabled(), a,
-                            flags)) {
+                    if (PackageUserStateUtils.isMatch(state, pkgSetting.isSystem(), pkg.isEnabled(),
+                            a.isEnabled(), a.isDirectBootAware(), a.getName(), flags)) {
                         res[num++] = generateActivityInfo(pkg, a, flags, state, applicationInfo,
                                 userId, pkgSetting);
                     }
@@ -306,8 +311,8 @@
                 final ServiceInfo[] res = new ServiceInfo[size];
                 for (int i = 0; i < size; i++) {
                     final ParsedService s = pkg.getServices().get(i);
-                    if (ComponentParseUtils.isMatch(state, pkgSetting.isSystem(), pkg.isEnabled(), s,
-                            flags)) {
+                    if (PackageUserStateUtils.isMatch(state, pkgSetting.isSystem(), pkg.isEnabled(),
+                            s.isEnabled(), s.isDirectBootAware(), s.getName(), flags)) {
                         res[num++] = generateServiceInfo(pkg, s, flags, state, applicationInfo,
                                 userId, pkgSetting);
                     }
@@ -323,8 +328,8 @@
                 for (int i = 0; i < size; i++) {
                     final ParsedProvider pr = pkg.getProviders()
                             .get(i);
-                    if (ComponentParseUtils.isMatch(state, pkgSetting.isSystem(), pkg.isEnabled(), pr,
-                            flags)) {
+                    if (PackageUserStateUtils.isMatch(state, pkgSetting.isSystem(), pkg.isEnabled(),
+                            pr.isEnabled(), pr.isDirectBootAware(), pr.getName(), flags)) {
                         res[num++] = generateProviderInfo(pkg, pr, flags, state, applicationInfo,
                                 userId, pkgSetting);
                     }
@@ -470,7 +475,34 @@
         }
         info.sharedLibraryFiles = usesLibraryFiles.isEmpty()
                 ? null : usesLibraryFiles.toArray(new String[0]);
-        info.sharedLibraryInfos = usesLibraryInfos.isEmpty() ? null : usesLibraryInfos;
+
+
+        if (!Flags.sdkLibIndependence()) {
+            info.sharedLibraryInfos = usesLibraryInfos.isEmpty() ? null : usesLibraryInfos;
+            info.optionalSharedLibraryInfos = null;
+        } else {
+            // sharedLibraryInfos contains all shared libraries that the app depends on (including
+            // the optional sdk libraries)
+            info.sharedLibraryInfos = usesLibraryInfos.isEmpty() ? null : usesLibraryInfos;
+            String[] libsNames = pkgSetting.getUsesSdkLibraries();
+            boolean[] libsOptional = pkgSetting.getUsesSdkLibrariesOptional();
+            List<SharedLibraryInfo> optionalSdkLibraries = null;
+            if (!ArrayUtils.isEmpty(libsOptional) && !ArrayUtils.isEmpty(libsNames)
+                    && libsNames.length == libsOptional.length) {
+                for (SharedLibraryInfo info1 : usesLibraryInfos) {
+                    if (info1.getType() == SharedLibraryInfo.TYPE_SDK_PACKAGE) {
+                        int index = ArrayUtils.indexOf(libsNames, info1.getName());
+                        if (index >= 0 && libsOptional[index]) {
+                            if (optionalSdkLibraries == null) {
+                                optionalSdkLibraries = new ArrayList<>();
+                            }
+                            optionalSdkLibraries.add(info1);
+                        }
+                    }
+                }
+            }
+            info.optionalSharedLibraryInfos = optionalSdkLibraries;
+        }
         if (info.category == ApplicationInfo.CATEGORY_UNDEFINED) {
             info.category = pkgSetting.getCategoryOverride();
         }
@@ -920,7 +952,7 @@
                 | flag(pkg.isExtraLargeScreensSupported(), ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS)
                 | flag(pkg.isResizeable(), ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS)
                 | flag(pkg.isAnyDensity(), ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
-                | flag(AndroidPackageUtils.isSystem(pkg), ApplicationInfo.FLAG_SYSTEM)
+                | flag(AndroidPackageLegacyUtils.isSystem(pkg), ApplicationInfo.FLAG_SYSTEM)
                 | flag(pkg.isFactoryTest(), ApplicationInfo.FLAG_FACTORY_TEST);
 
         return appInfoFlags(pkgWithoutStateFlags, pkgSetting);
@@ -961,12 +993,12 @@
                 | flag(pkg.isSaveStateDisallowed(), ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
                 | flag(pkg.isResizeableActivityViaSdkVersion(), ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION)
                 | flag(pkg.isAllowNativeHeapPointerTagging(), ApplicationInfo.PRIVATE_FLAG_ALLOW_NATIVE_HEAP_POINTER_TAGGING)
-                | flag(AndroidPackageUtils.isSystemExt(pkg), ApplicationInfo.PRIVATE_FLAG_SYSTEM_EXT)
-                | flag(AndroidPackageUtils.isPrivileged(pkg), ApplicationInfo.PRIVATE_FLAG_PRIVILEGED)
-                | flag(AndroidPackageUtils.isOem(pkg), ApplicationInfo.PRIVATE_FLAG_OEM)
-                | flag(AndroidPackageUtils.isVendor(pkg), ApplicationInfo.PRIVATE_FLAG_VENDOR)
-                | flag(AndroidPackageUtils.isProduct(pkg), ApplicationInfo.PRIVATE_FLAG_PRODUCT)
-                | flag(AndroidPackageUtils.isOdm(pkg), ApplicationInfo.PRIVATE_FLAG_ODM)
+                | flag(AndroidPackageLegacyUtils.isSystemExt(pkg), ApplicationInfo.PRIVATE_FLAG_SYSTEM_EXT)
+                | flag(AndroidPackageLegacyUtils.isPrivileged(pkg), ApplicationInfo.PRIVATE_FLAG_PRIVILEGED)
+                | flag(AndroidPackageLegacyUtils.isOem(pkg), ApplicationInfo.PRIVATE_FLAG_OEM)
+                | flag(AndroidPackageLegacyUtils.isVendor(pkg), ApplicationInfo.PRIVATE_FLAG_VENDOR)
+                | flag(AndroidPackageLegacyUtils.isProduct(pkg), ApplicationInfo.PRIVATE_FLAG_PRODUCT)
+                | flag(AndroidPackageLegacyUtils.isOdm(pkg), ApplicationInfo.PRIVATE_FLAG_ODM)
                 | flag(pkg.isSignedWithPlatformKey(), ApplicationInfo.PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY);
 
         Boolean resizeableActivity = pkg.getResizeableActivity();
diff --git a/services/core/java/com/android/server/pm/parsing/PackageParser2.java b/services/core/java/com/android/server/pm/parsing/PackageParser2.java
index 1c751e0..b6a08a5 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageParser2.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageParser2.java
@@ -35,17 +35,19 @@
 import android.util.Slog;
 
 import com.android.internal.compat.IPlatformCompat;
+import com.android.internal.pm.parsing.pkg.PackageImpl;
 import com.android.internal.pm.parsing.pkg.ParsedPackage;
 import com.android.internal.pm.pkg.parsing.ParsingPackage;
+import com.android.internal.pm.pkg.parsing.ParsingPackageUtils;
+import com.android.internal.pm.pkg.parsing.ParsingUtils;
 import com.android.internal.util.ArrayUtils;
+import com.android.server.SystemConfig;
 import com.android.server.pm.PackageManagerException;
 import com.android.server.pm.PackageManagerService;
-import com.android.server.pm.parsing.pkg.PackageImpl;
-import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
-import com.android.server.pm.pkg.parsing.ParsingUtils;
 
 import java.io.File;
 import java.util.List;
+import java.util.Set;
 
 /**
  * The v2 of package parsing for use when parsing is initiated in the server and must
@@ -88,6 +90,16 @@
                 // behavior.
                 return false;
             }
+
+            @Override
+            public Set<String> getHiddenApiWhitelistedApps() {
+                return SystemConfig.getInstance().getHiddenApiWhitelistedApps();
+            }
+
+            @Override
+            public Set<String> getInstallConstraintsAllowlist() {
+                return SystemConfig.getInstance().getInstallConstraintsAllowlist();
+            }
         });
     }
 
@@ -221,7 +233,7 @@
                 @NonNull String baseCodePath, @NonNull String codePath,
                 @NonNull TypedArray manifestArray, boolean isCoreApp) {
             return PackageImpl.forParsing(packageName, baseCodePath, codePath, manifestArray,
-                    isCoreApp);
+                    isCoreApp, Callback.this);
         }
 
         /**
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java
index 61be6e1..1b7c7ad 100644
--- a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java
+++ b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java
@@ -29,7 +29,9 @@
 import android.os.incremental.IncrementalManager;
 
 import com.android.internal.content.NativeLibraryHelper;
+import com.android.internal.pm.parsing.PackageParserException;
 import com.android.internal.pm.parsing.pkg.AndroidPackageHidden;
+import com.android.internal.pm.parsing.pkg.PackageImpl;
 import com.android.internal.pm.pkg.component.ParsedActivity;
 import com.android.internal.pm.pkg.component.ParsedInstrumentation;
 import com.android.internal.pm.pkg.component.ParsedProvider;
@@ -37,7 +39,6 @@
 import com.android.internal.pm.pkg.parsing.ParsingPackageHidden;
 import com.android.internal.util.ArrayUtils;
 import com.android.server.SystemConfig;
-import com.android.server.pm.PackageManagerException;
 import com.android.server.pm.pkg.AndroidPackage;
 import com.android.server.pm.pkg.PackageState;
 import com.android.server.pm.pkg.PackageStateInternal;
@@ -134,10 +135,10 @@
     /**
      * Validate the dex metadata files installed for the given package.
      *
-     * @throws PackageManagerException in case of errors.
+     * @throws PackageParserException in case of errors.
      */
     public static void validatePackageDexMetadata(AndroidPackage pkg)
-            throws PackageManagerException {
+            throws PackageParserException {
         Collection<String> apkToDexMetadataList = getPackageDexMetadata(pkg).values();
         String packageName = pkg.getPackageName();
         long versionCode = pkg.getLongVersionCode();
@@ -146,7 +147,7 @@
             final ParseResult result = DexMetadataHelper.validateDexMetadataFile(
                     input.reset(), dexMetadata, packageName, versionCode);
             if (result.isError()) {
-                throw new PackageManagerException(
+                throw new PackageParserException(
                         result.getErrorCode(), result.getErrorMessage(), result.getException());
             }
         }
@@ -314,60 +315,4 @@
         info.versionCode = ((ParsingPackageHidden) pkg).getVersionCode();
         info.versionCodeMajor = ((ParsingPackageHidden) pkg).getVersionCodeMajor();
     }
-
-    /**
-     * @deprecated Use {@link PackageState#isSystem}
-     */
-    @Deprecated
-    public static boolean isSystem(@NonNull AndroidPackage pkg) {
-        return ((AndroidPackageHidden) pkg).isSystem();
-    }
-
-    /**
-     * @deprecated Use {@link PackageState#isSystemExt}
-     */
-    @Deprecated
-    public static boolean isSystemExt(@NonNull AndroidPackage pkg) {
-        return ((AndroidPackageHidden) pkg).isSystemExt();
-    }
-
-    /**
-     * @deprecated Use {@link PackageState#isPrivileged}
-     */
-    @Deprecated
-    public static boolean isPrivileged(@NonNull AndroidPackage pkg) {
-        return ((AndroidPackageHidden) pkg).isPrivileged();
-    }
-
-    /**
-     * @deprecated Use {@link PackageState#isOem}
-     */
-    @Deprecated
-    public static boolean isOem(@NonNull AndroidPackage pkg) {
-        return ((AndroidPackageHidden) pkg).isOem();
-    }
-
-    /**
-     * @deprecated Use {@link PackageState#isVendor}
-     */
-    @Deprecated
-    public static boolean isVendor(@NonNull AndroidPackage pkg) {
-        return ((AndroidPackageHidden) pkg).isVendor();
-    }
-
-    /**
-     * @deprecated Use {@link PackageState#isProduct}
-     */
-    @Deprecated
-    public static boolean isProduct(@NonNull AndroidPackage pkg) {
-        return ((AndroidPackageHidden) pkg).isProduct();
-    }
-
-    /**
-     * @deprecated Use {@link PackageState#isOdm}
-     */
-    @Deprecated
-    public static boolean isOdm(@NonNull AndroidPackage pkg) {
-        return ((AndroidPackageHidden) pkg).isOdm();
-    }
 }
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
index 8bd2d94..671e031 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
@@ -120,8 +120,11 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.internal.os.RoSystemProperties;
+import com.android.internal.pm.permission.CompatibilityPermissionInfo;
+import com.android.internal.pm.pkg.component.ComponentMutateUtils;
 import com.android.internal.pm.pkg.component.ParsedPermission;
 import com.android.internal.pm.pkg.component.ParsedPermissionGroup;
+import com.android.internal.pm.pkg.component.ParsedPermissionUtils;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.CollectionUtils;
 import com.android.internal.util.IntPair;
@@ -144,8 +147,6 @@
 import com.android.server.pm.pkg.PackageState;
 import com.android.server.pm.pkg.PackageStateInternal;
 import com.android.server.pm.pkg.SharedUserApi;
-import com.android.server.pm.pkg.component.ComponentMutateUtils;
-import com.android.server.pm.pkg.component.ParsedPermissionUtils;
 import com.android.server.policy.PermissionPolicyInternal;
 import com.android.server.policy.SoftRestrictedPermissionPolicy;
 
diff --git a/services/core/java/com/android/server/pm/pkg/PackageState.java b/services/core/java/com/android/server/pm/pkg/PackageState.java
index 10b59c7..a7ae4eb 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageState.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageState.java
@@ -322,6 +322,14 @@
     long[] getUsesSdkLibrariesVersionsMajor();
 
     /**
+     * @see R.styleable#AndroidManifestUsesSdkLibrary_optional
+     * @hide
+     */
+    @Immutable.Ignore
+    @NonNull
+    boolean[] getUsesSdkLibrariesOptional();
+
+    /**
      * @see R.styleable#AndroidManifestUsesStaticLibrary
      * @hide
      */
diff --git a/services/core/java/com/android/server/pm/pkg/PackageUserStateUtils.java b/services/core/java/com/android/server/pm/pkg/PackageUserStateUtils.java
index 4b3992e..fe80f74 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageUserStateUtils.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageUserStateUtils.java
@@ -93,8 +93,8 @@
      * this object exists means that the package must be installed or has data on at least one user;
      * <li> If it is not installed but still has data (i.e., it was previously uninstalled with
      * {@link PackageManager#DELETE_KEEP_DATA}), return true if the caller requested
-     * {@link PackageManager#MATCH_UNINSTALLED_PACKAGES}.
-     * Always available for {@link PackageManager#MATCH_ARCHIVED_PACKAGES}.
+     * {@link PackageManager#MATCH_UNINSTALLED_PACKAGES} or
+     * {@link PackageManager#MATCH_ARCHIVED_PACKAGES};
      * </ul><p>
      */
     public static boolean isAvailable(@NonNull PackageUserState state, long flags) {
@@ -109,19 +109,11 @@
         if (state.isInstalled()) {
             if (!state.isHidden()) {
                 return true;
-            } else {
-                return matchDataExists;
-            }
+            } else return matchDataExists;
+        } else {
+            // not installed
+            return matchDataExists && state.dataExists();
         }
-
-        // not installed
-        if (matchUninstalled) {
-            return state.dataExists();
-        }
-
-        // archived or installed as archived
-        // TODO(b/314808978): Create data folders during install-archived.
-        return matchArchived;
     }
 
     public static boolean reportIfDebug(boolean result, long flags) {
diff --git a/services/core/java/com/android/server/pm/pkg/SELinuxUtil.java b/services/core/java/com/android/server/pm/pkg/SELinuxUtil.java
index 6cbc1de..6a15641 100644
--- a/services/core/java/com/android/server/pm/pkg/SELinuxUtil.java
+++ b/services/core/java/com/android/server/pm/pkg/SELinuxUtil.java
@@ -16,6 +16,8 @@
 
 package com.android.server.pm.pkg;
 
+import com.android.internal.pm.pkg.SEInfoUtil;
+
 /**
  * Utility methods that need to be used in application space.
  * @hide
@@ -23,10 +25,10 @@
 public final class SELinuxUtil {
 
     /** Append to existing seinfo label for instant apps @hide */
-    private static final String INSTANT_APP_STR = ":ephemeralapp";
+    private static final String INSTANT_APP_STR = SEInfoUtil.INSTANT_APP_STR;
 
     /** Append to existing seinfo when modifications are complete @hide */
-    public static final String COMPLETE_STR = ":complete";
+    public static final String COMPLETE_STR = SEInfoUtil.COMPLETE_STR;
 
     /** @hide */
     public static String getSeinfoUser(PackageUserState userState) {
diff --git a/services/core/java/com/android/server/pm/resolution/ComponentResolver.java b/services/core/java/com/android/server/pm/resolution/ComponentResolver.java
index 532a7f8..c9da99d 100644
--- a/services/core/java/com/android/server/pm/resolution/ComponentResolver.java
+++ b/services/core/java/com/android/server/pm/resolution/ComponentResolver.java
@@ -45,11 +45,13 @@
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.pm.pkg.component.ComponentMutateUtils;
 import com.android.internal.pm.pkg.component.ParsedActivity;
 import com.android.internal.pm.pkg.component.ParsedComponent;
 import com.android.internal.pm.pkg.component.ParsedIntentInfo;
 import com.android.internal.pm.pkg.component.ParsedMainComponent;
 import com.android.internal.pm.pkg.component.ParsedProvider;
+import com.android.internal.pm.pkg.component.ParsedProviderImpl;
 import com.android.internal.pm.pkg.component.ParsedService;
 import com.android.internal.util.ArrayUtils;
 import com.android.server.IntentResolver;
@@ -62,8 +64,6 @@
 import com.android.server.pm.pkg.PackageStateInternal;
 import com.android.server.pm.pkg.PackageStateUtils;
 import com.android.server.pm.pkg.PackageUserStateInternal;
-import com.android.server.pm.pkg.component.ComponentMutateUtils;
-import com.android.server.pm.pkg.component.ParsedProviderImpl;
 import com.android.server.pm.snapshot.PackageDataSnapshot;
 import com.android.server.utils.Snappable;
 import com.android.server.utils.SnapshotCache;
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 30bce2f4..938ed23 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -17,11 +17,13 @@
 package com.android.server.policy;
 
 import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
+import static android.Manifest.permission.OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW;
 import static android.Manifest.permission.SYSTEM_ALERT_WINDOW;
 import static android.Manifest.permission.SYSTEM_APPLICATION_OVERLAY;
 import static android.app.AppOpsManager.OP_CREATE_ACCESSIBILITY_OVERLAY;
 import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
 import static android.app.AppOpsManager.OP_TOAST_WINDOW;
+import static android.content.PermissionChecker.PID_UNKNOWN;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE;
@@ -74,7 +76,6 @@
 import static android.view.contentprotection.flags.Flags.createAccessibilityOverlayAppOpEnabled;
 
 import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.SCREENSHOT_KEYCHORD_DELAY;
-import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_WEAR_TRIPLE_PRESS_GESTURE;
 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED;
 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT;
 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_UNCOVERED;
@@ -95,7 +96,6 @@
 import static com.android.server.wm.WindowManagerPolicyProto.WINDOW_MANAGER_DRAW_COMPLETE;
 
 import android.accessibilityservice.AccessibilityService;
-import android.accessibilityservice.AccessibilityServiceInfo;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SuppressLint;
@@ -117,11 +117,11 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.PermissionChecker;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
-import android.content.pm.ServiceInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.database.ContentObserver;
@@ -201,8 +201,6 @@
 
 import com.android.internal.R;
 import com.android.internal.accessibility.AccessibilityShortcutController;
-import com.android.internal.accessibility.util.AccessibilityStatsLogUtils;
-import com.android.internal.accessibility.util.AccessibilityUtils;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.AssistUtils;
 import com.android.internal.display.BrightnessUtils;
@@ -382,8 +380,6 @@
 
     public static final String TRACE_WAIT_FOR_ALL_WINDOWS_DRAWN_METHOD = "waitForAllWindowsDrawn";
 
-    private static final String TALKBACK_LABEL = "TalkBack";
-
     private static final int POWER_BUTTON_SUPPRESSION_DELAY_DEFAULT_MILLIS = 800;
 
     /**
@@ -474,6 +470,8 @@
     /** Controller that supports enabling an AccessibilityService by holding down the volume keys */
     private AccessibilityShortcutController mAccessibilityShortcutController;
 
+    private TalkbackShortcutController mTalkbackShortcutController;
+
     boolean mSafeMode;
 
     // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
@@ -690,6 +688,8 @@
 
     private final com.android.internal.policy.LogDecelerateInterpolator mLogDecelerateInterpolator
             = new LogDecelerateInterpolator(100, 0);
+    private final DeferredKeyActionExecutor mDeferredKeyActionExecutor =
+            new DeferredKeyActionExecutor();
 
     private volatile int mTopFocusedDisplayId = INVALID_DISPLAY;
 
@@ -698,6 +698,7 @@
     private KeyCombinationManager mKeyCombinationManager;
     private SingleKeyGestureDetector mSingleKeyGestureDetector;
     private GestureLauncherService mGestureLauncherService;
+    private ButtonOverridePermissionChecker mButtonOverridePermissionChecker;
 
     private boolean mLockNowPending = false;
 
@@ -725,6 +726,7 @@
     private static final int MSG_RINGER_TOGGLE_CHORD = 24;
     private static final int MSG_SWITCH_KEYBOARD_LAYOUT = 25;
     private static final int MSG_LOG_KEYBOARD_SYSTEM_EVENT = 26;
+    private static final int MSG_SET_DEFERRED_KEY_ACTIONS_EXECUTABLE = 27;
 
     private class PolicyHandler extends Handler {
 
@@ -792,7 +794,9 @@
                     mAutofillManagerInternal.onBackKeyPressed();
                     break;
                 case MSG_SYSTEM_KEY_PRESS:
-                    sendSystemKeyToStatusBar((KeyEvent) msg.obj);
+                    KeyEvent event = (KeyEvent) msg.obj;
+                    sendSystemKeyToStatusBar(event);
+                    event.recycle();
                     break;
                 case MSG_HANDLE_ALL_APPS:
                     launchAllAppsAction();
@@ -804,11 +808,19 @@
                     handleScreenShot(msg.arg1);
                     break;
                 case MSG_SWITCH_KEYBOARD_LAYOUT:
-                    handleSwitchKeyboardLayout(msg.arg1, msg.arg2);
+                    SwitchKeyboardLayoutMessageObject object =
+                            (SwitchKeyboardLayoutMessageObject) msg.obj;
+                    handleSwitchKeyboardLayout(object.keyEvent, object.direction,
+                            object.focusedToken);
                     break;
                 case MSG_LOG_KEYBOARD_SYSTEM_EVENT:
                     handleKeyboardSystemEvent(KeyboardLogEvent.from(msg.arg1), (KeyEvent) msg.obj);
                     break;
+                case MSG_SET_DEFERRED_KEY_ACTIONS_EXECUTABLE:
+                    final int keyCode = msg.arg1;
+                    final long downTime = (Long) msg.obj;
+                    mDeferredKeyActionExecutor.setActionsExecutable(keyCode, downTime);
+                    break;
             }
         }
     }
@@ -920,6 +932,10 @@
         }
     }
 
+    private record SwitchKeyboardLayoutMessageObject(KeyEvent keyEvent, IBinder focusedToken,
+                                                     int direction) {
+    }
+
     final IPersistentVrStateCallbacks mPersistentVrModeListener =
             new IPersistentVrStateCallbacks.Stub() {
         @Override
@@ -1588,19 +1604,11 @@
                 if (DEBUG_INPUT) {
                     Slog.d(TAG, "Executing stem primary triple press action behavior.");
                 }
-
-                if (Settings.System.getIntForUser(mContext.getContentResolver(),
-                        Settings.System.WEAR_ACCESSIBILITY_GESTURE_ENABLED,
-                        /* def= */ 0, UserHandle.USER_CURRENT) == 1) {
-                    /** Toggle talkback begin */
-                    ComponentName componentName = getTalkbackComponent();
-                    if (componentName != null && toggleTalkBack(componentName)) {
-                        /** log stem triple press telemetry if it's a talkback enabled event */
-                        logStemTriplePressAccessibilityTelemetry(componentName);
-                    }
-                    performHapticFeedback(HapticFeedbackConstants.CONFIRM, /* always = */ false,
-                        /* reason = */ "Stem primary - Triple Press - Toggle Accessibility");
-                    /** Toggle talkback end */
+                mTalkbackShortcutController.toggleTalkback(mCurrentUserId);
+                if (mTalkbackShortcutController.isTalkBackShortcutGestureEnabled()) {
+                    performHapticFeedback(HapticFeedbackConstants.CONFIRM, /* always = */
+                            false, /* reason = */
+                            "Stem primary - Triple Press - Toggle Accessibility");
                 }
                 break;
         }
@@ -1626,61 +1634,6 @@
     }
 
     /**
-     * A function that toggles talkback service
-     *
-     * @return {@code true} if talkback is enabled, {@code false} if talkback is disabled
-     */
-    private boolean toggleTalkBack(ComponentName componentName) {
-        final Set<ComponentName> enabledServices =
-                AccessibilityUtils.getEnabledServicesFromSettings(mContext, mCurrentUserId);
-
-        boolean isTalkbackAlreadyEnabled = enabledServices.contains(componentName);
-        AccessibilityUtils.setAccessibilityServiceState(mContext, componentName,
-                !isTalkbackAlreadyEnabled);
-        /** if isTalkbackAlreadyEnabled is true, then it's a disabled event so return false
-         * and if isTalkbackAlreadyEnabled is false, return true as it's an enabled event */
-        return !isTalkbackAlreadyEnabled;
-    }
-
-    /**
-     * A function that logs stem triple press accessibility telemetry
-     * If the user setup (Oobe) is not completed, set the
-     * WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE
-     * setting which will be later logged via Settings Snapshot
-     * else, log ACCESSIBILITY_SHORTCUT_REPORTED atom
-     */
-    private void logStemTriplePressAccessibilityTelemetry(ComponentName componentName) {
-        if (!AccessibilityUtils.isUserSetupCompleted(mContext)) {
-            Settings.Secure.putInt(mContext.getContentResolver(),
-                    Settings.System.WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE, 1);
-        } else {
-            AccessibilityStatsLogUtils.logAccessibilityShortcutActivated(mContext, componentName,
-                    ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_WEAR_TRIPLE_PRESS_GESTURE,
-                    /* serviceEnabled= */ true);
-        }
-    }
-
-    private ComponentName getTalkbackComponent() {
-        AccessibilityManager accessibilityManager = mContext.getSystemService(
-                AccessibilityManager.class);
-        List<AccessibilityServiceInfo> serviceInfos =
-                accessibilityManager.getInstalledAccessibilityServiceList();
-
-        for (AccessibilityServiceInfo service : serviceInfos) {
-            final ServiceInfo serviceInfo = service.getResolveInfo().serviceInfo;
-            if (isTalkback(serviceInfo)) {
-                return new ComponentName(serviceInfo.packageName, serviceInfo.name);
-            }
-        }
-        return null;
-    }
-
-    private boolean isTalkback(ServiceInfo info) {
-        String label = info.loadLabel(mPackageManager).toString();
-        return label.equals(TALKBACK_LABEL);
-    }
-
-    /**
      * Load most recent task (expect current task) and bring it to the front.
      */
     void performStemPrimaryDoublePressSwitchToRecentTask() {
@@ -1717,12 +1670,7 @@
             case TRIPLE_PRESS_PRIMARY_NOTHING:
                 break;
             case TRIPLE_PRESS_PRIMARY_TOGGLE_ACCESSIBILITY:
-                if (Settings.System.getIntForUser(
-                                mContext.getContentResolver(),
-                                Settings.System.WEAR_ACCESSIBILITY_GESTURE_ENABLED,
-                                /* def= */ 0,
-                                UserHandle.USER_CURRENT)
-                        == 1) {
+                if (mTalkbackShortcutController.isTalkBackShortcutGestureEnabled()) {
                     return 3;
                 }
                 break;
@@ -2234,6 +2182,14 @@
         IActivityManager getActivityManagerService() {
             return ActivityManager.getService();
         }
+
+        ButtonOverridePermissionChecker getButtonOverridePermissionChecker() {
+            return new ButtonOverridePermissionChecker();
+        }
+
+        TalkbackShortcutController getTalkbackShortcutController() {
+            return new TalkbackShortcutController(mContext);
+        }
     }
 
     /** {@inheritDoc} */
@@ -2497,8 +2453,10 @@
         mKeyguardDrawnTimeout = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_keyguardDrawnTimeout);
         mKeyguardDelegate = injector.getKeyguardServiceDelegate();
+        mTalkbackShortcutController = injector.getTalkbackShortcutController();
         initKeyCombinationRules();
         initSingleKeyGestureRules(injector.getLooper());
+        mButtonOverridePermissionChecker = injector.getButtonOverridePermissionChecker();
         mSideFpsEventHandler = new SideFpsEventHandler(mContext, mHandler, mPowerManager);
     }
 
@@ -2768,17 +2726,33 @@
             if (mShouldEarlyShortPressOnStemPrimary) {
                 return;
             }
-            stemPrimaryPress(1 /*count*/);
+            // Short-press should be triggered only if app doesn't handle it.
+            mDeferredKeyActionExecutor.queueKeyAction(
+                    KeyEvent.KEYCODE_STEM_PRIMARY, downTime, () -> stemPrimaryPress(1 /*count*/));
         }
 
         @Override
         void onLongPress(long eventTime) {
-            stemPrimaryLongPress(eventTime);
+            // Long-press should be triggered only if app doesn't handle it.
+            mDeferredKeyActionExecutor.queueKeyAction(
+                    KeyEvent.KEYCODE_STEM_PRIMARY,
+                    eventTime,
+                    () -> stemPrimaryLongPress(eventTime));
         }
 
         @Override
         void onMultiPress(long downTime, int count, int unusedDisplayId) {
-            stemPrimaryPress(count);
+            // Triple-press stem to toggle accessibility gesture should always be triggered
+            // regardless of if app handles it.
+            if (count == 3
+                    && mTriplePressOnStemPrimaryBehavior
+                    == TRIPLE_PRESS_PRIMARY_TOGGLE_ACCESSIBILITY) {
+                stemPrimaryPress(count);
+            } else {
+                // Other multi-press gestures should be triggered only if app doesn't handle it.
+                mDeferredKeyActionExecutor.queueKeyAction(
+                        KeyEvent.KEYCODE_STEM_PRIMARY, downTime, () -> stemPrimaryPress(count));
+            }
         }
 
         @Override
@@ -2792,7 +2766,9 @@
                 mBackgroundRecentTaskInfoOnStemPrimarySingleKeyUp =
                         mActivityTaskManagerInternal.getMostRecentTaskFromBackground();
                 if (mShouldEarlyShortPressOnStemPrimary) {
-                    stemPrimaryPress(1 /*pressCount*/);
+                    // Key-up gesture should be triggered only if app doesn't handle it.
+                    mDeferredKeyActionExecutor.queueKeyAction(
+                            KeyEvent.KEYCODE_STEM_PRIMARY, eventTime, () -> stemPrimaryPress(1));
                 }
             }
         }
@@ -3672,7 +3648,7 @@
             case KeyEvent.KEYCODE_LANGUAGE_SWITCH:
                 if (firstDown) {
                     int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1;
-                    sendSwitchKeyboardLayout(event, direction);
+                    sendSwitchKeyboardLayout(event, focusedToken, direction);
                     logKeyboardSystemsEvent(event, KeyboardLogEvent.LANGUAGE_SWITCH);
                     return true;
                 }
@@ -3750,6 +3726,15 @@
                     return true;
                 }
                 break;
+            case KeyEvent.KEYCODE_STEM_PRIMARY:
+                if (prepareToSendSystemKeyToApplication(focusedToken, event)) {
+                    // Send to app.
+                    return false;
+                } else {
+                    // Intercepted.
+                    sendSystemKeyToStatusBarAsync(event);
+                    return true;
+                }
         }
         if (isValidGlobalKey(keyCode)
                 && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {
@@ -3760,6 +3745,60 @@
         return (metaState & KeyEvent.META_META_ON) != 0;
     }
 
+    /**
+     * In this function, we check whether a system key should be sent to the application. We also
+     * detect the key gesture on this key, even if the key will be sent to the app. The gesture
+     * action, if any, will not be executed immediately. It will be queued and execute only after
+     * the application tells us that it didn't handle this key.
+     *
+     * @return true if this key should be sent to the application. This also means that the target
+     *     application has the necessary permissions to receive this key. Return false otherwise.
+     */
+    private boolean prepareToSendSystemKeyToApplication(IBinder focusedToken, KeyEvent event) {
+        final int keyCode = event.getKeyCode();
+        if (!event.isSystem()) {
+            Log.wtf(
+                    TAG,
+                    "Illegal keycode provided to prepareToSendSystemKeyToApplication: "
+                            + KeyEvent.keyCodeToString(keyCode));
+            return false;
+        }
+        final boolean isDown = event.getAction() == KeyEvent.ACTION_DOWN;
+        if (isDown && event.getRepeatCount() == 0) {
+            // This happens at the initial DOWN event. Check focused window permission now.
+            final KeyInterceptionInfo info =
+                    mWindowManagerInternal.getKeyInterceptionInfoFromToken(focusedToken);
+            if (info != null
+                    && mButtonOverridePermissionChecker.canAppOverrideSystemKey(
+                            mContext, info.windowOwnerUid)) {
+                // Focused window has the permission. Pass the event to it.
+                return true;
+            } else {
+                // Focused window doesn't have the permission. Intercept the event.
+                // If the initial DOWN event is intercepted, follow-up events will be intercepted
+                // too. So we know the gesture won't be handled by app, and can handle the gesture
+                // in system.
+                setDeferredKeyActionsExecutableAsync(keyCode, event.getDownTime());
+                return false;
+            }
+        } else {
+            // This happens after the initial DOWN event. We will just reuse the initial decision.
+            // I.e., if the initial DOWN event was dispatched, follow-up events should be
+            // dispatched. Otherwise, follow-up events should be consumed.
+            final Set<Integer> consumedKeys = mConsumedKeysForDevice.get(event.getDeviceId());
+            final boolean wasConsumed = consumedKeys != null && consumedKeys.contains(keyCode);
+            return !wasConsumed;
+        }
+    }
+
+    private void setDeferredKeyActionsExecutableAsync(int keyCode, long downTime) {
+        Message msg = Message.obtain(mHandler, MSG_SET_DEFERRED_KEY_ACTIONS_EXECUTABLE);
+        msg.arg1 = keyCode;
+        msg.obj = downTime;
+        msg.setAsynchronous(true);
+        msg.sendToTarget();
+    }
+
     @SuppressLint("MissingPermission")
     private void injectBackGesture(long downtime) {
         // Create and inject down event
@@ -3878,7 +3917,7 @@
                     + ", policyFlags=" + policyFlags);
         }
 
-        if (interceptUnhandledKey(event)) {
+        if (interceptUnhandledKey(event, focusedToken)) {
             return null;
         }
 
@@ -3936,7 +3975,7 @@
         return fallbackEvent;
     }
 
-    private boolean interceptUnhandledKey(KeyEvent event) {
+    private boolean interceptUnhandledKey(KeyEvent event, IBinder focusedToken) {
         final int keyCode = event.getKeyCode();
         final int repeatCount = event.getRepeatCount();
         final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
@@ -3949,7 +3988,7 @@
                     if (KeyEvent.metaStateHasModifiers(metaState & ~KeyEvent.META_SHIFT_MASK,
                             KeyEvent.META_CTRL_ON)) {
                         int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1;
-                        sendSwitchKeyboardLayout(event, direction);
+                        sendSwitchKeyboardLayout(event, focusedToken, direction);
                         return true;
                     }
                 }
@@ -3977,21 +4016,50 @@
                     mContext.closeSystemDialogs();
                 }
                 return true;
+            case KeyEvent.KEYCODE_STEM_PRIMARY:
+                handleUnhandledSystemKey(event);
+                sendSystemKeyToStatusBarAsync(event);
+                return true;
         }
 
         return false;
     }
 
-    private void sendSwitchKeyboardLayout(@NonNull KeyEvent event, int direction) {
-        mHandler.obtainMessage(MSG_SWITCH_KEYBOARD_LAYOUT, event.getDeviceId(),
-                direction).sendToTarget();
+    /**
+     * Called when a system key was sent to application and was unhandled. We will execute any
+     * queued actions associated with this key code at this point.
+     */
+    private void handleUnhandledSystemKey(KeyEvent event) {
+        if (!event.isSystem()) {
+            Log.wtf(
+                    TAG,
+                    "Illegal keycode provided to handleUnhandledSystemKey: "
+                            + KeyEvent.keyCodeToString(event.getKeyCode()));
+            return;
+        }
+        if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
+            // If the initial DOWN event is unhandled by app, follow-up events will also be
+            // unhandled by app. So we can handle the key event in system.
+            setDeferredKeyActionsExecutableAsync(event.getKeyCode(), event.getDownTime());
+        }
     }
 
-    private void handleSwitchKeyboardLayout(int deviceId, int direction) {
+    private void sendSwitchKeyboardLayout(@NonNull KeyEvent event,
+            @Nullable IBinder focusedToken, int direction) {
+        SwitchKeyboardLayoutMessageObject object =
+                new SwitchKeyboardLayoutMessageObject(event, focusedToken, direction);
+        mHandler.obtainMessage(MSG_SWITCH_KEYBOARD_LAYOUT, object).sendToTarget();
+    }
+
+    private void handleSwitchKeyboardLayout(@NonNull KeyEvent event, int direction,
+            IBinder focusedToken) {
         if (FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_UI)) {
-            InputMethodManagerInternal.get().switchKeyboardLayout(direction);
+            IBinder targetWindowToken =
+                    mWindowManagerInternal.getTargetWindowTokenFromInputToken(focusedToken);
+            InputMethodManagerInternal.get().onSwitchKeyboardLayoutShortcut(direction,
+                    event.getDisplayId(), targetWindowToken);
         } else {
-            mWindowManagerFuncs.switchKeyboardLayout(deviceId, direction);
+            mWindowManagerFuncs.switchKeyboardLayout(event.getDeviceId(), direction);
         }
     }
 
@@ -4001,7 +4069,7 @@
         if ((actions & ACTION_PASS_TO_USER) != 0) {
             long delayMillis = interceptKeyBeforeDispatching(
                     focusedToken, fallbackEvent, policyFlags);
-            if (delayMillis == 0 && !interceptUnhandledKey(fallbackEvent)) {
+            if (delayMillis == 0 && !interceptUnhandledKey(fallbackEvent, focusedToken)) {
                 return true;
             }
         }
@@ -4904,9 +4972,6 @@
             case KeyEvent.KEYCODE_MACRO_4:
                 result &= ~ACTION_PASS_TO_USER;
                 break;
-            case KeyEvent.KEYCODE_STEM_PRIMARY:
-                sendSystemKeyToStatusBarAsync(event);
-                break;
         }
 
         if (useHapticFeedback) {
@@ -5016,7 +5081,8 @@
      * Notify the StatusBar that a system key was pressed without blocking the current thread.
      */
     private void sendSystemKeyToStatusBarAsync(KeyEvent keyEvent) {
-        Message message = mHandler.obtainMessage(MSG_SYSTEM_KEY_PRESS, keyEvent);
+        // Make a copy because the event may be recycled.
+        Message message = mHandler.obtainMessage(MSG_SYSTEM_KEY_PRESS, KeyEvent.obtain(keyEvent));
         message.setAsynchronous(true);
         mHandler.sendMessage(message);
     }
@@ -6468,6 +6534,7 @@
         mGlobalKeyManager.dump(prefix, pw);
         mKeyCombinationManager.dump(prefix, pw);
         mSingleKeyGestureDetector.dump(prefix, pw);
+        mDeferredKeyActionExecutor.dump(prefix, pw);
 
         if (mWakeGestureListener != null) {
             mWakeGestureListener.dump(pw, prefix);
@@ -6793,4 +6860,19 @@
                     + " name.");
         }
     }
+
+    /** A helper class to check button override permission. */
+    static class ButtonOverridePermissionChecker {
+        boolean canAppOverrideSystemKey(Context context, int uid) {
+            return PermissionChecker.checkPermissionForDataDelivery(
+                            context,
+                            OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW,
+                            PID_UNKNOWN,
+                            uid,
+                            null,
+                            null,
+                            null)
+                    == PERMISSION_GRANTED;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/policy/TalkbackShortcutController.java b/services/core/java/com/android/server/policy/TalkbackShortcutController.java
new file mode 100644
index 0000000..906da2f
--- /dev/null
+++ b/services/core/java/com/android/server/policy/TalkbackShortcutController.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.policy;
+
+import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_WEAR_TRIPLE_PRESS_GESTURE;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.ServiceInfo;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.view.accessibility.AccessibilityManager;
+
+import com.android.internal.accessibility.util.AccessibilityStatsLogUtils;
+import com.android.internal.accessibility.util.AccessibilityUtils;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * This class controls talkback shortcut related operations such as toggling, quering and
+ * logging.
+ */
+@VisibleForTesting
+class TalkbackShortcutController {
+    private static final String TALKBACK_LABEL = "TalkBack";
+    private final Context mContext;
+    private final PackageManager mPackageManager;
+
+    TalkbackShortcutController(Context context) {
+        mContext = context;
+        mPackageManager = mContext.getPackageManager();
+    }
+
+    /**
+     * A function that toggles talkback service.
+     *
+     * @return talkback state after toggle. {@code true} if talkback is enabled, {@code false} if
+     * talkback is disabled
+     */
+    boolean toggleTalkback(int userId) {
+        final Set<ComponentName> enabledServices =
+                AccessibilityUtils.getEnabledServicesFromSettings(mContext, userId);
+        ComponentName componentName = getTalkbackComponent();
+        boolean isTalkbackAlreadyEnabled = enabledServices.contains(componentName);
+
+        if (isTalkBackShortcutGestureEnabled()) {
+            isTalkbackAlreadyEnabled = !isTalkbackAlreadyEnabled;
+            AccessibilityUtils.setAccessibilityServiceState(mContext, componentName,
+                    isTalkbackAlreadyEnabled);
+
+            // log stem triple press telemetry if it's a talkback enabled event.
+            if (componentName != null && isTalkbackAlreadyEnabled) {
+                logStemTriplePressAccessibilityTelemetry(componentName);
+            }
+        }
+        return isTalkbackAlreadyEnabled;
+    }
+
+    private ComponentName getTalkbackComponent() {
+        AccessibilityManager accessibilityManager = mContext.getSystemService(
+                AccessibilityManager.class);
+        List<AccessibilityServiceInfo> serviceInfos =
+                accessibilityManager.getInstalledAccessibilityServiceList();
+
+        for (AccessibilityServiceInfo service : serviceInfos) {
+            final ServiceInfo serviceInfo = service.getResolveInfo().serviceInfo;
+            if (isTalkback(serviceInfo)) {
+                return new ComponentName(serviceInfo.packageName, serviceInfo.name);
+            }
+        }
+        return null;
+    }
+
+    boolean isTalkBackShortcutGestureEnabled() {
+        return Settings.System.getIntForUser(mContext.getContentResolver(),
+                Settings.System.WEAR_ACCESSIBILITY_GESTURE_ENABLED,
+                /* def= */ 0, UserHandle.USER_CURRENT) == 1;
+    }
+
+    /**
+     * A function that logs stem triple press accessibility telemetry. If the user setup (Oobe)
+     * is not completed, set the WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE setting which
+     * will be later logged via Settings Snapshot  else, log ACCESSIBILITY_SHORTCUT_REPORTED atom
+     */
+    private void logStemTriplePressAccessibilityTelemetry(ComponentName componentName) {
+        if (!AccessibilityUtils.isUserSetupCompleted(mContext)) {
+            Settings.Secure.putInt(mContext.getContentResolver(),
+                    Settings.System.WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE, 1);
+            return;
+        }
+        AccessibilityStatsLogUtils.logAccessibilityShortcutActivated(mContext,
+                componentName,
+                ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_WEAR_TRIPLE_PRESS_GESTURE,
+                /* serviceEnabled= */ true);
+    }
+
+    private boolean isTalkback(ServiceInfo info) {
+        return TALKBACK_LABEL.equals(info.loadLabel(mPackageManager).toString());
+    }
+}
diff --git a/services/core/java/com/android/server/power/ThermalManagerService.java b/services/core/java/com/android/server/power/ThermalManagerService.java
index 99653ae..24d7acd 100644
--- a/services/core/java/com/android/server/power/ThermalManagerService.java
+++ b/services/core/java/com/android/server/power/ThermalManagerService.java
@@ -759,6 +759,36 @@
                     case "NPU":
                         type = Temperature.TYPE_NPU;
                         break;
+                    case "TPU":
+                        type = Temperature.TYPE_TPU;
+                        break;
+                    case "DISPLAY":
+                        type = Temperature.TYPE_DISPLAY;
+                        break;
+                    case "MODEM":
+                        type = Temperature.TYPE_MODEM;
+                        break;
+                    case "SOC":
+                        type = Temperature.TYPE_SOC;
+                        break;
+                    case "WIFI":
+                        type = Temperature.TYPE_WIFI;
+                        break;
+                    case "CAMERA":
+                        type = Temperature.TYPE_CAMERA;
+                        break;
+                    case "FLASHLIGHT":
+                        type = Temperature.TYPE_FLASHLIGHT;
+                        break;
+                    case "SPEAKER":
+                        type = Temperature.TYPE_SPEAKER;
+                        break;
+                    case "AMBIENT":
+                        type = Temperature.TYPE_AMBIENT;
+                        break;
+                    case "POGO":
+                        type = Temperature.TYPE_POGO;
+                        break;
                     default:
                         pw.println("Invalid temperature type: " + typeName);
                         return -1;
diff --git a/services/core/java/com/android/server/power/stats/AggregatedPowerStatsConfig.java b/services/core/java/com/android/server/power/stats/AggregatedPowerStatsConfig.java
index 43fd15d..6fbbc0f 100644
--- a/services/core/java/com/android/server/power/stats/AggregatedPowerStatsConfig.java
+++ b/services/core/java/com/android/server/power/stats/AggregatedPowerStatsConfig.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.os.BatteryConsumer;
 
-import com.android.internal.os.MultiStateStats;
 import com.android.internal.os.PowerStats;
 
 import java.lang.annotation.Retention;
diff --git a/services/core/java/com/android/server/power/stats/AggregatedPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/AggregatedPowerStatsProcessor.java
index 5fd8ddf..7feb964 100644
--- a/services/core/java/com/android/server/power/stats/AggregatedPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/AggregatedPowerStatsProcessor.java
@@ -19,7 +19,6 @@
 import android.annotation.Nullable;
 import android.util.Log;
 
-import com.android.internal.os.MultiStateStats;
 import com.android.internal.os.PowerStats;
 
 import java.util.ArrayList;
diff --git a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
index 698f6ea..03f3763 100644
--- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
+++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
@@ -11744,8 +11744,14 @@
         // start time
         long monotonicStartTime =
                 mMonotonicClock.monotonicTime() - batteryUsageStats.getStatsDuration();
-        mHandler.post(() ->
-                mPowerStatsStore.storeBatteryUsageStats(monotonicStartTime, batteryUsageStats));
+        mHandler.post(() -> {
+            mPowerStatsStore.storeBatteryUsageStats(monotonicStartTime, batteryUsageStats);
+            try {
+                batteryUsageStats.close();
+            } catch (IOException e) {
+                Log.e(TAG, "Cannot close BatteryUsageStats", e);
+            }
+        });
     }
 
     @GuardedBy("this")
@@ -15903,6 +15909,7 @@
 
         mEndPlatformVersion = Build.ID;
 
+        mMonotonicEndTime = MonotonicClock.UNDEFINED;
         mHistory.continueRecordingHistory();
 
         recordDailyStatsIfNeededLocked(false, mClock.currentTimeMillis());
diff --git a/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java b/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
index 096c5e6..32656b1 100644
--- a/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
+++ b/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
@@ -126,18 +126,15 @@
      */
     public List<BatteryUsageStats> getBatteryUsageStats(BatteryStatsImpl stats,
             List<BatteryUsageStatsQuery> queries) {
-        if (mPowerStatsExporterEnabled) {
-            stats.collectPowerStatsSamples();
-        }
-
         ArrayList<BatteryUsageStats> results = new ArrayList<>(queries.size());
         synchronized (stats) {
             stats.prepareForDumpLocked();
-            final long currentTimeMillis = mClock.currentTimeMillis();
-            for (int i = 0; i < queries.size(); i++) {
-                results.add(getBatteryUsageStats(stats, queries.get(i), currentTimeMillis));
-            }
         }
+        final long currentTimeMillis = mClock.currentTimeMillis();
+        for (int i = 0; i < queries.size(); i++) {
+            results.add(getBatteryUsageStats(stats, queries.get(i), currentTimeMillis));
+        }
+
         return results;
     }
 
diff --git a/services/core/java/com/android/server/power/stats/CpuPowerStatsCollector.java b/services/core/java/com/android/server/power/stats/CpuPowerStatsCollector.java
index 4442845..1af1271 100644
--- a/services/core/java/com/android/server/power/stats/CpuPowerStatsCollector.java
+++ b/services/core/java/com/android/server/power/stats/CpuPowerStatsCollector.java
@@ -78,7 +78,7 @@
     private final SparseArray<UidStats> mUidStats = new SparseArray<>();
     private boolean mIsPerUidTimeInStateSupported;
     private PowerStatsInternal mPowerStatsInternal;
-    private int[] mCpuEnergyConsumerIds;
+    private int[] mCpuEnergyConsumerIds = new int[0];
     private PowerStats.Descriptor mPowerStatsDescriptor;
     // Reusable instance
     private PowerStats mCpuPowerStats;
@@ -286,8 +286,6 @@
 
         if (mPowerStatsInternal != null) {
             readCpuEnergyConsumerIds();
-        } else {
-            mCpuEnergyConsumerIds = new int[0];
         }
 
         int cpuScalingStepCount = mCpuScalingPolicies.getScalingStepCount();
@@ -320,7 +318,6 @@
     private void readCpuEnergyConsumerIds() {
         EnergyConsumer[] energyConsumerInfo = mPowerStatsInternal.getEnergyConsumerInfo();
         if (energyConsumerInfo == null) {
-            mCpuEnergyConsumerIds = new int[0];
             return;
         }
 
diff --git a/core/java/com/android/internal/os/MultiStateStats.java b/services/core/java/com/android/server/power/stats/MultiStateStats.java
similarity index 99%
rename from core/java/com/android/internal/os/MultiStateStats.java
rename to services/core/java/com/android/server/power/stats/MultiStateStats.java
index ecfed53..9356950 100644
--- a/core/java/com/android/internal/os/MultiStateStats.java
+++ b/services/core/java/com/android/server/power/stats/MultiStateStats.java
@@ -14,11 +14,12 @@
  * limitations under the License.
  */
 
-package com.android.internal.os;
+package com.android.server.power.stats;
 
 import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.LongArrayMultiStateCounter;
 import com.android.internal.util.Preconditions;
 import com.android.modules.utils.TypedXmlPullParser;
 import com.android.modules.utils.TypedXmlSerializer;
diff --git a/services/core/java/com/android/server/power/stats/PowerComponentAggregatedPowerStats.java b/services/core/java/com/android/server/power/stats/PowerComponentAggregatedPowerStats.java
index 0facb9c..1637022 100644
--- a/services/core/java/com/android/server/power/stats/PowerComponentAggregatedPowerStats.java
+++ b/services/core/java/com/android/server/power/stats/PowerComponentAggregatedPowerStats.java
@@ -21,7 +21,6 @@
 import android.util.IndentingPrintWriter;
 import android.util.SparseArray;
 
-import com.android.internal.os.MultiStateStats;
 import com.android.internal.os.PowerStats;
 import com.android.modules.utils.TypedXmlPullParser;
 import com.android.modules.utils.TypedXmlSerializer;
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsAggregator.java b/services/core/java/com/android/server/power/stats/PowerStatsAggregator.java
index 3f88a2d..cd3db36 100644
--- a/services/core/java/com/android/server/power/stats/PowerStatsAggregator.java
+++ b/services/core/java/com/android/server/power/stats/PowerStatsAggregator.java
@@ -30,16 +30,15 @@
  */
 public class PowerStatsAggregator {
     private static final long UNINITIALIZED = -1;
-    private final AggregatedPowerStats mStats;
     private final AggregatedPowerStatsConfig mAggregatedPowerStatsConfig;
     private final BatteryStatsHistory mHistory;
     private final SparseArray<AggregatedPowerStatsProcessor> mProcessors = new SparseArray<>();
+    private AggregatedPowerStats mStats;
     private int mCurrentBatteryState = AggregatedPowerStatsConfig.POWER_STATE_BATTERY;
     private int mCurrentScreenState = AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
 
     public PowerStatsAggregator(AggregatedPowerStatsConfig aggregatedPowerStatsConfig,
             BatteryStatsHistory history) {
-        mStats = new AggregatedPowerStats(aggregatedPowerStatsConfig);
         mAggregatedPowerStatsConfig = aggregatedPowerStatsConfig;
         mHistory = history;
         for (AggregatedPowerStatsConfig.PowerComponent powerComponentsConfig :
@@ -67,75 +66,81 @@
      */
     public void aggregatePowerStats(long startTimeMs, long endTimeMs,
             Consumer<AggregatedPowerStats> consumer) {
-        boolean clockUpdateAdded = false;
-        long baseTime = startTimeMs > 0 ? startTimeMs : UNINITIALIZED;
-        long lastTime = 0;
-        try (BatteryStatsHistoryIterator iterator =
-                     mHistory.copy().iterate(startTimeMs, endTimeMs)) {
-            while (iterator.hasNext()) {
-                BatteryStats.HistoryItem item = iterator.next();
+        synchronized (this) {
+            if (mStats == null) {
+                mStats = new AggregatedPowerStats(mAggregatedPowerStatsConfig);
+            }
 
-                if (!clockUpdateAdded) {
-                    mStats.addClockUpdate(item.time, item.currentTime);
-                    if (baseTime == UNINITIALIZED) {
-                        baseTime = item.time;
-                    }
-                    clockUpdateAdded = true;
-                } else if (item.cmd == BatteryStats.HistoryItem.CMD_CURRENT_TIME
-                           || item.cmd == BatteryStats.HistoryItem.CMD_RESET) {
-                    mStats.addClockUpdate(item.time, item.currentTime);
-                }
+            boolean clockUpdateAdded = false;
+            long baseTime = startTimeMs > 0 ? startTimeMs : UNINITIALIZED;
+            long lastTime = 0;
+            try (BatteryStatsHistoryIterator iterator =
+                         mHistory.copy().iterate(startTimeMs, endTimeMs)) {
+                while (iterator.hasNext()) {
+                    BatteryStats.HistoryItem item = iterator.next();
 
-                lastTime = item.time;
-
-                int batteryState =
-                        (item.states & BatteryStats.HistoryItem.STATE_BATTERY_PLUGGED_FLAG) != 0
-                                ? AggregatedPowerStatsConfig.POWER_STATE_OTHER
-                                : AggregatedPowerStatsConfig.POWER_STATE_BATTERY;
-                if (batteryState != mCurrentBatteryState) {
-                    mStats.setDeviceState(AggregatedPowerStatsConfig.STATE_POWER, batteryState,
-                            item.time);
-                    mCurrentBatteryState = batteryState;
-                }
-
-                int screenState =
-                        (item.states & BatteryStats.HistoryItem.STATE_SCREEN_ON_FLAG) != 0
-                                ? AggregatedPowerStatsConfig.SCREEN_STATE_ON
-                                : AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
-                if (screenState != mCurrentScreenState) {
-                    mStats.setDeviceState(AggregatedPowerStatsConfig.STATE_SCREEN, screenState,
-                            item.time);
-                    mCurrentScreenState = screenState;
-                }
-
-                if (item.processStateChange != null) {
-                    mStats.setUidState(item.processStateChange.uid,
-                            AggregatedPowerStatsConfig.STATE_PROCESS_STATE,
-                            item.processStateChange.processState, item.time);
-                }
-
-                if (item.powerStats != null) {
-                    if (!mStats.isCompatible(item.powerStats)) {
-                        if (lastTime > baseTime) {
-                            mStats.setDuration(lastTime - baseTime);
-                            finish(mStats);
-                            consumer.accept(mStats);
-                        }
-                        mStats.reset();
+                    if (!clockUpdateAdded) {
                         mStats.addClockUpdate(item.time, item.currentTime);
-                        baseTime = lastTime = item.time;
+                        if (baseTime == UNINITIALIZED) {
+                            baseTime = item.time;
+                        }
+                        clockUpdateAdded = true;
+                    } else if (item.cmd == BatteryStats.HistoryItem.CMD_CURRENT_TIME
+                               || item.cmd == BatteryStats.HistoryItem.CMD_RESET) {
+                        mStats.addClockUpdate(item.time, item.currentTime);
                     }
-                    mStats.addPowerStats(item.powerStats, item.time);
+
+                    lastTime = item.time;
+
+                    int batteryState =
+                            (item.states & BatteryStats.HistoryItem.STATE_BATTERY_PLUGGED_FLAG) != 0
+                                    ? AggregatedPowerStatsConfig.POWER_STATE_OTHER
+                                    : AggregatedPowerStatsConfig.POWER_STATE_BATTERY;
+                    if (batteryState != mCurrentBatteryState) {
+                        mStats.setDeviceState(AggregatedPowerStatsConfig.STATE_POWER, batteryState,
+                                item.time);
+                        mCurrentBatteryState = batteryState;
+                    }
+
+                    int screenState =
+                            (item.states & BatteryStats.HistoryItem.STATE_SCREEN_ON_FLAG) != 0
+                                    ? AggregatedPowerStatsConfig.SCREEN_STATE_ON
+                                    : AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
+                    if (screenState != mCurrentScreenState) {
+                        mStats.setDeviceState(AggregatedPowerStatsConfig.STATE_SCREEN, screenState,
+                                item.time);
+                        mCurrentScreenState = screenState;
+                    }
+
+                    if (item.processStateChange != null) {
+                        mStats.setUidState(item.processStateChange.uid,
+                                AggregatedPowerStatsConfig.STATE_PROCESS_STATE,
+                                item.processStateChange.processState, item.time);
+                    }
+
+                    if (item.powerStats != null) {
+                        if (!mStats.isCompatible(item.powerStats)) {
+                            if (lastTime > baseTime) {
+                                mStats.setDuration(lastTime - baseTime);
+                                finish(mStats);
+                                consumer.accept(mStats);
+                            }
+                            mStats.reset();
+                            mStats.addClockUpdate(item.time, item.currentTime);
+                            baseTime = lastTime = item.time;
+                        }
+                        mStats.addPowerStats(item.powerStats, item.time);
+                    }
                 }
             }
-        }
-        if (lastTime > baseTime) {
-            mStats.setDuration(lastTime - baseTime);
-            finish(mStats);
-            consumer.accept(mStats);
-        }
+            if (lastTime > baseTime) {
+                mStats.setDuration(lastTime - baseTime);
+                finish(mStats);
+                consumer.accept(mStats);
+            }
 
-        mStats.reset();     // to free up memory
+            mStats.reset();     // to free up memory
+        }
     }
 
     private void finish(AggregatedPowerStats stats) {
@@ -147,4 +152,13 @@
             }
         }
     }
+
+    /**
+     * Reset to prepare for a new aggregation session.
+     */
+    public void reset() {
+        synchronized (this) {
+            mStats = null;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsCollector.java b/services/core/java/com/android/server/power/stats/PowerStatsCollector.java
index abfe9de..c76797ba 100644
--- a/services/core/java/com/android/server/power/stats/PowerStatsCollector.java
+++ b/services/core/java/com/android/server/power/stats/PowerStatsCollector.java
@@ -20,7 +20,6 @@
 import android.os.ConditionVariable;
 import android.os.Handler;
 import android.os.PersistableBundle;
-import android.util.FastImmutableArraySet;
 import android.util.IndentingPrintWriter;
 import android.util.Slog;
 
@@ -30,8 +29,9 @@
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 import java.util.function.Consumer;
-import java.util.stream.Stream;
 
 /**
  * Collects snapshots of power-related system statistics.
@@ -246,8 +246,7 @@
 
     @GuardedBy("this")
     @SuppressWarnings("unchecked")
-    private volatile FastImmutableArraySet<Consumer<PowerStats>> mConsumerList =
-            new FastImmutableArraySet<Consumer<PowerStats>>(new Consumer[0]);
+    private volatile List<Consumer<PowerStats>> mConsumerList = Collections.emptyList();
 
     public PowerStatsCollector(Handler handler, long throttlePeriodMs, Clock clock) {
         mHandler = handler;
@@ -262,9 +261,13 @@
     @SuppressWarnings("unchecked")
     public void addConsumer(Consumer<PowerStats> consumer) {
         synchronized (this) {
-            mConsumerList = new FastImmutableArraySet<Consumer<PowerStats>>(
-                    Stream.concat(mConsumerList.stream(), Stream.of(consumer))
-                            .toArray(Consumer[]::new));
+            if (mConsumerList.contains(consumer)) {
+                return;
+            }
+
+            List<Consumer<PowerStats>> newList = new ArrayList<>(mConsumerList);
+            newList.add(consumer);
+            mConsumerList = Collections.unmodifiableList(newList);
         }
     }
 
@@ -275,9 +278,9 @@
     @SuppressWarnings("unchecked")
     public void removeConsumer(Consumer<PowerStats> consumer) {
         synchronized (this) {
-            mConsumerList = new FastImmutableArraySet<Consumer<PowerStats>>(
-                    mConsumerList.stream().filter(c -> c != consumer)
-                            .toArray(Consumer[]::new));
+            List<Consumer<PowerStats>> newList = new ArrayList<>(mConsumerList);
+            newList.remove(consumer);
+            mConsumerList = Collections.unmodifiableList(newList);
         }
     }
 
@@ -297,13 +300,14 @@
     }
 
     @SuppressWarnings("GuardedBy")  // Field is volatile
-    private void collectAndDeliverStats() {
+    public void collectAndDeliverStats() {
         PowerStats stats = collectStats();
         if (stats == null) {
             return;
         }
-        for (Consumer<PowerStats> consumer : mConsumerList) {
-            consumer.accept(stats);
+        List<Consumer<PowerStats>> consumerList = mConsumerList;
+        for (int i = consumerList.size() - 1; i >= 0; i--) {
+            consumerList.get(i).accept(stats);
         }
     }
 
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsExporter.java b/services/core/java/com/android/server/power/stats/PowerStatsExporter.java
index 1f6f113..4f4ddca 100644
--- a/services/core/java/com/android/server/power/stats/PowerStatsExporter.java
+++ b/services/core/java/com/android/server/power/stats/PowerStatsExporter.java
@@ -22,7 +22,6 @@
 import android.os.UidBatteryConsumer;
 import android.util.Slog;
 
-import com.android.internal.os.MultiStateStats;
 import com.android.internal.os.PowerStats;
 
 import java.util.ArrayList;
@@ -111,6 +110,7 @@
             mPowerStatsAggregator.aggregatePowerStats(maxEndTime, monotonicEndTime,
                     stats -> populateBatteryUsageStatsBuilder(batteryUsageStatsBuilder, stats));
         }
+        mPowerStatsAggregator.reset();
     }
 
     private void populateBatteryUsageStatsBuilder(
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsScheduler.java b/services/core/java/com/android/server/power/stats/PowerStatsScheduler.java
index 97d872a..abe4c0c 100644
--- a/services/core/java/com/android/server/power/stats/PowerStatsScheduler.java
+++ b/services/core/java/com/android/server/power/stats/PowerStatsScheduler.java
@@ -18,7 +18,6 @@
 
 import android.annotation.DurationMillisLong;
 import android.app.AlarmManager;
-import android.content.Context;
 import android.os.ConditionVariable;
 import android.os.Handler;
 import android.util.IndentingPrintWriter;
@@ -30,6 +29,7 @@
 import java.io.PrintWriter;
 import java.util.Calendar;
 import java.util.concurrent.TimeUnit;
+import java.util.function.Supplier;
 
 /**
  * Controls the frequency at which {@link PowerStatsSpan}'s are generated and stored in
@@ -39,7 +39,7 @@
     private static final long MINUTE_IN_MILLIS = TimeUnit.MINUTES.toMillis(1);
     private static final long HOUR_IN_MILLIS = TimeUnit.HOURS.toMillis(1);
 
-    private final Context mContext;
+    private final AlarmScheduler mAlarmScheduler;
     private boolean mEnablePeriodicPowerStatsCollection;
     @DurationMillisLong
     private final long mAggregatedPowerStatsSpanDuration;
@@ -49,24 +49,38 @@
     private final Clock mClock;
     private final MonotonicClock mMonotonicClock;
     private final Handler mHandler;
-    private final BatteryStatsImpl mBatteryStats;
+    private final Runnable mPowerStatsCollector;
+    private final Supplier<Long> mEarliestAvailableBatteryHistoryTimeMs;
     private final PowerStatsAggregator mPowerStatsAggregator;
     private long mLastSavedSpanEndMonotonicTime;
 
-    public PowerStatsScheduler(Context context, PowerStatsAggregator powerStatsAggregator,
+    /**
+     * External dependency on AlarmManager.
+     */
+    public interface AlarmScheduler {
+        /**
+         * Should use AlarmManager to schedule an inexact, non-wakeup alarm.
+         */
+        void scheduleAlarm(long triggerAtMillis, String tag,
+                AlarmManager.OnAlarmListener onAlarmListener, Handler handler);
+    }
+
+    public PowerStatsScheduler(Runnable powerStatsCollector,
+            PowerStatsAggregator powerStatsAggregator,
             @DurationMillisLong long aggregatedPowerStatsSpanDuration,
             @DurationMillisLong long powerStatsAggregationPeriod, PowerStatsStore powerStatsStore,
-            Clock clock, MonotonicClock monotonicClock, Handler handler,
-            BatteryStatsImpl batteryStats) {
-        mContext = context;
+            AlarmScheduler alarmScheduler, Clock clock, MonotonicClock monotonicClock,
+            Supplier<Long> earliestAvailableBatteryHistoryTimeMs, Handler handler) {
         mPowerStatsAggregator = powerStatsAggregator;
         mAggregatedPowerStatsSpanDuration = aggregatedPowerStatsSpanDuration;
         mPowerStatsAggregationPeriod = powerStatsAggregationPeriod;
         mPowerStatsStore = powerStatsStore;
+        mAlarmScheduler = alarmScheduler;
         mClock = clock;
         mMonotonicClock = monotonicClock;
         mHandler = handler;
-        mBatteryStats = batteryStats;
+        mPowerStatsCollector = powerStatsCollector;
+        mEarliestAvailableBatteryHistoryTimeMs = earliestAvailableBatteryHistoryTimeMs;
     }
 
     /**
@@ -81,9 +95,8 @@
     }
 
     private void scheduleNextPowerStatsAggregation() {
-        AlarmManager alarmManager = mContext.getSystemService(AlarmManager.class);
-        alarmManager.set(AlarmManager.ELAPSED_REALTIME,
-                mClock.elapsedRealtime() + mPowerStatsAggregationPeriod, "PowerStats",
+        mAlarmScheduler.scheduleAlarm(mClock.elapsedRealtime() + mPowerStatsAggregationPeriod,
+                "PowerStats",
                 () -> {
                     schedulePowerStatsAggregation();
                     mHandler.post(this::scheduleNextPowerStatsAggregation);
@@ -96,7 +109,7 @@
     @VisibleForTesting
     public void schedulePowerStatsAggregation() {
         // Catch up the power stats collectors
-        mBatteryStats.schedulePowerStatsSampleCollection();
+        mPowerStatsCollector.run();
         mHandler.post(this::aggregateAndStorePowerStats);
     }
 
@@ -105,7 +118,7 @@
         long currentMonotonicTime = mMonotonicClock.monotonicTime();
         long startTime = getLastSavedSpanEndMonotonicTime();
         if (startTime < 0) {
-            startTime = mBatteryStats.getHistory().getStartTime();
+            startTime = mEarliestAvailableBatteryHistoryTimeMs.get();
         }
         long endTimeMs = alignToWallClock(startTime + mAggregatedPowerStatsSpanDuration,
                 mAggregatedPowerStatsSpanDuration, currentMonotonicTime, currentTimeMillis);
@@ -140,7 +153,8 @@
             mPowerStatsStore.dump(ipw);
             // Aggregate the remainder of power stats and dump the results without storing them yet.
             long powerStoreEndMonotonicTime = getLastSavedSpanEndMonotonicTime();
-            mPowerStatsAggregator.aggregatePowerStats(powerStoreEndMonotonicTime, 0,
+            mPowerStatsAggregator.aggregatePowerStats(powerStoreEndMonotonicTime,
+                    MonotonicClock.UNDEFINED,
                     stats -> {
                         // Create a PowerStatsSpan for consistency of the textual output
                         PowerStatsSpan span = PowerStatsStore.createPowerStatsSpan(stats);
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index d172d3f..9a85c42 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -865,21 +865,19 @@
             mDeviceLockedForUser.put(userId, locked);
         }
         if (changed) {
-            dispatchDeviceLocked(userId, locked);
-            Authorization.onLockScreenEvent(locked, userId, null,
-                    getBiometricSids(userId));
+            notifyTrustAgentsOfDeviceLockState(userId, locked);
+            notifyKeystoreOfDeviceLockState(userId, locked);
             // Also update the user's profiles who have unified challenge, since they
             // share the same unlocked state (see {@link #isDeviceLocked(int)})
             for (int profileHandle : mUserManager.getEnabledProfileIds(userId)) {
                 if (mLockPatternUtils.isManagedProfileWithUnifiedChallenge(profileHandle)) {
-                    Authorization.onLockScreenEvent(locked, profileHandle, null,
-                            getBiometricSids(profileHandle));
+                    notifyKeystoreOfDeviceLockState(profileHandle, locked);
                 }
             }
         }
     }
 
-    private void dispatchDeviceLocked(int userId, boolean isLocked) {
+    private void notifyTrustAgentsOfDeviceLockState(int userId, boolean isLocked) {
         for (int i = 0; i < mActiveAgents.size(); i++) {
             AgentInfo agent = mActiveAgents.valueAt(i);
             if (agent.userId == userId) {
@@ -892,6 +890,17 @@
         }
     }
 
+    private void notifyKeystoreOfDeviceLockState(int userId, boolean isLocked) {
+        if (isLocked) {
+            Authorization.onDeviceLocked(userId, getBiometricSids(userId));
+        } else {
+            // Notify Keystore that the device is now unlocked for the user.  Note that for unlocks
+            // with LSKF, this is redundant with the call from LockSettingsService which provides
+            // the password.  However, for unlocks with biometric or trust agent, this is required.
+            Authorization.onDeviceUnlocked(userId, /* password= */ null);
+        }
+    }
+
     private void dispatchEscrowTokenActivatedLocked(long handle, int userId) {
         for (int i = 0; i < mActiveAgents.size(); i++) {
             AgentInfo agent = mActiveAgents.valueAt(i);
@@ -1425,10 +1434,10 @@
         }
     }
 
-    private long[] getBiometricSids(int userId) {
+    private @NonNull long[] getBiometricSids(int userId) {
         BiometricManager biometricManager = mContext.getSystemService(BiometricManager.class);
         if (biometricManager == null) {
-            return null;
+            return new long[0];
         }
         return biometricManager.getAuthenticatorIds(userId);
     }
@@ -1599,14 +1608,12 @@
                     user.name, user.id, user.flags);
             if (!user.supportsSwitchToByUser()) {
                 final boolean locked;
-                if (user.isProfile()) {
-                    if (mLockPatternUtils.isSeparateProfileChallengeEnabled(user.id)) {
-                        fout.print(" (profile with separate challenge)");
-                        locked = isDeviceLockedInner(user.id);
-                    } else {
-                        fout.print(" (profile with unified challenge)");
-                        locked = isDeviceLockedInner(resolveProfileParent(user.id));
-                    }
+                if (mLockPatternUtils.isProfileWithUnifiedChallenge(user.id)) {
+                    fout.print(" (profile with unified challenge)");
+                    locked = isDeviceLockedInner(resolveProfileParent(user.id));
+                } else if (mLockPatternUtils.isSeparateProfileChallengeEnabled(user.id)) {
+                    fout.print(" (profile with separate challenge)");
+                    locked = isDeviceLockedInner(user.id);
                 } else {
                     fout.println(" (user that cannot be switched to)");
                     locked = isDeviceLockedInner(user.id);
@@ -1680,8 +1687,7 @@
                         mDeviceLockedForUser.put(userId, locked);
                     }
 
-                    Authorization.onLockScreenEvent(locked, userId, null,
-                            getBiometricSids(userId));
+                    notifyKeystoreOfDeviceLockState(userId, locked);
 
                     if (locked) {
                         try {
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index e4c7fc1..d903ad4 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -41,7 +41,6 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.pm.UserInfo;
-import android.content.res.Resources;
 import android.graphics.Rect;
 import android.hardware.hdmi.HdmiControlManager;
 import android.hardware.hdmi.HdmiDeviceInfo;
@@ -1851,14 +1850,14 @@
                             sessionState.currentChannel = channelUri;
                             notifyCurrentChannelInfosUpdatedLocked(userState);
                             if (!sessionState.isRecordingSession) {
-                                String actualInputId = getActualInputId(sessionState);
-                                if (!TextUtils.equals(mOnScreenInputId, actualInputId)) {
+                                String sessionActualInputId = getSessionActualInputId(sessionState);
+                                if (!TextUtils.equals(mOnScreenInputId, sessionActualInputId)) {
                                     logExternalInputEvent(
                                             FrameworkStatsLog
                                                     .EXTERNAL_TV_INPUT_EVENT__EVENT_TYPE__TUNED,
-                                            actualInputId, sessionState);
+                                            sessionActualInputId, sessionState);
                                 }
-                                mOnScreenInputId = actualInputId;
+                                mOnScreenInputId = sessionActualInputId;
                                 mOnScreenSessionState = sessionState;
                             }
                         }
@@ -2081,6 +2080,45 @@
         }
 
         @Override
+        public void stopPlayback(IBinder sessionToken, int mode, int userId) {
+            final int callingUid = Binder.getCallingUid();
+            final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
+                    userId, "stopPlayback");
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    try {
+                        getSessionLocked(sessionToken, callingUid, resolvedUserId).stopPlayback(
+                                mode);
+                    } catch (RemoteException | SessionNotFoundException e) {
+                        Slog.e(TAG, "error in stopPlayback(mode)", e);
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
+        public void startPlayback(IBinder sessionToken, int userId) {
+            final int callingUid = Binder.getCallingUid();
+            final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
+                    userId, "stopPlayback");
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    try {
+                        getSessionLocked(sessionToken, callingUid, resolvedUserId).startPlayback();
+                    } catch (RemoteException | SessionNotFoundException e) {
+                        Slog.e(TAG, "error in startPlayback()", e);
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
         public void timeShiftPlay(IBinder sessionToken, final Uri recordedProgramUri, int userId) {
             final int callingUid = Binder.getCallingUid();
             final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
@@ -2985,11 +3023,20 @@
     // e.g. if an HDMI port has a CEC device plugged in, the actual input id of the HDMI
     // session should be the input id of CEC device instead of the default HDMI input id.
     @GuardedBy("mLock")
-    private String getActualInputId(SessionState sessionState) {
+    private String getSessionActualInputId(SessionState sessionState) {
         UserState userState = getOrCreateUserStateLocked(sessionState.userId);
         TvInputState tvInputState = userState.inputMap.get(sessionState.inputId);
+        if (tvInputState == null) {
+            Slog.w(TAG, "No TvInputState for sessionState.inputId " + sessionState.inputId);
+            return sessionState.inputId;
+        }
         TvInputInfo tvInputInfo = tvInputState.info;
-        String actualInputId = sessionState.inputId;
+        if (tvInputInfo == null) {
+            Slog.w(TAG, "TvInputInfo is null for input id " + sessionState.inputId);
+            return sessionState.inputId;
+        }
+
+        String sessionActualInputId = sessionState.inputId;
         switch (tvInputInfo.getType()) {
             case TvInputInfo.TYPE_HDMI:
                 // TODO: find a better approach towards active CEC device in future
@@ -2997,13 +3044,13 @@
                         mTvInputHardwareManager.getHdmiParentInputMap();
                 if (hdmiParentInputMap.containsKey(sessionState.inputId)) {
                     List<String> parentInputList = hdmiParentInputMap.get(sessionState.inputId);
-                    actualInputId = parentInputList.get(0);
+                    sessionActualInputId = parentInputList.get(0);
                 }
                 break;
             default:
                 break;
         }
-        return actualInputId;
+        return sessionActualInputId;
     }
 
     @Nullable
@@ -3111,7 +3158,21 @@
     private void logExternalInputEvent(int eventType, String inputId, SessionState sessionState) {
         UserState userState = getOrCreateUserStateLocked(sessionState.userId);
         TvInputState tvInputState = userState.inputMap.get(inputId);
+        if (tvInputState == null) {
+            Slog.w(TAG, "Cannot find input state for input id " + inputId);
+            // If input id is not found, try to find the input id of this sessionState.
+            inputId = sessionState.inputId;
+            tvInputState = userState.inputMap.get(inputId);
+        }
+        if (tvInputState == null) {
+            Slog.w(TAG, "Cannot find input state for sessionState.inputId " + inputId);
+            return;
+        }
         TvInputInfo tvInputInfo = tvInputState.info;
+        if (tvInputInfo == null) {
+            Slog.w(TAG, "TvInputInfo is null for input id " + inputId);
+            return;
+        }
         int inputState = tvInputState.state;
         int inputType = tvInputInfo.getType();
         String displayName = tvInputInfo.loadLabel(mContext).toString();
@@ -3647,14 +3708,14 @@
                         mSessionState.currentChannel = channelUri;
                         notifyCurrentChannelInfosUpdatedLocked(userState);
                         if (!mSessionState.isRecordingSession) {
-                            String actualInputId = getActualInputId(mSessionState);
-                            if (!TextUtils.equals(mOnScreenInputId, actualInputId)) {
+                            String sessionActualInputId = getSessionActualInputId(mSessionState);
+                            if (!TextUtils.equals(mOnScreenInputId, sessionActualInputId)) {
                                 logExternalInputEvent(
                                         FrameworkStatsLog
                                                 .EXTERNAL_TV_INPUT_EVENT__EVENT_TYPE__TUNED,
-                                        actualInputId, mSessionState);
+                                        sessionActualInputId, mSessionState);
                             }
-                            mOnScreenInputId = actualInputId;
+                            mOnScreenInputId = sessionActualInputId;
                             mOnScreenSessionState = mSessionState;
                         }
                     }
diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerService.java b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
index 7862f58..e501b9d 100644
--- a/services/core/java/com/android/server/uri/UriGrantsManagerService.java
+++ b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
@@ -146,17 +146,31 @@
             mGrantedUriPermissions = new SparseArray<>();
 
     private UriGrantsManagerService() {
-        this(SystemServiceManager.ensureSystemDir());
+        this(SystemServiceManager.ensureSystemDir(), "uri-grants");
     }
 
-    private UriGrantsManagerService(File systemDir) {
+    private UriGrantsManagerService(File systemDir, String commitTag) {
         mH = new H(IoThread.get().getLooper());
-        mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml"), "uri-grants");
+        final File file = new File(systemDir, "urigrants.xml");
+        mGrantFile = (commitTag != null) ? new AtomicFile(file, commitTag) : new AtomicFile(file);
     }
 
     @VisibleForTesting
     static UriGrantsManagerService createForTest(File systemDir) {
-        final UriGrantsManagerService service = new UriGrantsManagerService(systemDir);
+        final UriGrantsManagerService service = new UriGrantsManagerService(systemDir, null) {
+            @VisibleForTesting
+            protected int checkUidPermission(String permission, int uid) {
+                // Tests have no permission granted
+                return PackageManager.PERMISSION_DENIED;
+            }
+
+            @VisibleForTesting
+            protected int checkComponentPermission(String permission, int uid, int owningUid,
+                    boolean exported) {
+                // Tests have no permission granted
+                return PackageManager.PERMISSION_DENIED;
+            }
+        };
         service.mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
         service.mPmInternal = LocalServices.getService(PackageManagerInternal.class);
         return service;
@@ -202,7 +216,8 @@
         }
     }
 
-    private int checkUidPermission(String permission, int uid) {
+    @VisibleForTesting
+    protected int checkUidPermission(String permission, int uid) {
         try {
             return AppGlobals.getPackageManager().checkUidPermission(permission, uid);
         } catch (RemoteException e) {
@@ -210,6 +225,12 @@
         }
     }
 
+    @VisibleForTesting
+    protected int checkComponentPermission(String permission, int uid, int owningUid,
+            boolean exported) {
+        return ActivityManager.checkComponentPermission(permission, uid, owningUid, exported);
+    }
+
     /**
      * Grant uri permissions to the specified app.
      *
@@ -916,7 +937,7 @@
             ProviderInfo pi, GrantUri grantUri, int uid, final int modeFlags) {
         if (DEBUG) Slog.v(TAG, "checkHoldingPermissions: uri=" + grantUri + " uid=" + uid);
         if (UserHandle.getUserId(uid) != grantUri.sourceUserId) {
-            if (ActivityManager.checkComponentPermission(INTERACT_ACROSS_USERS, uid, -1, true)
+            if (checkComponentPermission(INTERACT_ACROSS_USERS, uid, -1, true)
                     != PERMISSION_GRANTED) {
                 return false;
             }
@@ -1340,7 +1361,7 @@
         if (uid == Process.SYSTEM_UID || uid == Process.ROOT_UID) {
             return true;
         }
-        return ActivityManager.checkComponentPermission(
+        return checkComponentPermission(
                     android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
                     uid, /* owningUid = */-1, /* exported = */ true)
                     == PackageManager.PERMISSION_GRANTED;
diff --git a/services/core/java/com/android/server/utils/AnrTimer.java b/services/core/java/com/android/server/utils/AnrTimer.java
index 2b6dffb..7b5192c 100644
--- a/services/core/java/com/android/server/utils/AnrTimer.java
+++ b/services/core/java/com/android/server/utils/AnrTimer.java
@@ -16,37 +16,22 @@
 
 package com.android.server.utils;
 
-import static android.text.TextUtils.formatSimple;
-
-import android.annotation.IntDef;
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.os.Handler;
-import android.os.Looper;
 import android.os.Message;
-import android.os.Process;
 import android.os.SystemClock;
 import android.os.Trace;
-import android.text.TextUtils;
 import android.text.format.TimeMigrationUtils;
-import android.util.ArrayMap;
 import android.util.IndentingPrintWriter;
 import android.util.Log;
-import android.util.MathUtils;
-import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.Keep;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.os.ProcessCpuTracker;
 import com.android.internal.util.RingBuffer;
 
 import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Objects;
-import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * This class managers AnrTimers.  An AnrTimer is a substitute for a delayed Message.  In legacy
@@ -102,12 +87,6 @@
     private static final long TRACE_TAG = Trace.TRACE_TAG_ACTIVITY_MANAGER;
 
     /**
-     * Enable tracing from the time a timer expires until it is accepted or discarded.  This is
-     * used to diagnose long latencies in the client.
-     */
-    private static final boolean ENABLE_TRACING = false;
-
-    /**
      * Return true if the feature is enabled.  By default, the value is take from the Flags class
      * but it can be changed for local testing.
      */
@@ -116,22 +95,13 @@
     }
 
     /**
-     * The status of an ANR timer.  TIMER_INVALID status is returned when an error is detected.
+     * This class allows test code to provide instance-specific overrides.
      */
-    private static final int TIMER_INVALID = 0;
-    private static final int TIMER_RUNNING = 1;
-    private static final int TIMER_EXPIRED = 2;
-
-    @IntDef(prefix = { "TIMER_" }, value = {
-                TIMER_INVALID, TIMER_RUNNING, TIMER_EXPIRED
-            })
-    private @interface TimerStatus {}
-
-    /**
-     * A static list of all known AnrTimer instances, used for dumping and testing.
-     */
-    @GuardedBy("sAnrTimerList")
-    private static final ArrayList<WeakReference<AnrTimer>> sAnrTimerList = new ArrayList<>();
+    static class Injector {
+        boolean anrTimerServiceEnabled() {
+            return AnrTimer.anrTimerServiceEnabled();
+        }
+    }
 
     /**
      * An error is defined by its issue, the operation that detected the error, the tag of the
@@ -161,6 +131,22 @@
             this.arg = arg;
             this.timestamp = SystemClock.elapsedRealtime();
         }
+
+        /**
+         * Dump a single error to the output stream.
+         */
+        private void dump(IndentingPrintWriter ipw, int seq) {
+            ipw.format("%2d: op:%s tag:%s issue:%s arg:%s\n", seq, operation, tag, issue, arg);
+
+            final long offset = System.currentTimeMillis() - SystemClock.elapsedRealtime();
+            final long etime = offset + timestamp;
+            ipw.println("    date:" + TimeMigrationUtils.formatMillisWithFixedFormat(etime));
+            ipw.increaseIndent();
+            for (int i = 0; i < stack.length; i++) {
+                ipw.println("    " + stack[i].toString());
+            }
+            ipw.decreaseIndent();
+        }
     }
 
     /**
@@ -171,132 +157,10 @@
     @GuardedBy("sErrors")
     private static final RingBuffer<Error> sErrors = new RingBuffer<>(Error.class, 20);
 
-    /**
-     * A record of a single anr timer.  The pid and uid are retained for reference but they do not
-     * participate in the equality tests. A {@link Timer} is bound to its parent {@link AnrTimer}
-     * through the owner field.  Access to timer fields is guarded by the mLock of the owner.
-     */
-    private static class Timer {
-        /** The AnrTimer that is managing this Timer. */
-        final AnrTimer owner;
-
-        /** The argument that uniquely identifies the Timer in the context of its current owner. */
-        final Object arg;
-        /** The pid of the process being tracked by this Timer. */
-        final int pid;
-        /** The uid of the process being tracked by this Timer as reported by the kernel. */
-        final int uid;
-        /** The original timeout. */
-        final long timeoutMs;
-
-        /** The status of the Timer.  */
-        @GuardedBy("owner.mLock")
-        @TimerStatus
-        int status;
-
-        /** The absolute time the timer was startd */
-        final long startedMs;
-
-        /** Fields used by the native timer service. */
-
-        /** The timer ID: used to exchange information with the native service. */
-        int timerId;
-
-        /** Fields used by the legacy timer service. */
-
-        /**
-         * The process's cpu delay time when the timer starts . It is meaningful only if
-         * extendable is true.  The cpu delay is cumulative, so the incremental delay that occurs
-         * during a timer is the delay at the end of the timer minus this value.  Units are in
-         * milliseconds.
-         */
-        @GuardedBy("owner.mLock")
-        long initialCpuDelayMs;
-
-        /** True if the timer has been extended. */
-        @GuardedBy("owner.mLock")
-        boolean extended;
-
-        /**
-         * Fetch a new Timer.  This is private.  Clients should get a new timer using the obtain()
-         * method.
-         */
-        private Timer(int pid, int uid, @Nullable Object arg, long timeoutMs,
-                @NonNull AnrTimer service) {
-            this.arg = arg;
-            this.pid = pid;
-            this.uid = uid;
-            this.timerId = 0;
-            this.timeoutMs = timeoutMs;
-            this.startedMs = now();
-            this.owner = service;
-            this.initialCpuDelayMs = 0;
-            this.extended = false;
-            this.status = TIMER_INVALID;
-        }
-
-        /** Get a timer.  This implementation constructs a new timer. */
-        static Timer obtain(int pid, int uid, @Nullable Object arg, long timeout,
-                @NonNull AnrTimer service) {
-            return new Timer(pid, uid, arg, timeout, service);
-        }
-
-        /** Release a timer. This implementation simply drops the timer. */
-        void release() {
-        }
-
-        /** Return the age of the timer. This is used for debugging. */
-        long age() {
-            return now() - startedMs;
-        }
-
-        /**
-         * The hash code is generated from the owner and the argument.  By definition, the
-         * combination must be unique for the lifetime of an in-use Timer.
-         */
-        @Override
-        public int hashCode() {
-            return Objects.hash(owner, arg);
-        }
-
-        /**
-         * The equality check compares the owner and the argument.  By definition, the combination
-         * must be unique for the lifetime of an in-use Timer.
-         */
-        @Override
-        public boolean equals(Object r) {
-            if (r instanceof Timer) {
-                Timer t = (Timer) r;
-                return Objects.equals(owner, t.owner) && Objects.equals(arg, t.arg);
-            }
-            return false;
-        }
-
-        @Override
-        public String toString() {
-            final int myStatus;
-            synchronized (owner.mLock) {
-                myStatus = status;
-            }
-            return "timerId=" + timerId + " pid=" + pid + " uid=" + uid
-                    + " " + statusString(myStatus) + " " + owner.mLabel;
-        }
-    }
-
     /** A lock for the AnrTimer instance. */
     private final Object mLock = new Object();
 
     /**
-     * The map from client argument to the associated timer.
-     */
-    @GuardedBy("mLock")
-    private final ArrayMap<V, Timer> mTimerMap = new ArrayMap<>();
-
-    /** The highwater mark of started, but not closed, timers. */
-    @GuardedBy("mLock")
-    private int mMaxStarted = 0;
-
-    /**
      * The total number of timers started.
      */
     @GuardedBy("mLock")
@@ -309,176 +173,6 @@
     private int mTotalErrors = 0;
 
     /**
-     * The total number of timers that have expired.
-     */
-    @GuardedBy("mLock")
-    private int mTotalExpired = 0;
-
-    /**
-     * A TimerService that generates a timeout event <n> milliseconds in the future.  See the
-     * class documentation for an explanation of the operations.
-     */
-    private abstract class TimerService {
-        /** Start a timer.  The timeout must be initialized. */
-        abstract boolean start(@NonNull Timer timer);
-
-        abstract void cancel(@NonNull Timer timer);
-
-        abstract void accept(@NonNull Timer timer);
-
-        abstract void discard(@NonNull Timer timer);
-    }
-
-    /**
-     * A class to assist testing.  All methods are null by default but can be overridden as
-     * necessary for a test.
-     */
-    @VisibleForTesting
-    static class Injector {
-        private final Handler mReferenceHandler;
-
-        Injector(@NonNull Handler handler) {
-            mReferenceHandler = handler;
-        }
-
-        /**
-         * Return a handler for the given Callback, based on the reference handler. The handler
-         * might be mocked, in which case it does not have a valid Looper.  In this case, use the
-         * main Looper.
-         */
-        @NonNull
-        Handler newHandler(@NonNull Handler.Callback callback) {
-            Looper looper = mReferenceHandler.getLooper();
-            if (looper == null) looper = Looper.getMainLooper();
-            return new Handler(looper, callback);
-        }
-
-        /**
-         * Return a CpuTracker. The default behavior is to create a new CpuTracker but this changes
-         * for unit tests.
-         **/
-        @NonNull
-        CpuTracker newTracker() {
-            return new CpuTracker();
-        }
-
-        /** Return true if the feature is enabled. */
-        boolean isFeatureEnabled() {
-            return anrTimerServiceEnabled();
-        }
-    }
-
-    /**
-     * A helper class to measure CPU delays.  Given a process ID, this class will return the
-     * cumulative CPU delay for the PID, since process inception.  This class is defined to assist
-     * testing.
-     */
-    @VisibleForTesting
-    static class CpuTracker {
-        /**
-         * The parameter to ProcessCpuTracker indicates that statistics should be collected on a
-         * single process and not on the collection of threads associated with that process.
-         */
-        private final ProcessCpuTracker mCpu = new ProcessCpuTracker(false);
-
-        /** A simple wrapper to fetch the delay.  This method can be overridden for testing. */
-        long delay(int pid) {
-            return mCpu.getCpuDelayTimeForPid(pid);
-        }
-    }
-
-    /**
-     * The "user-space" implementation of the timer service.  This service uses its own message
-     * handler to create timeouts.
-     */
-    private class HandlerTimerService extends TimerService {
-        /** The lock for this handler */
-        private final Object mLock = new Object();
-
-        /** The message handler for scheduling future events. */
-        private final Handler mHandler;
-
-        /** The interface to fetch process statistics that might extend an ANR timeout. */
-        private final CpuTracker mCpu;
-
-        /** Create a HandlerTimerService that directly uses the supplied handler and tracker. */
-        @VisibleForTesting
-        HandlerTimerService(@NonNull Injector injector) {
-            mHandler = injector.newHandler(this::expires);
-            mCpu = injector.newTracker();
-        }
-
-        /** Post a message with the specified timeout.  The timer is not modified. */
-        private void post(@NonNull Timer t, long timeoutMillis) {
-            final Message msg = mHandler.obtainMessage();
-            msg.obj = t;
-            mHandler.sendMessageDelayed(msg, timeoutMillis);
-        }
-
-        /**
-         * The local expiration handler first attempts to compute a timer extension.  If the timer
-         * should be extended, it is rescheduled in the future (granting more time to the
-         * associated process).  If the timer should not be extended then the timeout is delivered
-         * to the client.
-         *
-         * A process is extended to account for the time the process was swapped out and was not
-         * runnable through no fault of its own.  A timer can only be extended once and only if
-         * the AnrTimer permits extensions.  Finally, a timer will never be extended by more than
-         * the original timeout, so the total timeout will never be more than twice the originally
-         * configured timeout.
-         */
-        private boolean expires(Message msg) {
-            Timer t = (Timer) msg.obj;
-            synchronized (mLock) {
-                long extension = 0;
-                if (mExtend && !t.extended) {
-                    extension = mCpu.delay(t.pid) - t.initialCpuDelayMs;
-                    if (extension < 0) extension = 0;
-                    if (extension > t.timeoutMs) extension = t.timeoutMs;
-                    t.extended = true;
-                }
-                if (extension > 0) {
-                    post(t, extension);
-                } else {
-                    onExpiredLocked(t);
-                }
-            }
-            return true;
-        }
-
-        @GuardedBy("mLock")
-        @Override
-        boolean start(@NonNull Timer t) {
-            if (mExtend) {
-                t.initialCpuDelayMs = mCpu.delay(t.pid);
-            }
-            post(t, t.timeoutMs);
-            return true;
-        }
-
-        @Override
-        void cancel(@NonNull Timer t) {
-            mHandler.removeMessages(0, t);
-        }
-
-        @Override
-        void accept(@NonNull Timer t) {
-            // Nothing to do.
-        }
-
-        @Override
-        void discard(@NonNull Timer t) {
-            // Nothing to do.
-        }
-
-        /** The string identifies this subclass of AnrTimerService as being based on handlers. */
-        @Override
-        public String toString() {
-            return "handler";
-        }
-    }
-
-    /**
      * The handler for messages sent from this instance.
      */
     private final Handler mHandler;
@@ -499,18 +193,6 @@
     private final boolean mExtend;
 
     /**
-     * The timer service to use for this AnrTimer.
-     */
-    private final TimerService mTimerService;
-
-    /**
-     * Whether or not canceling a non-existent timer is an error.  Clients often cancel freely
-     * preemptively, without knowing if the timer was ever started.  Keeping this variable true
-     * means that such behavior is not an error.
-     */
-    private final boolean mLenientCancel = true;
-
-    /**
      * The top-level switch for the feature enabled or disabled.
      */
     private final FeatureSwitch mFeature;
@@ -528,40 +210,34 @@
      * AnrTimer may extend the individual timer rather than immediately delivering the timeout to
      * the client.  The extension policy is not part of the instance.
      *
-     * This method accepts an {@link #Injector} to tune behavior for testing.  This method should
-     * not be called directly by regular clients.
-     *
      * @param handler The handler to which the expiration message will be delivered.
      * @param what The "what" parameter for the expiration message.
      * @param label A name for this instance.
      * @param extend A flag to indicate if expired timers can be granted extensions.
-     * @param injector An {@link #Injector} to tune behavior for testing.
+     * @param injector An injector to provide overrides for testing.
      */
     @VisibleForTesting
     AnrTimer(@NonNull Handler handler, int what, @NonNull String label, boolean extend,
-            @NonNull Injector injector) {
+             @NonNull Injector injector) {
         mHandler = handler;
         mWhat = what;
         mLabel = label;
         mExtend = extend;
-        boolean enabled = injector.isFeatureEnabled();
-        if (!enabled) {
-            mFeature = new FeatureDisabled();
-            mTimerService = null;
-        } else {
-            mFeature = new FeatureEnabled();
-            mTimerService = new HandlerTimerService(injector);
-
-            synchronized (sAnrTimerList) {
-                sAnrTimerList.add(new WeakReference(this));
-            }
-        }
-        Log.i(TAG, formatSimple("created %s label: \"%s\"", mTimerService, label));
+        mFeature = new FeatureDisabled();
     }
 
     /**
-     * Create an AnrTimer instance with the default {@link #Injector}.  See {@link AnrTimer(Handler,
-     * int, String, boolean, Injector} for a functional description.
+     * Create one AnrTimer instance.  The instance is given a handler and a "what".  Individual
+     * timers are started with {@link #start}.  If a timer expires, then a {@link Message} is sent
+     * immediately to the handler with {@link Message.what} set to what and {@link Message.obj} set
+     * to the timer key.
+     *
+     * AnrTimer instances have a label, which must be unique.  The label is used for reporting and
+     * debug.
+     *
+     * If an individual timer expires internally, and the "extend" parameter is true, then the
+     * AnrTimer may extend the individual timer rather than immediately delivering the timeout to
+     * the client.  The extension policy is not part of the instance.
      *
      * @param handler The handler to which the expiration message will be delivered.
      * @param what The "what" parameter for the expiration message.
@@ -569,7 +245,7 @@
      * @param extend A flag to indicate if expired timers can be granted extensions.
      */
     public AnrTimer(@NonNull Handler handler, int what, @NonNull String label, boolean extend) {
-        this(handler, what, label, extend, new Injector(handler));
+        this(handler, what, label, extend, new Injector());
     }
 
     /**
@@ -596,105 +272,17 @@
     }
 
     /**
-     * Start a trace on the timer.  The trace is laid down in the AnrTimerTrack.
-     */
-    private void traceBegin(Timer t, String what) {
-        if (ENABLE_TRACING) {
-            final String label = formatSimple("%s(%d,%d,%s)", what, t.pid, t.uid, mLabel);
-            final int cookie = t.hashCode();
-            Trace.asyncTraceForTrackBegin(TRACE_TAG, TRACK, label, cookie);
-        }
-    }
-
-    /**
-     * End a trace on the timer.
-     */
-    private void traceEnd(Timer t) {
-        if (ENABLE_TRACING) {
-            final int cookie = t.hashCode();
-            Trace.asyncTraceForTrackEnd(TRACE_TAG, TRACK, cookie);
-        }
-    }
-
-    /**
-     * Return the string representation for a timer status.
-     */
-    private static String statusString(int s) {
-        switch (s) {
-            case TIMER_INVALID: return "invalid";
-            case TIMER_RUNNING: return "running";
-            case TIMER_EXPIRED: return "expired";
-        }
-        return formatSimple("unknown: %d", s);
-    }
-
-    /**
-     * Delete the timer associated with arg from the maps and return it.  Return null if the timer
-     * was not found.
-     */
-    @GuardedBy("mLock")
-    private Timer removeLocked(V arg) {
-        Timer timer = mTimerMap.remove(arg);
-        return timer;
-    }
-
-    /**
-     * Return the number of timers currently running.
-     */
-    @VisibleForTesting
-    static int sizeOfTimerList() {
-        synchronized (sAnrTimerList) {
-            int totalTimers = 0;
-            for (int i = 0; i < sAnrTimerList.size(); i++) {
-                AnrTimer client = sAnrTimerList.get(i).get();
-                if (client != null) totalTimers += client.mTimerMap.size();
-            }
-            return totalTimers;
-        }
-    }
-
-    /**
-     * Clear out all existing timers.  This will lead to unexpected behavior if used carelessly.
-     * It is available only for testing.  It returns the number of times that were actually
-     * erased.
-     */
-    @VisibleForTesting
-    static int resetTimerListForHermeticTest() {
-        synchronized (sAnrTimerList) {
-            int mapLen = 0;
-            for (int i = 0; i < sAnrTimerList.size(); i++) {
-                AnrTimer client = sAnrTimerList.get(i).get();
-                if (client != null) {
-                    mapLen += client.mTimerMap.size();
-                    client.mTimerMap.clear();
-                }
-            }
-            if (mapLen > 0) {
-                Log.w(TAG, formatSimple("erasing timer list: clearing %d timers", mapLen));
-            }
-            return mapLen;
-        }
-    }
-
-    /**
-     * Generate a log message for a timer.
-     */
-    private void report(@NonNull Timer timer, @NonNull String msg) {
-        Log.i(TAG, msg + " " + timer + " " + Objects.toString(timer.arg));
-    }
-
-    /**
      * The FeatureSwitch class provides a quick switch between feature-enabled behavior and
      * feature-disabled behavior.
      */
     private abstract class FeatureSwitch {
-        abstract boolean start(@NonNull V arg, int pid, int uid, long timeoutMs);
+        abstract void start(@NonNull V arg, int pid, int uid, long timeoutMs);
 
-        abstract boolean cancel(@NonNull V arg);
+        abstract void cancel(@NonNull V arg);
 
-        abstract boolean accept(@NonNull V arg);
+        abstract void accept(@NonNull V arg);
 
-        abstract boolean discard(@NonNull V arg);
+        abstract void discard(@NonNull V arg);
 
         abstract boolean enabled();
     }
@@ -706,29 +294,25 @@
     private class FeatureDisabled extends FeatureSwitch {
         /** Start a timer by sending a message to the client's handler. */
         @Override
-        boolean start(@NonNull V arg, int pid, int uid, long timeoutMs) {
+        void start(@NonNull V arg, int pid, int uid, long timeoutMs) {
             final Message msg = mHandler.obtainMessage(mWhat, arg);
             mHandler.sendMessageDelayed(msg, timeoutMs);
-            return true;
         }
 
         /** Cancel a timer by removing the message from the client's handler. */
         @Override
-        boolean cancel(@NonNull V arg) {
+        void cancel(@NonNull V arg) {
             mHandler.removeMessages(mWhat, arg);
-            return true;
         }
 
         /** accept() is a no-op when the feature is disabled. */
         @Override
-        boolean accept(@NonNull V arg) {
-            return true;
+        void accept(@NonNull V arg) {
         }
 
         /** discard() is a no-op when the feature is disabled. */
         @Override
-        boolean discard(@NonNull V arg) {
-            return true;
+        void discard(@NonNull V arg) {
         }
 
         /** The feature is not enabled. */
@@ -739,113 +323,6 @@
     }
 
     /**
-     * The FeatureEnabled class enables the AnrTimer logic.  It is used when the AnrTimer service
-     * is enabled via Flags.anrTimerServiceEnabled.
-     */
-    private class FeatureEnabled extends FeatureSwitch {
-
-        /**
-         * Start a timer.
-         */
-        @Override
-        boolean start(@NonNull V arg, int pid, int uid, long timeoutMs) {
-            final Timer timer = Timer.obtain(pid, uid, arg, timeoutMs, AnrTimer.this);
-            synchronized (mLock) {
-                Timer old = mTimerMap.get(arg);
-                // There is an existing timer.  If the timer was running, then cancel the running
-                // timer and restart it.  If the timer was expired record a protocol error and
-                // discard the expired timer.
-                if (old != null) {
-                    if (old.status == TIMER_EXPIRED) {
-                      restartedLocked(old.status, arg);
-                        discard(arg);
-                    } else {
-                        cancel(arg);
-                    }
-                }
-                if (mTimerService.start(timer)) {
-                    timer.status = TIMER_RUNNING;
-                    mTimerMap.put(arg, timer);
-                    mTotalStarted++;
-                    mMaxStarted = Math.max(mMaxStarted, mTimerMap.size());
-                    if (DEBUG) report(timer, "start");
-                    return true;
-                } else {
-                    Log.e(TAG, "AnrTimer.start failed");
-                    return false;
-                }
-            }
-        }
-
-        /**
-         * Cancel a timer.  Return false if the timer was not found.
-         */
-        @Override
-        boolean cancel(@NonNull V arg) {
-            synchronized (mLock) {
-                Timer timer = removeLocked(arg);
-                if (timer == null) {
-                    if (!mLenientCancel) notFoundLocked("cancel", arg);
-                    return false;
-                }
-                mTimerService.cancel(timer);
-                // There may be an expiration message in flight.  Cancel it.
-                mHandler.removeMessages(mWhat, arg);
-                if (DEBUG) report(timer, "cancel");
-                timer.release();
-                return true;
-            }
-        }
-
-        /**
-         * Accept a timer in the framework-level handler.  The timeout has been accepted and the
-         * timeout handler is executing.  Return false if the timer was not found.
-         */
-        @Override
-        boolean accept(@NonNull V arg) {
-            synchronized (mLock) {
-                Timer timer = removeLocked(arg);
-                if (timer == null) {
-                    notFoundLocked("accept", arg);
-                    return false;
-                }
-                mTimerService.accept(timer);
-                traceEnd(timer);
-                if (DEBUG) report(timer, "accept");
-                timer.release();
-                return true;
-            }
-        }
-
-        /**
-         * Discard a timer in the framework-level handler.  For whatever reason, the timer is no
-         * longer interesting.  No statistics are collected.  Return false if the time was not
-         * found.
-         */
-        @Override
-        boolean discard(@NonNull V arg) {
-            synchronized (mLock) {
-                Timer timer = removeLocked(arg);
-                if (timer == null) {
-                    notFoundLocked("discard", arg);
-                    return false;
-                }
-                mTimerService.discard(timer);
-                traceEnd(timer);
-                if (DEBUG) report(timer, "discard");
-                timer.release();
-                return true;
-            }
-        }
-
-        /** The feature is enabled. */
-        @Override
-        boolean enabled() {
-            return true;
-        }
-    }
-
-    /**
      * Start a timer associated with arg.  The same object must be used to cancel, accept, or
      * discard a timer later.  If a timer already exists with the same arg, then the existing timer
      * is canceled and a new timer is created.
@@ -854,32 +331,27 @@
      * @param pid The Linux process ID of the target being timed.
      * @param uid The Linux user ID of the target being timed.
      * @param timeoutMs The timer timeout, in milliseconds.
-     * @return true if the timer was successfully created.
      */
-    public boolean start(@NonNull V arg, int pid, int uid, long timeoutMs) {
-        return mFeature.start(arg, pid, uid, timeoutMs);
+    public void start(@NonNull V arg, int pid, int uid, long timeoutMs) {
+        mFeature.start(arg, pid, uid, timeoutMs);
     }
 
     /**
      * Cancel the running timer associated with arg.  The timer is forgotten.  If the timer has
      * expired, the call is treated as a discard.  No errors are reported if the timer does not
      * exist or if the timer has expired.
-     *
-     * @return true if the timer was found and was running.
      */
-    public boolean cancel(@NonNull V arg) {
-        return mFeature.cancel(arg);
+    public void cancel(@NonNull V arg) {
+        mFeature.cancel(arg);
     }
 
     /**
      * Accept the expired timer associated with arg.  This indicates that the caller considers the
      * timer expiration to be a true ANR.  (See {@link #discard} for an alternate response.)  It is
      * an error to accept a running timer, however the running timer will be canceled.
-     *
-     * @return true if the timer was found and was expired.
      */
-    public boolean accept(@NonNull V arg) {
-        return mFeature.accept(arg);
+    public void accept(@NonNull V arg) {
+        mFeature.accept(arg);
     }
 
     /**
@@ -889,24 +361,9 @@
      * such a process could be stopped at a breakpoint and its failure to respond would not be an
      * error.  It is an error to discard a running timer, however the running timer will be
      * canceled.
-     *
-     * @return true if the timer was found and was expired.
      */
-    public boolean discard(@NonNull V arg) {
-        return mFeature.discard(arg);
-    }
-
-    /**
-     * The notifier that a timer has fired.  The timer is not modified.
-     */
-    @GuardedBy("mLock")
-    private void onExpiredLocked(@NonNull Timer timer) {
-        if (DEBUG) report(timer, "expire");
-        traceBegin(timer, "expired");
-        mHandler.sendMessage(Message.obtain(mHandler, mWhat, timer.arg));
-        synchronized (mLock) {
-            mTotalExpired++;
-        }
+    public void discard(@NonNull V arg) {
+        mFeature.discard(arg);
     }
 
     /**
@@ -916,9 +373,7 @@
         synchronized (mLock) {
             pw.format("timer: %s\n", mLabel);
             pw.increaseIndent();
-            pw.format("started=%d maxStarted=%d running=%d expired=%d error=%d\n",
-                    mTotalStarted, mMaxStarted, mTimerMap.size(),
-                    mTotalExpired, mTotalErrors);
+            pw.format("started=%d errors=%d\n", mTotalStarted, mTotalErrors);
             pw.decreaseIndent();
         }
     }
@@ -931,10 +386,20 @@
     }
 
     /**
-     * The current time in milliseconds.
+     * Dump all errors to the output stream.
      */
-    private static long now() {
-        return SystemClock.uptimeMillis();
+    private static void dumpErrors(IndentingPrintWriter ipw) {
+        Error errors[];
+        synchronized (sErrors) {
+            if (sErrors.size() == 0) return;
+            errors = sErrors.toArray();
+        }
+        ipw.println("Errors");
+        ipw.increaseIndent();
+        for (int i = 0; i < errors.length; i++) {
+            if (errors[i] != null) errors[i].dump(ipw, i);
+        }
+        ipw.decreaseIndent();
     }
 
     /**
@@ -966,60 +431,12 @@
     }
 
     /**
-     * Log an error about a timer that is started when there is an existing timer.
-     */
-    @GuardedBy("mLock")
-    private void restartedLocked(@TimerStatus int status, Object arg) {
-        recordErrorLocked("start", status == TIMER_EXPIRED ? "autoDiscard" : "autoCancel", arg);
-    }
-
-    /**
-     * Dump a single error to the output stream.
-     */
-    private static void dump(IndentingPrintWriter ipw, int seq, Error err) {
-        ipw.format("%2d: op:%s tag:%s issue:%s arg:%s\n", seq, err.operation, err.tag,
-                err.issue, err.arg);
-
-        final long offset = System.currentTimeMillis() - SystemClock.elapsedRealtime();
-        final long etime = offset + err.timestamp;
-        ipw.println("    date:" + TimeMigrationUtils.formatMillisWithFixedFormat(etime));
-        ipw.increaseIndent();
-        for (int i = 0; i < err.stack.length; i++) {
-            ipw.println("    " + err.stack[i].toString());
-        }
-        ipw.decreaseIndent();
-    }
-
-    /**
-     * Dump all errors to the output stream.
-     */
-    private static void dumpErrors(IndentingPrintWriter ipw) {
-        Error errors[];
-        synchronized (sErrors) {
-            if (sErrors.size() == 0) return;
-            errors = sErrors.toArray();
-        }
-        ipw.println("Errors");
-        ipw.increaseIndent();
-        for (int i = 0; i < errors.length; i++) {
-            if (errors[i] != null) dump(ipw, i, errors[i]);
-        }
-        ipw.decreaseIndent();
-    }
-
-    /**
      * Dumpsys output.
      */
     public static void dump(@NonNull PrintWriter pw, boolean verbose) {
         final IndentingPrintWriter ipw = new IndentingPrintWriter(pw);
         ipw.println("AnrTimer statistics");
         ipw.increaseIndent();
-        synchronized (sAnrTimerList) {
-            for (int i = 0; i < sAnrTimerList.size(); i++) {
-                AnrTimer client = sAnrTimerList.get(i).get();
-                if (client != null) client.dump(ipw);
-            }
-        }
         if (verbose) dumpErrors(ipw);
         ipw.format("AnrTimerEnd\n");
         ipw.decreaseIndent();
diff --git a/services/core/java/com/android/server/utils/OWNERS b/services/core/java/com/android/server/utils/OWNERS
index be91611d..fbc0b56 100644
--- a/services/core/java/com/android/server/utils/OWNERS
+++ b/services/core/java/com/android/server/utils/OWNERS
@@ -10,3 +10,8 @@
 per-file Watcher.java = shombert@google.com
 per-file EventLogger.java = file:/platform/frameworks/av:/media/janitors/media_solutions_OWNERS
 per-file EventLogger.java = jmtrivi@google.com
+
+# Bug component : 158088 = per-file AnrTimer*.java
+per-file AnrTimer*.java = file:/PERFORMANCE_OWNERS
+
+per-file flags.aconfig = file:/PERFORMANCE_OWNERS
diff --git a/services/core/java/com/android/server/utils/WatchedSparseSetArray.java b/services/core/java/com/android/server/utils/WatchedSparseSetArray.java
index 0386e66..b8850af 100644
--- a/services/core/java/com/android/server/utils/WatchedSparseSetArray.java
+++ b/services/core/java/com/android/server/utils/WatchedSparseSetArray.java
@@ -142,6 +142,20 @@
         return (T) mStorage.valueAt(intIndex, valueIndex);
     }
 
+    /**
+     * Copy from another SparseSetArray.
+     */
+    public void copyFrom(@NonNull SparseSetArray<T> c) {
+        clear();
+        final int end = c.size();
+        for (int i = 0; i < end; i++) {
+            final int key = c.keyAt(i);
+            final ArraySet<T> set = c.get(key);
+            mStorage.addAll(key, set);
+        }
+        onChanged();
+    }
+
     @NonNull
     @Override
     public Object snapshot() {
diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
index d5044d9..fc824ab 100644
--- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
@@ -53,7 +53,6 @@
 import android.os.VibrationAttributes;
 import android.os.VibrationEffect;
 import android.os.VibratorInfo;
-import android.os.vibrator.Flags;
 import android.os.vibrator.PrebakedSegment;
 import android.os.vibrator.VibrationEffectSegment;
 import android.os.vibrator.VibratorInfoFactory;
@@ -88,7 +87,6 @@
 import java.util.function.Consumer;
 import java.util.function.Function;
 
-
 /** System implementation of {@link IVibratorManagerService}. */
 public class VibratorManagerService extends IVibratorManagerService.Stub {
     private static final String TAG = "VibratorManagerService";
@@ -273,10 +271,11 @@
         context.registerReceiver(mIntentReceiver, filter, Context.RECEIVER_NOT_EXPORTED);
 
         injector.addService(EXTERNAL_VIBRATOR_SERVICE, new ExternalVibratorService());
-        if (Flags.adaptiveHapticsEnabled()) {
+        if (ServiceManager.isDeclared(VIBRATOR_CONTROL_SERVICE)) {
             injector.addService(VIBRATOR_CONTROL_SERVICE,
                     new VibratorControlService(new VibratorControllerHolder(), mLock));
         }
+
     }
 
     /** Finish initialization at boot phase {@link SystemService#PHASE_SYSTEM_SERVICES_READY}. */
@@ -411,9 +410,13 @@
 
     @Override // Binder call
     public void performHapticFeedback(
-            int uid, int deviceId, String opPkg, int constant, boolean always, String reason,
-            IBinder token) {
-        performHapticFeedbackInternal(uid, deviceId, opPkg, constant, always, reason, token);
+            int uid, int deviceId, String opPkg, int constant, boolean always, String reason) {
+        // Note that the `performHapticFeedback` method does not take a token argument from the
+        // caller, and instead, uses this service as the token. This is to mitigate performance
+        // impact that would otherwise be caused due to marshal latency. Haptic feedback effects are
+        // short-lived, so we don't need to cancel when the process dies.
+        performHapticFeedbackInternal(
+                uid, deviceId, opPkg, constant, always, reason, /* token= */ this);
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index b1abe2a..1577cef 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -107,6 +107,7 @@
 import com.android.server.wm.WindowManagerInternal.AccessibilityControllerInternal;
 import com.android.server.wm.WindowManagerInternal.MagnificationCallbacks;
 import com.android.server.wm.WindowManagerInternal.WindowsForAccessibilityCallback;
+import com.android.window.flags.Flags;
 
 import java.io.File;
 import java.io.IOException;
@@ -758,6 +759,11 @@
                     if (!isMagnifierActivated) {
                         break;
                     }
+                    if (Flags.doNotCheckIntersectionWhenNonMagnifiableWindowTransitions()) {
+                        if (!windowState.shouldMagnify()) {
+                            break;
+                        }
+                    }
                     switch (type) {
                         case WindowManager.LayoutParams.TYPE_APPLICATION:
                         case WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION:
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index 315e7d8..4b55bec 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -18,17 +18,17 @@
 
 import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
 import static android.app.Activity.FULLSCREEN_MODE_REQUEST_ENTER;
+import static android.app.Activity.FULLSCREEN_MODE_REQUEST_EXIT;
 import static android.app.ActivityOptions.ANIM_SCENE_TRANSITION;
 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
 import static android.app.ActivityTaskManager.INVALID_WINDOWING_MODE;
 import static android.app.FullscreenRequestHandler.REMOTE_CALLBACK_RESULT_KEY;
 import static android.app.FullscreenRequestHandler.RESULT_APPROVED;
-import static android.app.FullscreenRequestHandler.RESULT_FAILED_NOT_DEFAULT_FREEFORM;
-import static android.app.FullscreenRequestHandler.RESULT_FAILED_NOT_IN_FREEFORM;
 import static android.app.FullscreenRequestHandler.RESULT_FAILED_NOT_IN_FULLSCREEN_WITH_HISTORY;
 import static android.app.FullscreenRequestHandler.RESULT_FAILED_NOT_TOP_FOCUSED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.os.Process.INVALID_UID;
 import static android.os.Process.SYSTEM_UID;
@@ -1092,19 +1092,14 @@
 
     private @FullscreenRequestHandler.RequestResult int validateMultiwindowFullscreenRequestLocked(
             Task topFocusedRootTask, int fullscreenRequest, ActivityRecord requesterActivity) {
-        // If the mode is not by default freeform, the freeform will be a user-driven event.
-        if (topFocusedRootTask.getParent().getWindowingMode() != WINDOWING_MODE_FREEFORM) {
-            return RESULT_FAILED_NOT_DEFAULT_FREEFORM;
+        if (requesterActivity.getWindowingMode() == WINDOWING_MODE_PINNED) {
+            return RESULT_APPROVED;
         }
         // If this is not coming from the currently top-most activity, reject the request.
         if (requesterActivity != topFocusedRootTask.getTopMostActivity()) {
             return RESULT_FAILED_NOT_TOP_FOCUSED;
         }
-        if (fullscreenRequest == FULLSCREEN_MODE_REQUEST_ENTER) {
-            if (topFocusedRootTask.getWindowingMode() != WINDOWING_MODE_FREEFORM) {
-                return RESULT_FAILED_NOT_IN_FREEFORM;
-            }
-        } else {
+        if (fullscreenRequest == FULLSCREEN_MODE_REQUEST_EXIT) {
             if (topFocusedRootTask.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
                 return RESULT_FAILED_NOT_IN_FULLSCREEN_WITH_HISTORY;
             }
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLaunchObserver.java b/services/core/java/com/android/server/wm/ActivityMetricsLaunchObserver.java
index 81e5fbd..769f01c 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLaunchObserver.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLaunchObserver.java
@@ -142,8 +142,11 @@
      *           if the launching activity is started from an existing launch sequence (trampoline)
      *           but cannot coalesce to the existing one, e.g. to a different display.
      * @param name The launching activity name.
+     * @param temperature The temperature at which a launch sequence had started.
+     * @param userId The id of the user the activity is being launched for.
      */
-    public void onActivityLaunched(long id, ComponentName name, @Temperature int temperature) {
+    public void onActivityLaunched(long id, ComponentName name, @Temperature int temperature,
+            int userId) {
     }
 
     /**
@@ -177,13 +180,15 @@
      * @param timestampNanos the timestamp of ActivityLaunchFinished event in nanoseconds.
      *        To compute the TotalTime duration, deduct the timestamp {@link #onIntentStarted}
      *        from {@code timestampNanos}.
+     * @param launchMode The activity launch mode.
      *
      * @apiNote The finishing activity isn't necessarily the same as the starting activity;
      *          in the case of a trampoline, multiple activities could've been started
      *          and only the latest activity that was top-most during first-frame drawn
      *          is reported here.
      */
-    public void onActivityLaunchFinished(long id, ComponentName name, long timestampNanos) {
+    public void onActivityLaunchFinished(long id, ComponentName name, long timestampNanos,
+            int launchMode) {
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index 7b20529..78f501a 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -1737,7 +1737,8 @@
 
         // Beginning a launch is timing sensitive and so should be observed as soon as possible.
         mLaunchObserver.onActivityLaunched(info.mLaunchingState.mStartUptimeNs,
-                info.mLastLaunchedActivity.mActivityComponent, temperature);
+                info.mLastLaunchedActivity.mActivityComponent, temperature,
+                info.mLastLaunchedActivity.mUserId);
 
         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
     }
@@ -1774,7 +1775,8 @@
                 "MetricsLogger:launchObserverNotifyActivityLaunchFinished");
 
         mLaunchObserver.onActivityLaunchFinished(info.mLaunchingState.mStartUptimeNs,
-                info.mLastLaunchedActivity.mActivityComponent, timestampNs);
+                info.mLastLaunchedActivity.mActivityComponent, timestampNs,
+                info.mLastLaunchedActivity.launchMode);
 
         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
     }
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 0d06f5b..2df965c 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -353,6 +353,7 @@
 import android.window.TaskSnapshot;
 import android.window.TransitionInfo.AnimationOptions;
 import android.window.WindowContainerToken;
+import android.window.WindowOnBackInvokedDispatcher;
 
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
@@ -562,7 +563,6 @@
     boolean mClientVisibilityDeferred;// was the visibility change message to client deferred?
     boolean idle;           // has the activity gone idle?
     boolean hasBeenLaunched;// has this activity ever been launched?
-    boolean frozenBeforeDestroy;// has been frozen but not yet destroyed.
     boolean immersive;      // immersive mode (don't interrupt if possible)
     boolean forceNewConfig; // force re-create with new config next time
     boolean supportsEnterPipOnTaskSwitch;  // This flag is set by the system to indicate that the
@@ -979,6 +979,8 @@
     int mAllowedTouchUid;
     // Whether client has requested a scene transition when exiting.
     final boolean mHasSceneTransition;
+    // Whether the app has opt-in enableOnBackInvokedCallback.
+    final boolean mOptInOnBackInvoked;
 
     // Whether the ActivityEmbedding is enabled on the app.
     private final boolean mAppActivityEmbeddingSplitsEnabled;
@@ -1201,8 +1203,6 @@
                 pw.print(" noDisplay="); pw.print(noDisplay);
                 pw.print(" immersive="); pw.print(immersive);
                 pw.print(" launchMode="); pw.println(launchMode);
-        pw.print(prefix); pw.print("frozenBeforeDestroy="); pw.print(frozenBeforeDestroy);
-                pw.print(" forceNewConfig="); pw.println(forceNewConfig);
         pw.print(prefix); pw.print("mActivityType=");
                 pw.println(activityTypeToString(getActivityType()));
         pw.print(prefix); pw.print("mImeInsetsFrozenUntilStartInput=");
@@ -2234,6 +2234,10 @@
             // No such property name.
         }
         mAppActivityEmbeddingSplitsEnabled = appActivityEmbeddingEnabled;
+
+        mOptInOnBackInvoked = WindowOnBackInvokedDispatcher
+                .isOnBackInvokedCallbackEnabled(info, info.applicationInfo,
+                        () -> ent != null ? ent.array : null, false);
     }
 
     /**
@@ -3848,7 +3852,7 @@
         // updated for restoring original orientation of the display.
         if (next == null) {
             mRootWindowContainer.ensureVisibilityAndConfig(next, getDisplayId(),
-                    false /* markFrozenIfConfigChanged */, true /* deferResume */);
+                    true /* deferResume */);
         }
         if (activityRemoved) {
             mRootWindowContainer.resumeFocusedTasksTopActivities();
@@ -4090,7 +4094,6 @@
         cleanUpSplashScreen();
 
         deferRelaunchUntilPaused = false;
-        frozenBeforeDestroy = false;
 
         if (setState) {
             setState(DESTROYED, "cleanUp");
@@ -6276,7 +6279,6 @@
     }
 
     void handleAlreadyVisible() {
-        stopFreezingScreenLocked(false);
         try {
             if (returningOptions != null) {
                 app.getThread().scheduleOnNewActivityOptions(token, returningOptions.toBundle());
@@ -6710,19 +6712,6 @@
         stopFreezingScreen(true, true);
     }
 
-    void stopFreezingScreenLocked(boolean force) {
-        if (force || frozenBeforeDestroy) {
-            frozenBeforeDestroy = false;
-            if (getParent() == null) {
-                return;
-            }
-            ProtoLog.v(WM_DEBUG_ORIENTATION,
-                        "Clear freezing of %s: visible=%b freezing=%b", token,
-                                isVisible(), isFreezingScreen());
-            stopFreezingScreen(true, force);
-        }
-    }
-
     void stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force) {
         if (!mFreezingScreen) {
             return;
@@ -9569,7 +9558,6 @@
         if (finishing) {
             ProtoLog.v(WM_DEBUG_CONFIGURATION, "Configuration doesn't matter "
                     + "in finishing %s", this);
-            stopFreezingScreenLocked(false);
             return true;
         }
 
@@ -9660,7 +9648,6 @@
         // pick that up next time it starts.
         if (!attachedToProcess()) {
             ProtoLog.v(WM_DEBUG_CONFIGURATION, "Configuration doesn't matter not running %s", this);
-            stopFreezingScreenLocked(false);
             forceNewConfig = false;
             return true;
         }
@@ -9723,9 +9710,6 @@
         }
         notifyDisplayCompatPolicyAboutConfigurationChange(
                 mLastReportedConfiguration.getMergedConfiguration(), mTmpConfig);
-
-        stopFreezingScreenLocked(false);
-
         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 e5794a1..630b9e1 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -84,7 +84,9 @@
 import static com.android.server.wm.TaskFragment.EMBEDDING_DISALLOWED_NEW_TASK;
 import static com.android.server.wm.TaskFragment.EMBEDDING_DISALLOWED_UNTRUSTED_HOST;
 import static com.android.server.wm.WindowContainer.POSITION_TOP;
+import static com.android.window.flags.Flags.balDontBringExistingBackgroundTaskStackToFg;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
@@ -140,6 +142,8 @@
 import com.android.server.wm.TaskFragment.EmbeddingCheckResult;
 
 import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.text.DateFormat;
 import java.util.Date;
 
@@ -230,7 +234,26 @@
     private boolean mIsTaskCleared;
     private boolean mMovedToFront;
     private boolean mNoAnimation;
-    private boolean mAvoidMoveToFront;
+
+    // TODO mAvoidMoveToFront before V is changed from a boolean to a int code mCanMoveToFrontCode
+    // for the purpose of attribution of new BAL V feature. This should be reverted back to the
+    // boolean flag post V.
+    @IntDef(prefix = {"MOVE_TO_FRONT_"}, value = {
+            MOVE_TO_FRONT_ALLOWED,
+            MOVE_TO_FRONT_AVOID_PI_ONLY_CREATOR_ALLOWS,
+            MOVE_TO_FRONT_AVOID_LEGACY,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface MoveToFrontCode {}
+
+    // Allows a task move to front.
+    private static final int MOVE_TO_FRONT_ALLOWED = 0;
+    // Avoid a task move to front because the Pending Intent that starts the activity only
+    // its creator has the BAL privilege, its sender does not.
+    private static final int MOVE_TO_FRONT_AVOID_PI_ONLY_CREATOR_ALLOWS = 1;
+    // Avoid a task move to front because of all other legacy reasons.
+    private static final int MOVE_TO_FRONT_AVOID_LEGACY = 2;
+    private @MoveToFrontCode int mCanMoveToFrontCode = MOVE_TO_FRONT_ALLOWED;
     private boolean mFrozeTaskList;
     private boolean mTransientLaunch;
     // The task which was above the targetTask before starting this activity. null if the targetTask
@@ -642,7 +665,7 @@
         mIsTaskCleared = starter.mIsTaskCleared;
         mMovedToFront = starter.mMovedToFront;
         mNoAnimation = starter.mNoAnimation;
-        mAvoidMoveToFront = starter.mAvoidMoveToFront;
+        mCanMoveToFrontCode = starter.mCanMoveToFrontCode;
         mFrozeTaskList = starter.mFrozeTaskList;
 
         mVoiceSession = starter.mVoiceSession;
@@ -1121,6 +1144,7 @@
                             callerApp,
                             request.originatingPendingIntent,
                             request.forcedBalByPiSender,
+                            resultRecord,
                             intent,
                             checkedOptions);
                 request.logMessage.append(" (").append(balVerdict).append(")");
@@ -1498,6 +1522,14 @@
         return result;
     }
 
+    private boolean avoidMoveToFront() {
+        return mCanMoveToFrontCode != MOVE_TO_FRONT_ALLOWED;
+    }
+
+    private boolean avoidMoveToFrontPIOnlyCreatorAllows() {
+        return mCanMoveToFrontCode == MOVE_TO_FRONT_AVOID_PI_ONLY_CREATOR_ALLOWS;
+    }
+
     /**
      * If the start result is success, ensure that the configuration of the started activity matches
      * the current display. Otherwise clean up unassociated containers to avoid leakage.
@@ -1548,11 +1580,10 @@
         final ActivityRecord currentTop = startedActivityRootTask.topRunningActivity();
         if (currentTop != null && currentTop.shouldUpdateConfigForDisplayChanged()) {
             mRootWindowContainer.ensureVisibilityAndConfig(
-                    currentTop, currentTop.getDisplayId(),
-                    true /* markFrozenIfConfigChanged */, false /* deferResume */);
+                    currentTop, currentTop.getDisplayId(), false /* deferResume */);
         }
 
-        if (!mAvoidMoveToFront && mDoResume && mRootWindowContainer
+        if (!avoidMoveToFront() && mDoResume && mRootWindowContainer
                 .hasVisibleWindowAboveButDoesNotOwnNotificationShade(started.launchedFromUid)) {
             // If the UID launching the activity has a visible window on top of the notification
             // shade and it's launching an activity that's going to be at the front, we should move
@@ -1689,10 +1720,18 @@
             }
             // When running transient transition, the transient launch target should keep on top.
             // So disallow the transient hide activity to move itself to front, e.g. trampoline.
-            if (!mAvoidMoveToFront && (mService.mHomeProcess == null
+            if (!avoidMoveToFront() && (mService.mHomeProcess == null
                     || mService.mHomeProcess.mUid != realCallingUid)
                     && r.mTransitionController.isTransientHide(targetTask)) {
-                mAvoidMoveToFront = true;
+                mCanMoveToFrontCode = MOVE_TO_FRONT_AVOID_LEGACY;
+            }
+            // If the activity is started by sending a pending intent and only its creator has the
+            // privilege to allow BAL (its sender does not), avoid move it to the front. Only do
+            // this when it is not a new task and not already been marked as avoid move to front.
+            // Guarded by a flag: balDontBringExistingBackgroundTaskStackToFg
+            if (balDontBringExistingBackgroundTaskStackToFg() && !avoidMoveToFront()
+                    && balVerdict.onlyCreatorAllows()) {
+                mCanMoveToFrontCode = MOVE_TO_FRONT_AVOID_PI_ONLY_CREATOR_ALLOWS;
             }
             mPriorAboveTask = TaskDisplayArea.getRootTaskAbove(targetTask.getRootTask());
         }
@@ -1746,15 +1785,19 @@
         // After activity is attached to task, but before actual start
         recordTransientLaunchIfNeeded(mLastStartActivityRecord);
 
-        if (!mAvoidMoveToFront && mDoResume) {
-            logOnlyCreatorAllowsBAL(balVerdict, realCallingUid, newTask);
-            mTargetRootTask.getRootTask().moveToFront("reuseOrNewTask", targetTask);
-            if (!mTargetRootTask.isTopRootTaskInDisplayArea() && mService.isDreaming()
-                    && !dreamStopping) {
-                // Launching underneath dream activity (fullscreen, always-on-top). Run the launch-
-                // -behind transition so the Activity gets created and starts in visible state.
-                mLaunchTaskBehind = true;
-                r.mLaunchTaskBehind = true;
+        if (mDoResume) {
+            if (!avoidMoveToFront()) {
+                mTargetRootTask.getRootTask().moveToFront("reuseOrNewTask", targetTask);
+                if (!mTargetRootTask.isTopRootTaskInDisplayArea() && mService.isDreaming()
+                        && !dreamStopping) {
+                    // Launching underneath dream activity (fullscreen, always-on-top). Run the
+                    // launch--behind transition so the Activity gets created and starts
+                    // in visible state.
+                    mLaunchTaskBehind = true;
+                    r.mLaunchTaskBehind = true;
+                }
+            } else {
+                logPIOnlyCreatorAllowsBAL();
             }
         }
 
@@ -1816,10 +1859,13 @@
                 // root-task to the will not update the focused root-task.  If starting the new
                 // activity now allows the task root-task to be focusable, then ensure that we
                 // now update the focused root-task accordingly.
-                if (!mAvoidMoveToFront && mTargetRootTask.isTopActivityFocusable()
+                if (mTargetRootTask.isTopActivityFocusable()
                         && !mRootWindowContainer.isTopDisplayFocusedRootTask(mTargetRootTask)) {
-                    logOnlyCreatorAllowsBAL(balVerdict, realCallingUid, newTask);
-                    mTargetRootTask.moveToFront("startActivityInner");
+                    if (!avoidMoveToFront()) {
+                        mTargetRootTask.moveToFront("startActivityInner");
+                    } else {
+                        logPIOnlyCreatorAllowsBAL();
+                    }
                 }
                 mRootWindowContainer.resumeFocusedTasksTopActivities(
                         mTargetRootTask, mStartActivity, mOptions, mTransientLaunch);
@@ -1847,25 +1893,24 @@
         return START_SUCCESS;
     }
 
-    private void logOnlyCreatorAllowsBAL(BalVerdict balVerdict,
-            int realCallingUid, boolean newTask) {
-        // TODO (b/296478675) eventually, we will prevent such case from happening
-        // and probably also log that a BAL is prevented by android V.
-        if (!newTask && balVerdict.onlyCreatorAllows()) {
-            String realCallingPackage =
-                    mService.mContext.getPackageManager().getNameForUid(realCallingUid);
-            if (realCallingPackage == null) {
-                realCallingPackage = "uid=" + realCallingUid;
-            }
-            Slog.wtf(TAG, "A background app is brought to the foreground due to a "
-                    + "PendingIntent. However, only the creator of the PendingIntent allows BAL, "
-                    + "while the sender does not allow BAL. realCallingPackage: "
-                    + realCallingPackage + "; callingPackage: " + mRequest.callingPackage
-                    + "; mTargetRootTask:" + mTargetRootTask + "; mIntent: " + mIntent
-                    + "; mTargetRootTask.getTopNonFinishingActivity: "
-                    + mTargetRootTask.getTopNonFinishingActivity()
-                    + "; mTargetRootTask.getRootActivity: " + mTargetRootTask.getRootActivity());
+    // TODO (b/316135632) Post V release, remove this log method.
+    private void logPIOnlyCreatorAllowsBAL() {
+        if (!avoidMoveToFrontPIOnlyCreatorAllows()) return;
+        String realCallingPackage =
+                mService.mContext.getPackageManager().getNameForUid(mRealCallingUid);
+        if (realCallingPackage == null) {
+            realCallingPackage = "uid=" + mRealCallingUid;
         }
+        Slog.wtf(TAG, "Without Android 15 BAL hardening this activity would be moved to the "
+                + "foreground. The activity is started by a PendingIntent. However, only the "
+                + "creator of the PendingIntent allows BAL while the sender does not allow BAL. "
+                + "realCallingPackage: " + realCallingPackage
+                + "; callingPackage: " + mRequest.callingPackage
+                + "; mTargetRootTask:" + mTargetRootTask
+                + "; mIntent: " + mIntent
+                + "; mTargetRootTask.getTopNonFinishingActivity: "
+                + mTargetRootTask.getTopNonFinishingActivity()
+                + "; mTargetRootTask.getRootActivity: " + mTargetRootTask.getRootActivity());
     }
 
     private void recordTransientLaunchIfNeeded(ActivityRecord r) {
@@ -2064,7 +2109,7 @@
         mRootWindowContainer.startPowerModeLaunchIfNeeded(false /* forceSend */,
                 targetTaskTop);
 
-        setTargetRootTaskIfNeeded(targetTaskTop, balVerdict);
+        setTargetRootTaskIfNeeded(targetTaskTop);
 
         // When there is a reused activity and the current result is a trampoline activity,
         // set the reused activity as the result.
@@ -2080,13 +2125,12 @@
             if (!mMovedToFront && mDoResume) {
                 ProtoLog.d(WM_DEBUG_TASKS, "Bring to front target: %s from %s", mTargetRootTask,
                         targetTaskTop);
-                logOnlyCreatorAllowsBAL(balVerdict, mRealCallingUid, false);
                 mTargetRootTask.moveToFront("intentActivityFound");
             }
+
             resumeTargetRootTaskIfNeeded();
             return START_RETURN_INTENT_TO_CALLER;
         }
-
         complyActivityFlags(targetTask,
                 reusedTask != null ? reusedTask.getTopNonFinishingActivity() : null, intentGrants);
 
@@ -2109,7 +2153,6 @@
             targetTaskTop.showStartingWindow(true /* taskSwitch */);
         } else if (mDoResume) {
             // Make sure the root task and its belonging display are moved to topmost.
-            logOnlyCreatorAllowsBAL(balVerdict, mRealCallingUid, false);
             mTargetRootTask.moveToFront("intentActivityFound");
         }
         // We didn't do anything...  but it was needed (a.k.a., client don't use that intent!)
@@ -2344,7 +2387,7 @@
         mIsTaskCleared = false;
         mMovedToFront = false;
         mNoAnimation = false;
-        mAvoidMoveToFront = false;
+        mCanMoveToFrontCode = MOVE_TO_FRONT_ALLOWED;
         mFrozeTaskList = false;
         mTransientLaunch = false;
         mPriorAboveTask = null;
@@ -2456,12 +2499,12 @@
                         // The caller specifies that we'd like to be avoided to be moved to the
                         // front, so be it!
                         mDoResume = false;
-                        mAvoidMoveToFront = true;
+                        mCanMoveToFrontCode = MOVE_TO_FRONT_AVOID_LEGACY;
                     }
                 }
             } else if (mOptions.getAvoidMoveToFront()) {
                 mDoResume = false;
-                mAvoidMoveToFront = true;
+                mCanMoveToFrontCode = MOVE_TO_FRONT_AVOID_LEGACY;
             }
             mTransientLaunch = mOptions.getTransientLaunch();
             final KeyguardController kc = mSupervisor.getKeyguardController();
@@ -2471,7 +2514,7 @@
             if (mTransientLaunch && mDisplayLockAndOccluded
                     && mService.getTransitionController().isShellTransitionsEnabled()) {
                 mDoResume = false;
-                mAvoidMoveToFront = true;
+                mCanMoveToFrontCode = MOVE_TO_FRONT_AVOID_LEGACY;
             }
             mTargetRootTask = Task.fromWindowContainerToken(mOptions.getLaunchRootTask());
 
@@ -2528,7 +2571,7 @@
         mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
 
         if (mBalCode == BAL_BLOCK && !mService.isBackgroundActivityStartsEnabled()) {
-            mAvoidMoveToFront = true;
+            mCanMoveToFrontCode = MOVE_TO_FRONT_AVOID_LEGACY;
             mDoResume = false;
         }
     }
@@ -2705,7 +2748,7 @@
      * @param intentActivity Existing matching activity.
      * @return {@link ActivityRecord} brought to front.
      */
-    private void setTargetRootTaskIfNeeded(ActivityRecord intentActivity, BalVerdict balVerdict) {
+    private void setTargetRootTaskIfNeeded(ActivityRecord intentActivity) {
         intentActivity.getTaskFragment().clearLastPausedActivity();
         Task intentTask = intentActivity.getTask();
         // The intent task might be reparented while in getOrCreateRootTask, caches the original
@@ -2742,7 +2785,7 @@
             differentTopTask = true;
         }
 
-        if (differentTopTask && !mAvoidMoveToFront) {
+        if (differentTopTask && !avoidMoveToFront()) {
             mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
             if (mSourceRecord == null || inTopNonFinishingTask(mSourceRecord)) {
                 // We really do want to push this one into the user's face, right now.
@@ -2772,7 +2815,6 @@
                     // task on top there.
                     // Defer resuming the top activity while moving task to top, since the
                     // current task-top activity may not be the activity that should be resumed.
-                    logOnlyCreatorAllowsBAL(balVerdict, mRealCallingUid, false);
                     mTargetRootTask.moveTaskToFront(intentTask, mNoAnimation, mOptions,
                             mStartActivity.appTimeTracker, DEFER_RESUME,
                             "bringingFoundTaskToFront");
@@ -2789,7 +2831,9 @@
                 mOptions = null;
             }
         }
-
+        if (differentTopTask) {
+            logPIOnlyCreatorAllowsBAL();
+        }
         // Update the target's launch cookie and pending remote animation to those specified in the
         // options if set.
         if (mStartActivity.mLaunchCookie != null) {
@@ -2840,7 +2884,7 @@
     }
 
     private void setNewTask(Task taskToAffiliate) {
-        final boolean toTop = !mLaunchTaskBehind && !mAvoidMoveToFront;
+        final boolean toTop = !mLaunchTaskBehind && !avoidMoveToFront();
         final Task task = mTargetRootTask.reuseOrCreateTask(
                 mStartActivity.info, mIntent, mVoiceSession,
                 mVoiceInteractor, toTop, mStartActivity, mSourceRecord, mOptions);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 91f45a7..869bcc0 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -103,6 +103,7 @@
 import static com.android.server.wm.ActivityInterceptorCallback.SYSTEM_LAST_ORDERED_ID;
 import static com.android.server.wm.ActivityRecord.State.PAUSING;
 import static com.android.server.wm.ActivityRecord.State.RESUMED;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ACTIVITY_STARTS;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ALL;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_ROOT_TASK;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH;
@@ -118,6 +119,7 @@
 import static com.android.server.wm.ActivityTaskSupervisor.ON_TOP;
 import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
 import static com.android.server.wm.ActivityTaskSupervisor.REMOVE_FROM_RECENTS;
+import static com.android.server.wm.BackgroundActivityStartController.BalVerdict;
 import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_DONT_LOCK;
 import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
 import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION;
@@ -1051,6 +1053,7 @@
             mWindowManager = wm;
             mRootWindowContainer = wm.mRoot;
             mWindowOrganizerController.mTransitionController.setWindowManager(wm);
+            mLifecycleManager.setWindowManager(wm);
             mTempConfig.setToDefaults();
             mTempConfig.setLocales(LocaleList.getDefault());
             mConfigurationSeq = mTempConfig.seq = 1;
@@ -1272,7 +1275,6 @@
             @Nullable String callingFeatureId, Intent intent, String resolvedType,
             IBinder resultTo, String resultWho, int requestCode, int startFlags,
             ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
-
         final SafeActivityOptions opts = SafeActivityOptions.fromBundle(bOptions);
 
         assertPackageMatchesCallingUid(callingPackage);
@@ -1313,7 +1315,6 @@
                 .setActivityOptions(opts)
                 .setUserId(userId)
                 .execute();
-
     }
 
     @Override
@@ -2242,7 +2243,7 @@
         }
         final BackgroundActivityStartController balController =
                 mTaskSupervisor.getBackgroundActivityLaunchController();
-        if (balController.shouldAbortBackgroundActivityStart(
+        final BalVerdict balVerdict = balController.checkBackgroundActivityStart(
                 callingUid,
                 callingPid,
                 callingPackage,
@@ -2252,10 +2253,14 @@
                 null,
                 BackgroundStartPrivileges.NONE,
                 null,
-                null)) {
-            if (!isBackgroundActivityStartsEnabled()) {
-                return;
-            }
+                null,
+                null);
+        if (balVerdict.blocks() && !isBackgroundActivityStartsEnabled()) {
+            Slog.w(TAG, "moveTaskToFront blocked: " + balVerdict);
+            return;
+        }
+        if (DEBUG_ACTIVITY_STARTS) {
+            Slog.d(TAG, "moveTaskToFront allowed: " + balVerdict);
         }
         try {
             final Task task = mRootWindowContainer.anyTaskForId(taskId);
@@ -4259,7 +4264,7 @@
 
     void dumpActivityContainersLocked(PrintWriter pw) {
         pw.println("ACTIVITY MANAGER CONTAINERS (dumpsys activity containers)");
-        mRootWindowContainer.dumpChildrenNames(pw, " ");
+        mRootWindowContainer.dumpChildrenNames(pw, "");
         pw.println(" ");
     }
 
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index 4a479aa..e59601c 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -843,7 +843,7 @@
                 // We don't want to perform a redundant launch of the same record while ensuring
                 // configurations and trying to resume top activity of focused root task.
                 mRootWindowContainer.ensureVisibilityAndConfig(r, r.getDisplayId(),
-                        false /* markFrozenIfConfigChanged */, true /* deferResume */);
+                        true /* deferResume */);
             }
 
             if (mKeyguardController.checkKeyguardVisibility(r) && r.allowMoveToFront()) {
diff --git a/services/core/java/com/android/server/wm/AppTaskImpl.java b/services/core/java/com/android/server/wm/AppTaskImpl.java
index 761b0a8..50de0b0 100644
--- a/services/core/java/com/android/server/wm/AppTaskImpl.java
+++ b/services/core/java/com/android/server/wm/AppTaskImpl.java
@@ -16,6 +16,8 @@
 
 package com.android.server.wm;
 
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ACTIVITY_STARTS;
+import static com.android.server.wm.BackgroundActivityStartController.BalVerdict;
 import static com.android.server.wm.ActivityTaskSupervisor.REMOVE_FROM_RECENTS;
 import static com.android.server.wm.RootWindowContainer.MATCH_ATTACHED_TASK_OR_RECENT_TASKS;
 
@@ -31,6 +33,7 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.util.Slog;
 
 /**
  * An implementation of IAppTask, that allows an app to manage its own tasks via
@@ -123,7 +126,7 @@
                 }
                 final BackgroundActivityStartController balController =
                         mService.mTaskSupervisor.getBackgroundActivityLaunchController();
-                if (balController.shouldAbortBackgroundActivityStart(
+                BalVerdict balVerdict = balController.checkBackgroundActivityStart(
                         callingUid,
                         callingPid,
                         callingPackage,
@@ -133,10 +136,14 @@
                         null,
                         BackgroundStartPrivileges.NONE,
                         null,
-                        null)) {
-                    if (!mService.isBackgroundActivityStartsEnabled()) {
-                        return;
-                    }
+                        null,
+                        null);
+                if (balVerdict.blocks() && !mService.isBackgroundActivityStartsEnabled()) {
+                    Slog.w(TAG, "moveTaskToFront blocked: : " + balVerdict);
+                    return;
+                }
+                if (DEBUG_ACTIVITY_STARTS) {
+                    Slog.d(TAG, "moveTaskToFront allowed: " + balVerdict);
                 }
             }
             mService.mTaskSupervisor.startActivityFromRecents(callingPid, callingUid, mTaskId,
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index c5902c9..c3f1e41 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -258,11 +258,11 @@
                 // activity, we won't close the activity.
                 backType = BackNavigationInfo.TYPE_DIALOG_CLOSE;
                 removedWindowContainer = window;
-            } else if (!currentActivity.occludesParent() || currentActivity.showWallpaper()) {
-                // skip if current activity is translucent
+            } else if (hasTranslucentActivity(currentActivity, prevActivities)) {
+                // skip if one of participant activity is translucent
                 backType = BackNavigationInfo.TYPE_CALLBACK;
             } else if (prevActivities.size() > 0) {
-                if (!isOccluded || prevActivities.get(0).canShowWhenLocked()) {
+                if (!isOccluded || isAllActivitiesCanShowWhenLocked(prevActivities)) {
                     // We have another Activity in the same currentTask to go to
                     final WindowContainer parent = currentActivity.getParent();
                     final boolean canCustomize = parent != null
@@ -307,7 +307,7 @@
                     findAdjacentActivityIfExist(tmpPre, prevActivities);
                 }
                 if (prevTask == null || prevActivities.isEmpty()
-                        || (isOccluded && !prevActivities.get(0).canShowWhenLocked())) {
+                        || (isOccluded && !isAllActivitiesCanShowWhenLocked(prevActivities))) {
                     backType = BackNavigationInfo.TYPE_CALLBACK;
                 } else if (prevTask.isActivityTypeHome()) {
                     removedWindowContainer = currentTask;
@@ -508,6 +508,30 @@
         outList.add(topActivity);
     }
 
+    private static boolean hasTranslucentActivity(@NonNull ActivityRecord currentActivity,
+            @NonNull ArrayList<ActivityRecord> prevActivities) {
+        if (!currentActivity.occludesParent() || currentActivity.showWallpaper()) {
+            return true;
+        }
+        for (int i = prevActivities.size() - 1; i >= 0; --i) {
+            final ActivityRecord test = prevActivities.get(i);
+            if (!test.occludesParent() || test.showWallpaper()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static boolean isAllActivitiesCanShowWhenLocked(
+            @NonNull ArrayList<ActivityRecord> prevActivities) {
+        for (int i = prevActivities.size() - 1; i >= 0; --i) {
+            if (!prevActivities.get(i).canShowWhenLocked()) {
+                return false;
+            }
+        }
+        return !prevActivities.isEmpty();
+    }
+
     boolean isMonitoringTransition() {
         return mAnimationHandler.mComposed || mNavigationMonitor.isMonitorForRemote();
     }
diff --git a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
index f8b22c9..4929df80 100644
--- a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
+++ b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
@@ -20,6 +20,7 @@
 import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
 import static android.os.Process.SYSTEM_UID;
 import static android.provider.DeviceConfig.NAMESPACE_WINDOW_MANAGER;
 
@@ -49,7 +50,6 @@
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.PackageManager;
-import android.os.Build;
 import android.os.Process;
 import android.os.UserHandle;
 import android.provider.DeviceConfig;
@@ -86,7 +86,7 @@
     private static final int NO_PROCESS_UID = -1;
     /** If enabled the creator will not allow BAL on its behalf by default. */
     @ChangeId
-    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+    @EnabledAfter(targetSdkVersion = UPSIDE_DOWN_CAKE)
     private static final long DEFAULT_RESCIND_BAL_PRIVILEGES_FROM_PENDING_INTENT_CREATOR =
             296478951;
     public static final ActivityOptions ACTIVITY_OPTIONS_SYSTEM_DEFINED =
@@ -205,27 +205,6 @@
         return activity != null && packageName.equals(activity.getPackageName());
     }
 
-    /**
-     * @see #checkBackgroundActivityStart(int, int, String, int, int, WindowProcessController,
-     *      PendingIntentRecord, BackgroundStartPrivileges, Intent, ActivityOptions)
-     */
-    boolean shouldAbortBackgroundActivityStart(
-            int callingUid,
-            int callingPid,
-            final String callingPackage,
-            int realCallingUid,
-            int realCallingPid,
-            WindowProcessController callerApp,
-            PendingIntentRecord originatingPendingIntent,
-            BackgroundStartPrivileges forcedBalByPiSender,
-            Intent intent,
-            ActivityOptions checkedOptions) {
-        return checkBackgroundActivityStart(callingUid, callingPid, callingPackage,
-                realCallingUid, realCallingPid,
-                callerApp, originatingPendingIntent,
-                forcedBalByPiSender, intent, checkedOptions).blocks();
-    }
-
     private class BalState {
 
         private final String mCallingPackage;
@@ -249,12 +228,14 @@
         private final Intent mIntent;
         private final WindowProcessController mCallerApp;
         private final WindowProcessController mRealCallerApp;
+        private final boolean mIsCallForResult;
 
         private BalState(int callingUid, int callingPid, final String callingPackage,
                  int realCallingUid, int realCallingPid,
                  WindowProcessController callerApp,
                  PendingIntentRecord originatingPendingIntent,
                  BackgroundStartPrivileges forcedBalByPiSender,
+                 ActivityRecord resultRecord,
                  Intent intent,
                  ActivityOptions checkedOptions) {
             this.mCallingPackage = callingPackage;
@@ -267,7 +248,11 @@
             mOriginatingPendingIntent = originatingPendingIntent;
             mIntent = intent;
             mRealCallingPackage = mService.getPackageNameIfUnique(realCallingUid, realCallingPid);
-            if (originatingPendingIntent == null) {
+            mIsCallForResult = resultRecord != null;
+            if (balRequireOptInByPendingIntentCreator() // auto-opt in introduced with this feature
+                    && (originatingPendingIntent == null // not a PendingIntent
+                    || mIsCallForResult) // sent for result
+            ) {
                 // grant BAL privileges unless explicitly opted out
                 mBalAllowedByPiCreatorWithHardening = mBalAllowedByPiCreator =
                         checkedOptions.getPendingIntentCreatorBackgroundActivityStartMode()
@@ -369,6 +354,19 @@
             return name + "[debugOnly]";
         }
 
+        /** @return valid targetSdk or <code>-1</code> */
+        private int getTargetSdk(String packageName) {
+            if (packageName == null) {
+                return -1;
+            }
+            try {
+                PackageManager pm = mService.mContext.getPackageManager();
+                return pm.getTargetSdkVersion(packageName);
+            } catch (Exception e) {
+                return -1;
+            }
+        }
+
         private boolean hasRealCaller() {
             return mRealCallingUid != NO_PROCESS_UID;
         }
@@ -386,6 +384,7 @@
             StringBuilder sb = new StringBuilder(2048);
             sb.append("[callingPackage: ")
                     .append(getDebugPackageName(mCallingPackage, mCallingUid));
+            sb.append("; callingPackageTargetSdk: ").append(getTargetSdk(mCallingPackage));
             sb.append("; callingUid: ").append(mCallingUid);
             sb.append("; callingPid: ").append(mCallingPid);
             sb.append("; appSwitchState: ").append(mAppSwitchState);
@@ -405,10 +404,13 @@
                     .append(mBalAllowedByPiCreatorWithHardening);
             sb.append("; resultIfPiCreatorAllowsBal: ").append(resultIfPiCreatorAllowsBal);
             sb.append("; hasRealCaller: ").append(hasRealCaller());
+            sb.append("; isCallForResult: ").append(mIsCallForResult);
             sb.append("; isPendingIntent: ").append(isPendingIntent());
             if (hasRealCaller()) {
                 sb.append("; realCallingPackage: ")
                         .append(getDebugPackageName(mRealCallingPackage, mRealCallingUid));
+                sb.append("; realCallingPackageTargetSdk: ")
+                        .append(getTargetSdk(mRealCallingPackage));
                 sb.append("; realCallingUid: ").append(mRealCallingUid);
                 sb.append("; realCallingPid: ").append(mRealCallingPid);
                 sb.append("; realCallingUidHasAnyVisibleWindow: ")
@@ -443,6 +445,8 @@
         // indicates BAL would be blocked because only creator of the PI has the privilege to allow
         // BAL, the sender does not have the privilege to allow BAL.
         private boolean mOnlyCreatorAllows;
+        /** indicates that this verdict is based on the real calling UID and not the calling UID */
+        private boolean mBasedOnRealCaller;
 
         BalVerdict(@BalCode int balCode, boolean background, String message) {
             this.mBackground = background;
@@ -472,6 +476,15 @@
             return mOnlyCreatorAllows;
         }
 
+        private BalVerdict setBasedOnRealCaller() {
+            mBasedOnRealCaller = true;
+            return this;
+        }
+
+        private boolean isBasedOnRealCaller() {
+            return mBasedOnRealCaller;
+        }
+
         public String toString() {
             StringBuilder builder = new StringBuilder();
             builder.append(balCodeToString(mCode));
@@ -495,7 +508,15 @@
             return builder.toString();
         }
 
+        public @BalCode int getRawCode() {
+            return mCode;
+        }
+
         public @BalCode int getCode() {
+            if (mBasedOnRealCaller && mCode != BAL_BLOCK) {
+                // for compatibility always return BAL_ALLOW_PENDING_INTENT if based on real caller
+                return BAL_ALLOW_PENDING_INTENT;
+            }
             return mCode;
         }
     }
@@ -516,6 +537,7 @@
      * @param forcedBalByPiSender If set to allow, the
      *        PendingIntent's sender will try to force allow background activity starts.
      *        This is only possible if the sender of the PendingIntent is a system process.
+     * @param resultRecord If not null, this indicates that the caller expects a result.
      * @param intent Intent that should be started.
      * @param checkedOptions ActivityOptions to allow specific opt-ins/opt outs.
      *
@@ -531,6 +553,7 @@
             WindowProcessController callerApp,
             PendingIntentRecord originatingPendingIntent,
             BackgroundStartPrivileges forcedBalByPiSender,
+            ActivityRecord resultRecord,
             Intent intent,
             ActivityOptions checkedOptions) {
 
@@ -541,7 +564,7 @@
 
         BalState state = new BalState(callingUid, callingPid, callingPackage,
                 realCallingUid, realCallingPid, callerApp, originatingPendingIntent,
-                forcedBalByPiSender, intent, checkedOptions);
+                forcedBalByPiSender, resultRecord, intent, checkedOptions);
 
         // In the case of an SDK sandbox calling uid, check if the corresponding app uid has a
         // visible window.
@@ -580,7 +603,8 @@
         // PendingIntents is null).
         BalVerdict resultForRealCaller = state.callerIsRealCaller() && resultForCaller.allows()
                 ? resultForCaller
-                : checkBackgroundActivityStartAllowedBySender(state, checkedOptions);
+                : checkBackgroundActivityStartAllowedBySender(state, checkedOptions)
+                        .setBasedOnRealCaller();
         if (state.isPendingIntent()) {
             resultForCaller.setOnlyCreatorAllows(
                     resultForCaller.allows() && resultForRealCaller.blocks());
@@ -828,7 +852,7 @@
                 && ActivityManager.checkComponentPermission(
                 android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND,
                 state.mRealCallingUid, NO_PROCESS_UID, true) == PackageManager.PERMISSION_GRANTED) {
-            return new BalVerdict(BAL_ALLOW_PENDING_INTENT,
+            return new BalVerdict(BAL_ALLOW_PERMISSION,
                     /*background*/ false,
                     "realCallingUid has BAL permission.");
         }
@@ -839,18 +863,18 @@
                 || state.mAppSwitchState == APP_SWITCH_FG_ONLY;
         if (Flags.balImproveRealCallerVisibilityCheck()) {
             if (appSwitchAllowedOrFg && state.mRealCallingUidHasAnyVisibleWindow) {
-                return new BalVerdict(BAL_ALLOW_PENDING_INTENT,
+                return new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW,
                         /*background*/ false, "realCallingUid has visible window");
             }
             if (mService.mActiveUids.hasNonAppVisibleWindow(state.mRealCallingUid)) {
-                return new BalVerdict(BAL_ALLOW_PENDING_INTENT,
+                return new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW,
                         /*background*/ false, "realCallingUid has non-app visible window");
             }
         } else {
             // don't abort if the realCallingUid has a visible window
             // TODO(b/171459802): We should check appSwitchAllowed also
             if (state.mRealCallingUidHasAnyVisibleWindow) {
-                return new BalVerdict(BAL_ALLOW_PENDING_INTENT,
+                return new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW,
                         /*background*/ false,
                         "realCallingUid has visible (non-toast) window.");
             }
@@ -860,7 +884,7 @@
         // wasn't allowed to start an activity
         if (state.mForcedBalByPiSender.allowsBackgroundActivityStarts()
                 && state.mIsRealCallingUidPersistentSystemProcess) {
-            return new BalVerdict(BAL_ALLOW_PENDING_INTENT,
+            return new BalVerdict(BAL_ALLOW_ALLOWLISTED_UID,
                     /*background*/ false,
                     "realCallingUid is persistent system process AND intent "
                             + "sender forced to allow.");
@@ -868,7 +892,7 @@
         // don't abort if the realCallingUid is an associated companion app
         if (mService.isAssociatedCompanionApp(
                 UserHandle.getUserId(state.mRealCallingUid), state.mRealCallingUid)) {
-            return new BalVerdict(BAL_ALLOW_PENDING_INTENT,
+            return new BalVerdict(BAL_ALLOW_ALLOWLISTED_COMPONENT,
                     /*background*/ false,
                     "realCallingUid is a companion app.");
         }
@@ -1469,7 +1493,7 @@
                     intent != null ? intent.getComponent().flattenToShortString() : "";
             FrameworkStatsLog.write(FrameworkStatsLog.BAL_ALLOWED,
                     activityName,
-                    code,
+                    BAL_ALLOW_PENDING_INTENT,
                     callingUid,
                     realCallingUid);
         }
diff --git a/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java b/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java
index 9a32dc8..478524b 100644
--- a/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java
+++ b/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java
@@ -22,7 +22,7 @@
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.ActivityTaskManagerService.ACTIVITY_BG_START_GRACE_PERIOD_MS;
 import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_ALLOW;
-import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_FG_ONLY;
+import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_DISALLOW;
 import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_FOREGROUND;
 import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_GRACE_PERIOD;
 import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_PERMISSION;
@@ -49,6 +49,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.server.wm.BackgroundActivityStartController.BalVerdict;
+import com.android.window.flags.Flags;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -113,13 +114,17 @@
                     "process allowed by token");
         }
         // Allow if the caller is bound by a UID that's currently foreground.
-        if (isBoundByForegroundUid()) {
+        // But still respect the appSwitchState.
+        boolean allowBoundByForegroundUid =
+                Flags.balRespectAppSwitchStateWhenCheckBoundByForegroundUid()
+                ? appSwitchState != APP_SWITCH_DISALLOW && isBoundByForegroundUid()
+                : isBoundByForegroundUid();
+        if (allowBoundByForegroundUid) {
             return new BalVerdict(BAL_ALLOW_VISIBLE_WINDOW, /*background*/ false,
                     "process bound by foreground uid");
         }
         // Allow if the caller has an activity in any foreground task.
-        if (hasActivityInVisibleTask
-                && (appSwitchState == APP_SWITCH_ALLOW || appSwitchState == APP_SWITCH_FG_ONLY)) {
+        if (hasActivityInVisibleTask && appSwitchState != APP_SWITCH_DISALLOW) {
             return new BalVerdict(BAL_ALLOW_FOREGROUND, /*background*/ false,
                     "process has activity in foreground task");
         }
diff --git a/services/core/java/com/android/server/wm/ClientLifecycleManager.java b/services/core/java/com/android/server/wm/ClientLifecycleManager.java
index 8b282dd3..6b6388b 100644
--- a/services/core/java/com/android/server/wm/ClientLifecycleManager.java
+++ b/services/core/java/com/android/server/wm/ClientLifecycleManager.java
@@ -22,7 +22,13 @@
 import android.app.servertransaction.ClientTransaction;
 import android.app.servertransaction.ClientTransactionItem;
 import android.os.Binder;
+import android.os.IBinder;
 import android.os.RemoteException;
+import android.util.ArrayMap;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.window.flags.Flags;
 
 /**
  * Class that is able to combine multiple client lifecycle transition requests and/or callbacks,
@@ -31,8 +37,18 @@
  * @see ClientTransaction
  */
 class ClientLifecycleManager {
-    // TODO(lifecycler): Implement building transactions or global transaction.
-    // TODO(lifecycler): Use object pools for transactions and transaction items.
+
+    private static final String TAG = "ClientLifecycleManager";
+
+    /** Mapping from client process binder to its pending transaction. */
+    @VisibleForTesting
+    final ArrayMap<IBinder, ClientTransaction> mPendingTransactions = new ArrayMap<>();
+
+    private WindowManagerService mWms;
+
+    void setWindowManager(@NonNull WindowManagerService wms) {
+        mWms = wms;
+    }
 
     /**
      * Schedules a transaction, which may consist of multiple callbacks and a lifecycle request.
@@ -82,14 +98,24 @@
      */
     void scheduleTransactionItem(@NonNull IApplicationThread client,
             @NonNull ClientTransactionItem transactionItem) throws RemoteException {
-        // TODO(b/260873529): queue the transaction items.
-        final ClientTransaction clientTransaction = ClientTransaction.obtain(client);
-        if (transactionItem.isActivityLifecycleItem()) {
-            clientTransaction.setLifecycleStateRequest((ActivityLifecycleItem) transactionItem);
+        // The behavior is different depending on the flag.
+        // When flag is on, we wait until RootWindowContainer#performSurfacePlacementNoTrace to
+        // dispatch all pending transactions at once.
+        if (Flags.bundleClientTransactionFlag()) {
+            final ClientTransaction clientTransaction = getOrCreatePendingTransaction(client);
+            clientTransaction.addTransactionItem(transactionItem);
+
+            onClientTransactionItemScheduledLocked(clientTransaction);
         } else {
-            clientTransaction.addCallback(transactionItem);
+            // TODO(b/260873529): cleanup after launch.
+            final ClientTransaction clientTransaction = ClientTransaction.obtain(client);
+            if (transactionItem.isActivityLifecycleItem()) {
+                clientTransaction.setLifecycleStateRequest((ActivityLifecycleItem) transactionItem);
+            } else {
+                clientTransaction.addCallback(transactionItem);
+            }
+            scheduleTransaction(clientTransaction);
         }
-        scheduleTransaction(clientTransaction);
     }
 
     /**
@@ -100,10 +126,67 @@
     void scheduleTransactionAndLifecycleItems(@NonNull IApplicationThread client,
             @NonNull ClientTransactionItem transactionItem,
             @NonNull ActivityLifecycleItem lifecycleItem) throws RemoteException {
-        // TODO(b/260873529): replace with #scheduleTransactionItem after launch for cleanup.
-        final ClientTransaction clientTransaction = ClientTransaction.obtain(client);
-        clientTransaction.addCallback(transactionItem);
-        clientTransaction.setLifecycleStateRequest(lifecycleItem);
+        // The behavior is different depending on the flag.
+        // When flag is on, we wait until RootWindowContainer#performSurfacePlacementNoTrace to
+        // dispatch all pending transactions at once.
+        if (Flags.bundleClientTransactionFlag()) {
+            final ClientTransaction clientTransaction = getOrCreatePendingTransaction(client);
+            clientTransaction.addTransactionItem(transactionItem);
+            clientTransaction.addTransactionItem(lifecycleItem);
+
+            onClientTransactionItemScheduledLocked(clientTransaction);
+        } else {
+            // TODO(b/260873529): cleanup after launch.
+            final ClientTransaction clientTransaction = ClientTransaction.obtain(client);
+            clientTransaction.addCallback(transactionItem);
+            clientTransaction.setLifecycleStateRequest(lifecycleItem);
+            scheduleTransaction(clientTransaction);
+        }
+    }
+
+    /** Executes all the pending transactions. */
+    void dispatchPendingTransactions() {
+        final int size = mPendingTransactions.size();
+        for (int i = 0; i < size; i++) {
+            final ClientTransaction transaction = mPendingTransactions.valueAt(i);
+            try {
+                scheduleTransaction(transaction);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Failed to deliver transaction for " + transaction.getClient());
+            }
+        }
+        mPendingTransactions.clear();
+    }
+
+    @NonNull
+    private ClientTransaction getOrCreatePendingTransaction(@NonNull IApplicationThread client) {
+        final IBinder clientBinder = client.asBinder();
+        final ClientTransaction pendingTransaction = mPendingTransactions.get(clientBinder);
+        if (pendingTransaction != null) {
+            return pendingTransaction;
+        }
+
+        // Create new transaction if there is no existing.
+        final ClientTransaction transaction = ClientTransaction.obtain(client);
+        mPendingTransactions.put(clientBinder, transaction);
+        return transaction;
+    }
+
+    /** Must only be called with WM lock. */
+    private void onClientTransactionItemScheduledLocked(
+            @NonNull ClientTransaction clientTransaction) throws RemoteException {
+        // TODO(b/260873529): make sure WindowSurfacePlacer#requestTraversal is called before
+        // ClientTransaction scheduled when needed.
+
+        if (mWms != null && (mWms.mWindowPlacerLocked.isInLayout()
+                || mWms.mWindowPlacerLocked.isTraversalScheduled())) {
+            // The pending transactions will be dispatched when
+            // RootWindowContainer#performSurfacePlacementNoTrace.
+            return;
+        }
+
+        // Dispatch the pending transaction immediately.
+        mPendingTransactions.remove(clientTransaction.getClient().asBinder());
         scheduleTransaction(clientTransaction);
     }
 }
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index 7947112..be7c18c 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -23,7 +23,9 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.app.WindowConfiguration.activityTypeToString;
 import static android.app.WindowConfiguration.windowingModeToString;
 import static android.app.WindowConfigurationProto.WINDOWING_MODE;
@@ -739,17 +741,43 @@
      * level with the input prefix.
      */
     public void dumpChildrenNames(PrintWriter pw, String prefix) {
-        final String childPrefix = prefix + " ";
+        dumpChildrenNames(pw, prefix, true /* isLastChild */);
+    }
+
+    /**
+     * Dumps the names of this container children in the input print writer indenting each
+     * level with the input prefix.
+     */
+    public void dumpChildrenNames(PrintWriter pw, String prefix, boolean isLastChild) {
+        int curWinMode = getWindowingMode();
+        String winMode = windowingModeToString(curWinMode);
+        if (curWinMode != WINDOWING_MODE_UNDEFINED &&
+                curWinMode != WINDOWING_MODE_FULLSCREEN) {
+            winMode = winMode.toUpperCase();
+        }
+        int requestedWinMode = getRequestedOverrideWindowingMode();
+        String overrideWinMode = windowingModeToString(requestedWinMode);
+        if (requestedWinMode != WINDOWING_MODE_UNDEFINED &&
+                requestedWinMode != WINDOWING_MODE_FULLSCREEN) {
+            overrideWinMode = overrideWinMode.toUpperCase();
+        }
+        String actType = activityTypeToString(getActivityType());
+        if (getActivityType() != ACTIVITY_TYPE_UNDEFINED
+                && getActivityType() != ACTIVITY_TYPE_STANDARD) {
+            actType = actType.toUpperCase();
+        }
+        pw.print(prefix + (isLastChild ? "└─ " : "├─ "));
         pw.println(getName()
-                + " type=" + activityTypeToString(getActivityType())
-                + " mode=" + windowingModeToString(getWindowingMode())
-                + " override-mode=" + windowingModeToString(getRequestedOverrideWindowingMode())
+                + " type=" + actType
+                + " mode=" + winMode
+                + " override-mode=" + overrideWinMode
                 + " requested-bounds=" + getRequestedOverrideBounds().toShortString()
                 + " bounds=" + getBounds().toShortString());
+
+        String childPrefix = prefix + (isLastChild ? "   " : "│  ");
         for (int i = getChildCount() - 1; i >= 0; --i) {
             final E cc = getChildAt(i);
-            pw.print(childPrefix + "#" + i + " ");
-            cc.dumpChildrenNames(pw, childPrefix);
+            cc.dumpChildrenNames(pw, childPrefix, i == 0 /* isLastChild */);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/DeferredDisplayUpdater.java b/services/core/java/com/android/server/wm/DeferredDisplayUpdater.java
new file mode 100644
index 0000000..975fdc0
--- /dev/null
+++ b/services/core/java/com/android/server/wm/DeferredDisplayUpdater.java
@@ -0,0 +1,345 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static android.view.WindowManager.TRANSIT_CHANGE;
+
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS;
+import static com.android.server.wm.ActivityTaskManagerService.POWER_MODE_REASON_CHANGE_DISPLAY;
+import static com.android.server.wm.utils.DisplayInfoOverrides.WM_OVERRIDE_FIELDS;
+import static com.android.server.wm.utils.DisplayInfoOverrides.copyDisplayInfoFields;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.graphics.Rect;
+import android.view.DisplayInfo;
+import android.window.DisplayAreaInfo;
+import android.window.TransitionRequestInfo;
+import android.window.WindowContainerTransaction;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.display.BrightnessSynchronizer;
+import com.android.internal.protolog.common.ProtoLog;
+import com.android.server.wm.utils.DisplayInfoOverrides.DisplayInfoFieldsUpdater;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * A DisplayUpdater that could defer and queue display updates coming from DisplayManager to
+ * WindowManager. It allows to defer pending display updates if WindowManager is currently not
+ * ready to apply them.
+ * For example, this might happen if there is a Shell transition running and physical display
+ * changed. We can't immediately apply the display updates because we want to start a separate
+ * display change transition. In this case, we will queue all display updates until the current
+ * transition's collection finishes and then apply them afterwards.
+ */
+public class DeferredDisplayUpdater implements DisplayUpdater {
+
+    /**
+     * List of fields that could be deferred before applying to DisplayContent.
+     * This should be kept in sync with {@link DeferredDisplayUpdater#calculateDisplayInfoDiff}
+     */
+    @VisibleForTesting
+    static final DisplayInfoFieldsUpdater DEFERRABLE_FIELDS = (out, override) -> {
+        // Treat unique id and address change as WM-specific display change as we re-query display
+        // settings and parameters based on it which could cause window changes
+        out.uniqueId = override.uniqueId;
+        out.address = override.address;
+
+        // Also apply WM-override fields, since they might produce differences in window hierarchy
+        WM_OVERRIDE_FIELDS.setFields(out, override);
+    };
+
+    private final DisplayContent mDisplayContent;
+
+    @NonNull
+    private final DisplayInfo mNonOverrideDisplayInfo = new DisplayInfo();
+
+    /**
+     * The last known display parameters from DisplayManager, some WM-specific fields in this object
+     * might not be applied to the DisplayContent yet
+     */
+    @Nullable
+    private DisplayInfo mLastDisplayInfo;
+
+    /**
+     * The last DisplayInfo that was applied to DisplayContent, only WM-specific parameters must be
+     * used from this object. This object is used to store old values of DisplayInfo while these
+     * fields are pending to be applied to DisplayContent.
+     */
+    @Nullable
+    private DisplayInfo mLastWmDisplayInfo;
+
+    @NonNull
+    private final DisplayInfo mOutputDisplayInfo = new DisplayInfo();
+
+    public DeferredDisplayUpdater(@NonNull DisplayContent displayContent) {
+        mDisplayContent = displayContent;
+        mNonOverrideDisplayInfo.copyFrom(mDisplayContent.getDisplayInfo());
+    }
+
+    /**
+     * Reads the latest display parameters from the display manager and returns them in a callback.
+     * If there are pending display updates, it will wait for them to finish first and only then it
+     * will call the callback with the latest display parameters.
+     *
+     * @param finishCallback is called when all pending display updates are finished
+     */
+    @Override
+    public void updateDisplayInfo(@NonNull Runnable finishCallback) {
+        // Get the latest display parameters from the DisplayManager
+        final DisplayInfo displayInfo = getCurrentDisplayInfo();
+
+        final int displayInfoDiff = calculateDisplayInfoDiff(mLastDisplayInfo, displayInfo);
+        final boolean physicalDisplayUpdated = isPhysicalDisplayUpdated(mLastDisplayInfo,
+                displayInfo);
+
+        mLastDisplayInfo = displayInfo;
+
+        // Apply whole display info immediately as is if either:
+        // * it is the first display update
+        // * shell transitions are disabled or temporary unavailable
+        if (displayInfoDiff == DIFF_EVERYTHING
+                || !mDisplayContent.mTransitionController.isShellTransitionsEnabled()) {
+            ProtoLog.d(WM_DEBUG_WINDOW_TRANSITIONS,
+                    "DeferredDisplayUpdater: applying DisplayInfo immediately");
+
+            mLastWmDisplayInfo = displayInfo;
+            applyLatestDisplayInfo();
+            finishCallback.run();
+            return;
+        }
+
+        // If there are non WM-specific display info changes, apply only these fields immediately
+        if ((displayInfoDiff & DIFF_NOT_WM_DEFERRABLE) > 0) {
+            ProtoLog.d(WM_DEBUG_WINDOW_TRANSITIONS,
+                    "DeferredDisplayUpdater: partially applying DisplayInfo immediately");
+            applyLatestDisplayInfo();
+        }
+
+        // If there are WM-specific display info changes, apply them through a Shell transition
+        if ((displayInfoDiff & DIFF_WM_DEFERRABLE) > 0) {
+            ProtoLog.d(WM_DEBUG_WINDOW_TRANSITIONS,
+                    "DeferredDisplayUpdater: deferring DisplayInfo update");
+
+            requestDisplayChangeTransition(physicalDisplayUpdated, () -> {
+                // Apply deferrable fields to DisplayContent only when the transition
+                // starts collecting, non-deferrable fields are ignored in mLastWmDisplayInfo
+                mLastWmDisplayInfo = displayInfo;
+                applyLatestDisplayInfo();
+                finishCallback.run();
+            });
+        } else {
+            // There are no WM-specific updates, so we can immediately notify that all display
+            // info changes are applied
+            finishCallback.run();
+        }
+    }
+
+    /**
+     * Requests a display change Shell transition
+     *
+     * @param physicalDisplayUpdated if true also starts remote display change
+     * @param onStartCollect         called when the Shell transition starts collecting
+     */
+    private void requestDisplayChangeTransition(boolean physicalDisplayUpdated,
+            @NonNull Runnable onStartCollect) {
+
+        final Transition transition = new Transition(TRANSIT_CHANGE, /* flags= */ 0,
+                mDisplayContent.mTransitionController,
+                mDisplayContent.mTransitionController.mSyncEngine);
+
+        mDisplayContent.mAtmService.startPowerMode(POWER_MODE_REASON_CHANGE_DISPLAY);
+
+        mDisplayContent.mTransitionController.startCollectOrQueue(transition, deferred -> {
+            final Rect startBounds = new Rect(0, 0, mDisplayContent.mInitialDisplayWidth,
+                    mDisplayContent.mInitialDisplayHeight);
+            final int fromRotation = mDisplayContent.getRotation();
+
+            onStartCollect.run();
+
+            ProtoLog.d(WM_DEBUG_WINDOW_TRANSITIONS,
+                    "DeferredDisplayUpdater: applied DisplayInfo after deferring");
+
+            if (physicalDisplayUpdated) {
+                onDisplayUpdated(transition, fromRotation, startBounds);
+            } else {
+                transition.setAllReady();
+            }
+        });
+    }
+
+    /**
+     * Applies current DisplayInfo to DisplayContent, DisplayContent is merged from two parts:
+     * - non-deferrable fields are set from the most recent values received from DisplayManager
+     * (uses {@link mLastDisplayInfo} field)
+     * - deferrable fields are set from the latest values that we could apply to WM
+     * (uses {@link mLastWmDisplayInfo} field)
+     */
+    private void applyLatestDisplayInfo() {
+        copyDisplayInfoFields(mOutputDisplayInfo, /* base= */ mLastDisplayInfo,
+                /* override= */ mLastWmDisplayInfo, /* fields= */ DEFERRABLE_FIELDS);
+        mDisplayContent.onDisplayInfoUpdated(mOutputDisplayInfo);
+    }
+
+    @NonNull
+    private DisplayInfo getCurrentDisplayInfo() {
+        mDisplayContent.mWmService.mDisplayManagerInternal.getNonOverrideDisplayInfo(
+                mDisplayContent.mDisplayId, mNonOverrideDisplayInfo);
+        return new DisplayInfo(mNonOverrideDisplayInfo);
+    }
+
+    /**
+     * Called when physical display is updated, this could happen e.g. on foldable
+     * devices when the physical underlying display is replaced. This method should be called
+     * when the new display info is already applied to the WM hierarchy.
+     *
+     * @param fromRotation rotation before the display change
+     * @param startBounds  display bounds before the display change
+     */
+    private void onDisplayUpdated(@NonNull Transition transition, int fromRotation,
+            @NonNull Rect startBounds) {
+        final Rect endBounds = new Rect(0, 0, mDisplayContent.mInitialDisplayWidth,
+                mDisplayContent.mInitialDisplayHeight);
+        final int toRotation = mDisplayContent.getRotation();
+
+        final TransitionRequestInfo.DisplayChange displayChange =
+                new TransitionRequestInfo.DisplayChange(mDisplayContent.getDisplayId());
+        displayChange.setStartAbsBounds(startBounds);
+        displayChange.setEndAbsBounds(endBounds);
+        displayChange.setStartRotation(fromRotation);
+        displayChange.setEndRotation(toRotation);
+        displayChange.setPhysicalDisplayChanged(true);
+
+        mDisplayContent.mTransitionController.requestStartTransition(transition,
+                /* startTask= */ null, /* remoteTransition= */ null, displayChange);
+
+        final DisplayAreaInfo newDisplayAreaInfo = mDisplayContent.getDisplayAreaInfo();
+
+        final boolean startedRemoteChange = mDisplayContent.mRemoteDisplayChangeController
+                .performRemoteDisplayChange(fromRotation, toRotation, newDisplayAreaInfo,
+                        transaction -> finishDisplayUpdate(transaction, transition));
+
+        if (!startedRemoteChange) {
+            finishDisplayUpdate(/* wct= */ null, transition);
+        }
+    }
+
+    private void finishDisplayUpdate(@Nullable WindowContainerTransaction wct,
+            @NonNull Transition transition) {
+        if (wct != null) {
+            mDisplayContent.mAtmService.mWindowOrganizerController.applyTransaction(
+                    wct);
+        }
+        transition.setAllReady();
+    }
+
+    private boolean isPhysicalDisplayUpdated(@Nullable DisplayInfo first,
+            @Nullable DisplayInfo second) {
+        if (first == null || second == null) return true;
+        return !Objects.equals(first.uniqueId, second.uniqueId);
+    }
+
+    /**
+     * Diff result: fields are the same
+     */
+    static final int DIFF_NONE = 0;
+
+    /**
+     * Diff result: fields that could be deferred in WM are different
+     */
+    static final int DIFF_WM_DEFERRABLE = 1 << 0;
+
+    /**
+     * Diff result: fields that could not be deferred in WM are different
+     */
+    static final int DIFF_NOT_WM_DEFERRABLE = 1 << 1;
+
+    /**
+     * Diff result: everything is different
+     */
+    static final int DIFF_EVERYTHING = 0XFFFFFFFF;
+
+    @VisibleForTesting
+    static int calculateDisplayInfoDiff(@Nullable DisplayInfo first, @Nullable DisplayInfo second) {
+        int diff = DIFF_NONE;
+
+        if (Objects.equals(first, second)) return diff;
+        if (first == null || second == null) return DIFF_EVERYTHING;
+
+        if (first.layerStack != second.layerStack
+                || first.flags != second.flags
+                || first.type != second.type
+                || first.displayId != second.displayId
+                || first.displayGroupId != second.displayGroupId
+                || !Objects.equals(first.deviceProductInfo, second.deviceProductInfo)
+                || first.modeId != second.modeId
+                || first.renderFrameRate != second.renderFrameRate
+                || first.defaultModeId != second.defaultModeId
+                || first.userPreferredModeId != second.userPreferredModeId
+                || !Arrays.equals(first.supportedModes, second.supportedModes)
+                || first.colorMode != second.colorMode
+                || !Arrays.equals(first.supportedColorModes, second.supportedColorModes)
+                || !Objects.equals(first.hdrCapabilities, second.hdrCapabilities)
+                || !Arrays.equals(first.userDisabledHdrTypes, second.userDisabledHdrTypes)
+                || first.minimalPostProcessingSupported != second.minimalPostProcessingSupported
+                || first.appVsyncOffsetNanos != second.appVsyncOffsetNanos
+                || first.presentationDeadlineNanos != second.presentationDeadlineNanos
+                || first.state != second.state
+                || first.committedState != second.committedState
+                || first.ownerUid != second.ownerUid
+                || !Objects.equals(first.ownerPackageName, second.ownerPackageName)
+                || first.removeMode != second.removeMode
+                || first.getRefreshRate() != second.getRefreshRate()
+                || first.brightnessMinimum != second.brightnessMinimum
+                || first.brightnessMaximum != second.brightnessMaximum
+                || first.brightnessDefault != second.brightnessDefault
+                || first.installOrientation != second.installOrientation
+                || !Objects.equals(first.layoutLimitedRefreshRate, second.layoutLimitedRefreshRate)
+                || !BrightnessSynchronizer.floatEquals(first.hdrSdrRatio, second.hdrSdrRatio)
+                || !first.thermalRefreshRateThrottling.contentEquals(
+                second.thermalRefreshRateThrottling)
+                || !Objects.equals(first.thermalBrightnessThrottlingDataId,
+                second.thermalBrightnessThrottlingDataId)) {
+            diff |= DIFF_NOT_WM_DEFERRABLE;
+        }
+
+        if (first.appWidth != second.appWidth
+                || first.appHeight != second.appHeight
+                || first.smallestNominalAppWidth != second.smallestNominalAppWidth
+                || first.smallestNominalAppHeight != second.smallestNominalAppHeight
+                || first.largestNominalAppWidth != second.largestNominalAppWidth
+                || first.largestNominalAppHeight != second.largestNominalAppHeight
+                || first.logicalWidth != second.logicalWidth
+                || first.logicalHeight != second.logicalHeight
+                || first.physicalXDpi != second.physicalXDpi
+                || first.physicalYDpi != second.physicalYDpi
+                || first.rotation != second.rotation
+                || !Objects.equals(first.displayCutout, second.displayCutout)
+                || first.logicalDensityDpi != second.logicalDensityDpi
+                || !Objects.equals(first.roundedCorners, second.roundedCorners)
+                || !Objects.equals(first.displayShape, second.displayShape)
+                || !Objects.equals(first.uniqueId, second.uniqueId)
+                || !Objects.equals(first.address, second.address)
+        ) {
+            diff |= DIFF_WM_DEFERRABLE;
+        }
+
+        return diff;
+    }
+}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 50376fe..ae10ce3 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -276,6 +276,7 @@
 import java.util.Set;
 import java.util.function.Consumer;
 import java.util.function.Predicate;
+import static com.android.window.flags.Flags.deferDisplayUpdates;
 
 /**
  * Utility class for keeping track of the WindowStates and other pertinent contents of a
@@ -545,10 +546,12 @@
     boolean isDefaultDisplay;
 
     /** Detect user tapping outside of current focused task bounds .*/
+    // TODO(b/315321016): Remove once pointer event detection is removed from WM.
     @VisibleForTesting
     final TaskTapPointerEventListener mTapDetector;
 
     /** Detect user tapping outside of current focused root task bounds .*/
+    // TODO(b/315321016): Remove once pointer event detection is removed from WM.
     private Region mTouchExcludeRegion = new Region();
 
     /** Save allocating when calculating rects */
@@ -1158,7 +1161,11 @@
         mWallpaperController.resetLargestDisplay(display);
         display.getDisplayInfo(mDisplayInfo);
         display.getMetrics(mDisplayMetrics);
-        mDisplayUpdater = new ImmediateDisplayUpdater(this);
+        if (deferDisplayUpdates()) {
+            mDisplayUpdater = new DeferredDisplayUpdater(this);
+        } else {
+            mDisplayUpdater = new ImmediateDisplayUpdater(this);
+        }
         mSystemGestureExclusionLimit = mWmService.mConstants.mSystemGestureExclusionLimitDp
                 * mDisplayMetrics.densityDpi / DENSITY_DEFAULT;
         isDefaultDisplay = mDisplayId == DEFAULT_DISPLAY;
@@ -1189,12 +1196,18 @@
                 "PointerEventDispatcher" + mDisplayId, mDisplayId);
         mPointerEventDispatcher = new PointerEventDispatcher(inputChannel);
 
-        // Tap Listeners are supported for:
-        // 1. All physical displays (multi-display).
-        // 2. VirtualDisplays on VR, AA (and everything else).
-        mTapDetector = new TaskTapPointerEventListener(mWmService, this);
-        registerPointerEventListener(mTapDetector);
-        registerPointerEventListener(mWmService.mMousePositionTracker);
+        if (com.android.input.flags.Flags.removePointerEventTrackingInWm()) {
+            mTapDetector = null;
+        } else {
+            // Tap Listeners are supported for:
+            // 1. All physical displays (multi-display).
+            // 2. VirtualDisplays on VR, AA (and everything else).
+            mTapDetector = new TaskTapPointerEventListener(mWmService, this);
+            registerPointerEventListener(mTapDetector);
+        }
+        if (mWmService.mMousePositionTracker != null) {
+            registerPointerEventListener(mWmService.mMousePositionTracker);
+        }
         if (mWmService.mAtmService.getRecentTasks() != null) {
             registerPointerEventListener(
                     mWmService.mAtmService.getRecentTasks().getInputListener());
@@ -1636,12 +1649,13 @@
         mWmService.mWindowPlacerLocked.performSurfacePlacement();
     }
 
-    void sendNewConfiguration() {
+    /** Returns {@code true} if the display configuration is changed. */
+    boolean sendNewConfiguration() {
         if (!isReady()) {
-            return;
+            return false;
         }
         if (mRemoteDisplayChangeController.isWaitingForRemoteDisplayChange()) {
-            return;
+            return false;
         }
 
         final Transition.ReadyCondition displayConfig = mTransitionController.isCollecting()
@@ -1656,7 +1670,7 @@
             displayConfig.meet();
         }
         if (configUpdated) {
-            return;
+            return true;
         }
 
         // The display configuration doesn't change. If there is a launching transformed app, that
@@ -1674,6 +1688,7 @@
             setLayoutNeeded();
             mWmService.mWindowPlacerLocked.performSurfacePlacement();
         }
+        return false;
     }
 
     @Override
@@ -1695,7 +1710,6 @@
             final ActivityRecord activityRecord = (ActivityRecord) requestingContainer;
             final boolean kept = updateDisplayOverrideConfigurationLocked(config, activityRecord,
                     false /* deferResume */, null /* result */);
-            activityRecord.frozenBeforeDestroy = true;
             if (!kept) {
                 mRootWindowContainer.resumeFocusedTasksTopActivities();
             }
@@ -3260,6 +3274,12 @@
     }
 
     void updateTouchExcludeRegion() {
+        if (mTapDetector == null) {
+            // The touch exclude region is used to detect the region outside of the focused task
+            // so that the tap detector can detect outside touches. Don't calculate the exclude
+            // region when the tap detector is disabled.
+            return;
+        }
         final Task focusedTask = (mFocusedApp != null ? mFocusedApp.getTask() : null);
         if (focusedTask == null) {
             mTouchExcludeRegion.setEmpty();
@@ -3298,6 +3318,11 @@
     }
 
     private void processTaskForTouchExcludeRegion(Task task, Task focusedTask, int delta) {
+        if (mTapDetector == null) {
+            // The touch exclude region is used to detect the region outside of the focused task
+            // so that the tap detector can detect outside touches. Don't calculate the exclude
+            // region when the tap detector is disabled.
+        }
         final ActivityRecord topVisibleActivity = task.getTopVisibleActivity();
 
         if (topVisibleActivity == null || !topVisibleActivity.hasContentToDisplay()) {
@@ -5124,8 +5149,13 @@
 
     /** @return the orientation of the display when it's rotation is ROTATION_0. */
     int getNaturalOrientation() {
-        return mBaseDisplayWidth < mBaseDisplayHeight
-                ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
+        final Configuration config = getConfiguration();
+        if (config.windowConfiguration.getDisplayRotation() == ROTATION_0) {
+            return config.orientation;
+        }
+        final Rect frame = mDisplayPolicy.getDecorInsetsInfo(
+                ROTATION_0, mBaseDisplayWidth, mBaseDisplayHeight).mConfigFrame;
+        return frame.width() <= frame.height() ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
     }
 
     void performLayout(boolean initial, boolean updateInputWindows) {
@@ -5502,6 +5532,10 @@
                 configureDisplayPolicy();
             }
 
+            if (!isDefaultDisplay) {
+                mDisplayRotation.updateRotationUnchecked(true);
+            }
+
             reconfigureDisplayLocked();
             onRequestedOverrideConfigurationChanged(getRequestedOverrideConfiguration());
             mWmService.mDisplayNotificationController.dispatchDisplayAdded(this);
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index b862d7c..460a68f 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -39,6 +39,7 @@
 import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_CONSUME_IME_INSETS;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IMMERSIVE_CONFIRMATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP;
@@ -272,6 +273,8 @@
 
     private @InsetsType int mForciblyShownTypes;
 
+    private boolean mImeInsetsConsumed;
+
     private boolean mIsImmersiveMode;
 
     // The windows we were told about in focusChanged.
@@ -1420,6 +1423,7 @@
         mShowingDream = false;
         mIsFreeformWindowOverlappingWithNavBar = false;
         mForciblyShownTypes = 0;
+        mImeInsetsConsumed = false;
     }
 
     /**
@@ -1481,6 +1485,17 @@
             mForciblyShownTypes |= win.mAttrs.forciblyShownTypes;
         }
 
+        if (win.mImeInsetsConsumed != mImeInsetsConsumed) {
+            win.mImeInsetsConsumed = mImeInsetsConsumed;
+            final WindowState imeWin = mDisplayContent.mInputMethodWindow;
+            if (win.isReadyToDispatchInsetsState() && imeWin != null && imeWin.isVisible()) {
+                win.notifyInsetsChanged();
+            }
+        }
+        if ((attrs.privateFlags & PRIVATE_FLAG_CONSUME_IME_INSETS) != 0 && win.isVisible()) {
+            mImeInsetsConsumed = true;
+        }
+
         if (!affectsSystemUi) {
             return;
         }
@@ -2828,6 +2843,7 @@
             }
         }
         pw.print(prefix); pw.print("mTopIsFullscreen="); pw.println(mTopIsFullscreen);
+        pw.print(prefix); pw.print("mImeInsetsConsumed="); pw.println(mImeInsetsConsumed);
         pw.print(prefix); pw.print("mForceShowNavigationBarEnabled=");
         pw.print(mForceShowNavigationBarEnabled);
         pw.print(" mAllowLockscreenWhenOn="); pw.println(mAllowLockscreenWhenOn);
diff --git a/services/core/java/com/android/server/wm/DragDropController.java b/services/core/java/com/android/server/wm/DragDropController.java
index 4a3d0c1..32d60c5 100644
--- a/services/core/java/com/android/server/wm/DragDropController.java
+++ b/services/core/java/com/android/server/wm/DragDropController.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import static com.android.input.flags.Flags.enablePointerChoreographer;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -23,6 +24,7 @@
 import android.annotation.NonNull;
 import android.content.ClipData;
 import android.content.Context;
+import android.hardware.input.InputManagerGlobal;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
@@ -31,6 +33,8 @@
 import android.util.Slog;
 import android.view.Display;
 import android.view.IWindow;
+import android.view.InputDevice;
+import android.view.PointerIcon;
 import android.view.SurfaceControl;
 import android.view.View;
 import android.view.accessibility.AccessibilityManager;
@@ -97,8 +101,8 @@
     }
 
     IBinder performDrag(int callerPid, int callerUid, IWindow window, int flags,
-            SurfaceControl surface, int touchSource, float touchX, float touchY,
-            float thumbCenterX, float thumbCenterY, ClipData data) {
+            SurfaceControl surface, int touchSource, int touchDeviceId, int touchPointerId,
+            float touchX, float touchY, float thumbCenterX, float thumbCenterY, ClipData data) {
         if (DEBUG_DRAG) {
             Slog.d(TAG_WM, "perform drag: win=" + window + " surface=" + surface + " flags=" +
                     Integer.toHexString(flags) + " data=" + data + " touch(" + touchX + ","
@@ -208,7 +212,17 @@
 
                 final SurfaceControl surfaceControl = mDragState.mSurfaceControl;
                 mDragState.broadcastDragStartedLocked(touchX, touchY);
-                mDragState.overridePointerIconLocked(touchSource);
+                if (enablePointerChoreographer()) {
+                    if ((touchSource & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE) {
+                        InputManagerGlobal.getInstance().setPointerIcon(
+                                PointerIcon.getSystemIcon(
+                                        mService.mContext, PointerIcon.TYPE_GRABBING),
+                                mDragState.mDisplayContent.getDisplayId(), touchDeviceId,
+                                touchPointerId, mDragState.getInputToken());
+                    }
+                } else {
+                    mDragState.overridePointerIconLocked(touchSource);
+                }
                 // remember the thumb offsets for later
                 mDragState.mThumbOffsetX = thumbCenterX;
                 mDragState.mThumbOffsetY = thumbCenterY;
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index a888f84..adbe3bc 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -416,6 +416,13 @@
         return mInputInterceptor == null ? null : mInputInterceptor.mDragWindowHandle;
     }
 
+    IBinder getInputToken() {
+        if (mInputInterceptor == null || mInputInterceptor.mClientChannel == null) {
+            return null;
+        }
+        return mInputInterceptor.mClientChannel.getToken();
+    }
+
     /**
      * @param display The Display that the window being dragged is on.
      */
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index c089d10..7815679 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -391,13 +391,26 @@
 
             if (originalImeSource != null) {
                 final boolean imeVisibility = w.isRequestedVisible(Type.ime());
-                final InsetsState state = copyState ? new InsetsState(originalState)
+                final InsetsState state = copyState
+                        ? new InsetsState(originalState)
                         : originalState;
                 final InsetsSource imeSource = new InsetsSource(originalImeSource);
                 imeSource.setVisible(imeVisibility);
                 state.addSource(imeSource);
                 return state;
             }
+        } else if (w.mImeInsetsConsumed) {
+            // Set the IME source (if there is one) to be invisible if it has been consumed.
+            final InsetsSource originalImeSource = originalState.peekSource(ID_IME);
+            if (originalImeSource != null && originalImeSource.isVisible()) {
+                final InsetsState state = copyState
+                        ? new InsetsState(originalState)
+                        : originalState;
+                final InsetsSource imeSource = new InsetsSource(originalImeSource);
+                imeSource.setVisible(false);
+                state.addSource(imeSource);
+                return state;
+            }
         }
         return originalState;
     }
diff --git a/services/core/java/com/android/server/wm/LaunchObserverRegistryImpl.java b/services/core/java/com/android/server/wm/LaunchObserverRegistryImpl.java
index 9cbc1bd..4c73a41 100644
--- a/services/core/java/com/android/server/wm/LaunchObserverRegistryImpl.java
+++ b/services/core/java/com/android/server/wm/LaunchObserverRegistryImpl.java
@@ -84,10 +84,10 @@
     }
 
     @Override
-    public void onActivityLaunched(long id, ComponentName name, int temperature) {
+    public void onActivityLaunched(long id, ComponentName name, int temperature, int userId) {
         mHandler.sendMessage(PooledLambda.obtainMessage(
                 LaunchObserverRegistryImpl::handleOnActivityLaunched,
-                this, id, name, temperature));
+                this, id, name, temperature, userId));
     }
 
     @Override
@@ -97,10 +97,11 @@
     }
 
     @Override
-    public void onActivityLaunchFinished(long id, ComponentName name, long timestampNs) {
+    public void onActivityLaunchFinished(long id, ComponentName name, long timestampNs,
+            int launchMode) {
         mHandler.sendMessage(PooledLambda.obtainMessage(
                 LaunchObserverRegistryImpl::handleOnActivityLaunchFinished,
-                this, id, name, timestampNs));
+                this, id, name, timestampNs, launchMode));
     }
 
     @Override
@@ -137,10 +138,10 @@
     }
 
     private void handleOnActivityLaunched(long id, ComponentName name,
-            @Temperature int temperature) {
+            @Temperature int temperature, int userId) {
         // Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee.
         for (int i = 0; i < mList.size(); i++) {
-            mList.get(i).onActivityLaunched(id, name, temperature);
+            mList.get(i).onActivityLaunched(id, name, temperature, userId);
         }
     }
 
@@ -151,10 +152,11 @@
         }
     }
 
-    private void handleOnActivityLaunchFinished(long id, ComponentName name, long timestampNs) {
+    private void handleOnActivityLaunchFinished(long id, ComponentName name, long timestampNs,
+            int launchMode) {
         // Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee.
         for (int i = 0; i < mList.size(); i++) {
-            mList.get(i).onActivityLaunchFinished(id, name, timestampNs);
+            mList.get(i).onActivityLaunchFinished(id, name, timestampNs, launchMode);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/PhysicalDisplaySwitchTransitionLauncher.java b/services/core/java/com/android/server/wm/PhysicalDisplaySwitchTransitionLauncher.java
index 0d15fc9..2b841fd 100644
--- a/services/core/java/com/android/server/wm/PhysicalDisplaySwitchTransitionLauncher.java
+++ b/services/core/java/com/android/server/wm/PhysicalDisplaySwitchTransitionLauncher.java
@@ -17,6 +17,7 @@
 package com.android.server.wm;
 
 import static android.view.WindowManager.TRANSIT_CHANGE;
+import static android.view.WindowManager.TRANSIT_FLAG_PHYSICAL_DISPLAY_SWITCH;
 
 import static com.android.internal.R.bool.config_unfoldTransitionEnabled;
 import static com.android.server.wm.ActivityTaskManagerService.POWER_MODE_REASON_CHANGE_DISPLAY;
@@ -110,15 +111,6 @@
             return;
         }
 
-        final TransitionRequestInfo.DisplayChange displayChange =
-                new TransitionRequestInfo.DisplayChange(displayId);
-
-        final Rect startAbsBounds = new Rect(0, 0, oldDisplayWidth, oldDisplayHeight);
-        displayChange.setStartAbsBounds(startAbsBounds);
-        final Rect endAbsBounds = new Rect(0, 0, newDisplayWidth, newDisplayHeight);
-        displayChange.setEndAbsBounds(endAbsBounds);
-        displayChange.setPhysicalDisplayChanged(true);
-
         mTransition = null;
 
         if (mTransitionController.isCollecting()) {
@@ -128,10 +120,20 @@
 
             // Make sure that transition is not ready until we finish the remote display change
             mTransition.setReady(mDisplayContent, false);
+            mTransition.addFlag(TRANSIT_FLAG_PHYSICAL_DISPLAY_SWITCH);
 
             ProtoLog.d(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
                     "Adding display switch to existing collecting transition");
         } else {
+            final TransitionRequestInfo.DisplayChange displayChange =
+                    new TransitionRequestInfo.DisplayChange(displayId);
+
+            final Rect startAbsBounds = new Rect(0, 0, oldDisplayWidth, oldDisplayHeight);
+            displayChange.setStartAbsBounds(startAbsBounds);
+            final Rect endAbsBounds = new Rect(0, 0, newDisplayWidth, newDisplayHeight);
+            displayChange.setEndAbsBounds(endAbsBounds);
+            displayChange.setPhysicalDisplayChanged(true);
+
             mTransition = mTransitionController.requestTransitionIfNeeded(TRANSIT_CHANGE,
                     0 /* flags */,
                     mDisplayContent, mDisplayContent, null /* remoteTransition */,
diff --git a/services/core/java/com/android/server/wm/RefreshRatePolicy.java b/services/core/java/com/android/server/wm/RefreshRatePolicy.java
index 23c135a..03574029 100644
--- a/services/core/java/com/android/server/wm/RefreshRatePolicy.java
+++ b/services/core/java/com/android/server/wm/RefreshRatePolicy.java
@@ -26,6 +26,7 @@
 import android.view.Display.Mode;
 import android.view.DisplayInfo;
 import android.view.Surface;
+import android.view.SurfaceControl;
 import android.view.SurfaceControl.RefreshRateRange;
 
 import java.util.HashMap;
@@ -191,26 +192,35 @@
     public static class FrameRateVote {
         float mRefreshRate;
         @Surface.FrameRateCompatibility int mCompatibility;
+        @SurfaceControl.FrameRateSelectionStrategy int mSelectionStrategy;
 
-        FrameRateVote(float refreshRate, @Surface.FrameRateCompatibility int compatibility) {
-            update(refreshRate, compatibility);
+
+
+        FrameRateVote(float refreshRate, @Surface.FrameRateCompatibility int compatibility,
+                      @SurfaceControl.FrameRateSelectionStrategy int selectionStrategy) {
+            update(refreshRate, compatibility, selectionStrategy);
         }
 
         FrameRateVote() {
             reset();
         }
 
-        boolean update(float refreshRate, @Surface.FrameRateCompatibility int compatibility) {
-            if (!refreshRateEquals(refreshRate) || mCompatibility != compatibility) {
+        boolean update(float refreshRate, @Surface.FrameRateCompatibility int compatibility,
+                       @SurfaceControl.FrameRateSelectionStrategy int selectionStrategy) {
+            if (!refreshRateEquals(refreshRate)
+                    || mCompatibility != compatibility
+                    || mSelectionStrategy != selectionStrategy) {
                 mRefreshRate = refreshRate;
                 mCompatibility = compatibility;
+                mSelectionStrategy = selectionStrategy;
                 return true;
             }
             return false;
         }
 
         boolean reset() {
-            return update(0, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT);
+            return update(0, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT,
+                    SurfaceControl.FRAME_RATE_SELECTION_STRATEGY_PROPAGATE);
         }
 
         @Override
@@ -221,17 +231,20 @@
 
             FrameRateVote other = (FrameRateVote) o;
             return refreshRateEquals(other.mRefreshRate)
-                    && mCompatibility == other.mCompatibility;
+                    && mCompatibility == other.mCompatibility
+                    && mSelectionStrategy == other.mSelectionStrategy;
         }
 
         @Override
         public int hashCode() {
-            return Objects.hash(mRefreshRate, mCompatibility);
+            return Objects.hash(mRefreshRate, mCompatibility, mSelectionStrategy);
+
         }
 
         @Override
         public String toString() {
-            return "mRefreshRate=" + mRefreshRate + ", mCompatibility=" + mCompatibility;
+            return "mRefreshRate=" + mRefreshRate + ", mCompatibility=" + mCompatibility
+                    + ", mSelectionStrategy=" + mSelectionStrategy;
         }
 
         private boolean refreshRateEquals(float refreshRate) {
@@ -265,7 +278,8 @@
                 for (Display.Mode mode : mDisplayInfo.supportedModes) {
                     if (preferredModeId == mode.getModeId()) {
                         return w.mFrameRateVote.update(mode.getRefreshRate(),
-                                Surface.FRAME_RATE_COMPATIBILITY_EXACT);
+                                Surface.FRAME_RATE_COMPATIBILITY_EXACT,
+                                SurfaceControl.FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN);
                     }
                 }
             }
@@ -273,7 +287,8 @@
 
         if (w.mAttrs.preferredRefreshRate > 0) {
             return w.mFrameRateVote.update(w.mAttrs.preferredRefreshRate,
-                    Surface.FRAME_RATE_COMPATIBILITY_DEFAULT);
+                    Surface.FRAME_RATE_COMPATIBILITY_DEFAULT,
+                    SurfaceControl.FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN);
         }
 
         // If the app didn't set a preferred mode id or refresh rate, but it is part of the deny
@@ -282,7 +297,8 @@
             final String packageName = w.getOwningPackage();
             if (mHighRefreshRateDenylist.isDenylisted(packageName)) {
                 return w.mFrameRateVote.update(mLowRefreshRateMode.getRefreshRate(),
-                        Surface.FRAME_RATE_COMPATIBILITY_EXACT);
+                        Surface.FRAME_RATE_COMPATIBILITY_EXACT,
+                        SurfaceControl.FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN);
             }
         }
 
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 522e7d2..9a75dae 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -842,6 +842,9 @@
         handleResizingWindows();
         clearFrameChangingWindows();
 
+        // Called after #handleResizingWindows to include WindowStateResizeItem if any.
+        mWmService.mAtmService.getLifecycleManager().dispatchPendingTransactions();
+
         if (mWmService.mDisplayFrozen) {
             ProtoLog.v(WM_DEBUG_ORIENTATION,
                     "With display frozen, orientationChangeComplete=%b",
@@ -1741,14 +1744,11 @@
      * @param starting                  The currently starting activity or {@code null} if there is
      *                                  none.
      * @param displayId                 The id of the display where operation is executed.
-     * @param markFrozenIfConfigChanged Whether to set {@link ActivityRecord#frozenBeforeDestroy} to
-     *                                  {@code true} if config changed.
      * @param deferResume               Whether to defer resume while updating config.
      * @return 'true' if starting activity was kept or wasn't provided, 'false' if it was relaunched
      * because of configuration update.
      */
-    boolean ensureVisibilityAndConfig(ActivityRecord starting, int displayId,
-            boolean markFrozenIfConfigChanged, boolean deferResume) {
+    boolean ensureVisibilityAndConfig(ActivityRecord starting, int displayId, boolean deferResume) {
         // First ensure visibility without updating the config just yet. We need this to know what
         // activities are affecting configuration now.
         // Passing null here for 'starting' param value, so that visibility of actual starting
@@ -1774,9 +1774,6 @@
         if (starting != null) {
             starting.reportDescendantOrientationChangeIfNeeded();
         }
-        if (starting != null && markFrozenIfConfigChanged && config != null) {
-            starting.frozenBeforeDestroy = true;
-        }
 
         if (displayContent != null) {
             // Update the configuration of the activities on the display.
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 56f9aa4..57939bc 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -340,7 +340,8 @@
 
     @Override
     public IBinder performDrag(IWindow window, int flags, SurfaceControl surface, int touchSource,
-            float touchX, float touchY, float thumbCenterX, float thumbCenterY, ClipData data) {
+            int touchDeviceId, int touchPointerId, float touchX, float touchY, float thumbCenterX,
+            float thumbCenterY, ClipData data) {
         final int callingUid = Binder.getCallingUid();
         final int callingPid = Binder.getCallingPid();
         // Validate and resolve ClipDescription data before clearing the calling identity
@@ -349,7 +350,8 @@
         final long ident = Binder.clearCallingIdentity();
         try {
             return mDragDropController.performDrag(mPid, mUid, window, flags, surface, touchSource,
-                    touchX, touchY, thumbCenterX, thumbCenterY, data);
+                    touchDeviceId, touchPointerId, touchX, touchY, thumbCenterX, thumbCenterY,
+                    data);
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
diff --git a/services/core/java/com/android/server/wm/SnapshotController.java b/services/core/java/com/android/server/wm/SnapshotController.java
index 01fa39b..b6f040a 100644
--- a/services/core/java/com/android/server/wm/SnapshotController.java
+++ b/services/core/java/com/android/server/wm/SnapshotController.java
@@ -25,6 +25,7 @@
 import static android.view.WindowManager.TRANSIT_TO_FRONT;
 
 import android.os.Trace;
+import android.util.ArrayMap;
 import android.view.WindowManager;
 import android.window.TaskSnapshot;
 
@@ -80,6 +81,7 @@
         if (!isTransitionOpen && !isTransitionClose && type < TRANSIT_FIRST_CUSTOM) {
             return;
         }
+        ActivitiesByTask activityTargets = null;
         for (int i = changeInfos.size() - 1; i >= 0; --i) {
             Transition.ChangeInfo info = changeInfos.get(i);
             // Intentionally skip record snapshot for changes originated from PiP.
@@ -98,14 +100,68 @@
                 final TaskFragment tf = info.mContainer.asTaskFragment();
                 final ActivityRecord ar = tf != null ? tf.getTopMostActivity()
                         : info.mContainer.asActivityRecord();
-                if (ar != null && !ar.isVisibleRequested() && ar.getTask().isVisibleRequested()) {
-                    final WindowState mainWindow = ar.findMainWindow(false);
-                    // Only capture activity snapshot if this app has adapted to back predict
-                    if (mainWindow != null
-                            && mainWindow.getOnBackInvokedCallbackInfo() != null
-                            && mainWindow.getOnBackInvokedCallbackInfo().isSystemCallback()) {
-                        mActivitySnapshotController.recordSnapshot(ar);
+                if (ar != null && ar.getTask().isVisibleRequested()) {
+                    if (activityTargets == null) {
+                        activityTargets = new ActivitiesByTask();
                     }
+                    activityTargets.put(ar);
+                }
+            }
+        }
+        if (activityTargets != null) {
+            activityTargets.recordSnapshot(mActivitySnapshotController);
+        }
+    }
+
+    private static class ActivitiesByTask {
+        final ArrayMap<Task, OpenCloseActivities> mActivitiesMap = new ArrayMap<>();
+
+        void put(ActivityRecord ar) {
+            OpenCloseActivities activities = mActivitiesMap.get(ar.getTask());
+            if (activities == null) {
+                activities = new OpenCloseActivities();
+                mActivitiesMap.put(ar.getTask(), activities);
+            }
+            activities.add(ar);
+        }
+
+        void recordSnapshot(ActivitySnapshotController controller) {
+            for (int i = mActivitiesMap.size() - 1; i >= 0; i--) {
+                final OpenCloseActivities pair = mActivitiesMap.valueAt(i);
+                pair.recordSnapshot(controller);
+            }
+        }
+
+        static class OpenCloseActivities {
+            final ArrayList<ActivityRecord> mOpenActivities = new ArrayList<>();
+            final ArrayList<ActivityRecord> mCloseActivities = new ArrayList<>();
+
+            void add(ActivityRecord ar) {
+                if (ar.isVisibleRequested()) {
+                    mOpenActivities.add(ar);
+                } else {
+                    mCloseActivities.add(ar);
+                }
+            }
+
+            boolean allOpensOptInOnBackInvoked() {
+                if (mOpenActivities.isEmpty()) {
+                    return false;
+                }
+                for (int i = mOpenActivities.size() - 1; i >= 0; --i) {
+                    if (!mOpenActivities.get(i).mOptInOnBackInvoked) {
+                        return false;
+                    }
+                }
+                return true;
+            }
+
+            void recordSnapshot(ActivitySnapshotController controller) {
+                if (!allOpensOptInOnBackInvoked() || mCloseActivities.isEmpty()) {
+                    return;
+                }
+                for (int i = mCloseActivities.size() - 1; i >= 0; --i) {
+                    controller.recordSnapshot(mCloseActivities.get(i));
                 }
             }
         }
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 5f08212..671acfc 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -5815,8 +5815,7 @@
             }
 
             mRootWindowContainer.ensureVisibilityAndConfig(null /* starting */,
-                    mDisplayContent.mDisplayId, false /* markFrozenIfConfigChanged */,
-                    false /* deferResume */);
+                    mDisplayContent.mDisplayId, false /* deferResume */);
         } finally {
             if (mTransitionController.isShellTransitionsEnabled()) {
                 mAtmService.continueWindowLayout();
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 39b4480..5d01912 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -73,6 +73,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityOptions;
+import android.app.IApplicationThread;
 import android.app.ResultInfo;
 import android.app.WindowConfiguration;
 import android.app.servertransaction.ActivityResultItem;
@@ -103,6 +104,7 @@
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.server.am.HostingRecord;
 import com.android.server.pm.pkg.AndroidPackage;
+import com.android.window.flags.Flags;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -1485,7 +1487,7 @@
                 // TODO: Remove this once visibilities are set correctly immediately when
                 // starting an activity.
                 notUpdated = !mRootWindowContainer.ensureVisibilityAndConfig(next, getDisplayId(),
-                        true /* markFrozenIfConfigChanged */, false /* deferResume */);
+                        false /* deferResume */);
             }
 
             if (notUpdated) {
@@ -1509,23 +1511,38 @@
             }
 
             try {
-                final ClientTransaction transaction = ClientTransaction.obtain(
-                        next.app.getThread());
+                final IApplicationThread appThread = next.app.getThread();
+                final ClientTransaction transaction = Flags.bundleClientTransactionFlag()
+                        ? null
+                        : ClientTransaction.obtain(appThread);
                 // Deliver all pending results.
-                ArrayList<ResultInfo> a = next.results;
+                final ArrayList<ResultInfo> a = next.results;
                 if (a != null) {
                     final int size = a.size();
                     if (!next.finishing && size > 0) {
                         if (DEBUG_RESULTS) {
                             Slog.v(TAG_RESULTS, "Delivering results to " + next + ": " + a);
                         }
-                        transaction.addCallback(ActivityResultItem.obtain(next.token, a));
+                        final ActivityResultItem activityResultItem = ActivityResultItem.obtain(
+                                next.token, a);
+                        if (transaction == null) {
+                            mAtmService.getLifecycleManager().scheduleTransactionItem(
+                                    appThread, activityResultItem);
+                        } else {
+                            transaction.addCallback(activityResultItem);
+                        }
                     }
                 }
 
                 if (next.newIntents != null) {
-                    transaction.addCallback(
-                            NewIntentItem.obtain(next.token, next.newIntents, true /* resume */));
+                    final NewIntentItem newIntentItem = NewIntentItem.obtain(
+                            next.token, next.newIntents, true /* resume */);
+                    if (transaction == null) {
+                        mAtmService.getLifecycleManager().scheduleTransactionItem(
+                                appThread, newIntentItem);
+                    } else {
+                        transaction.addCallback(newIntentItem);
+                    }
                 }
 
                 // Well the app will no longer be stopped.
@@ -1539,10 +1556,16 @@
                 final int topProcessState = mAtmService.mTopProcessState;
                 next.app.setPendingUiCleanAndForceProcessStateUpTo(topProcessState);
                 next.abortAndClearOptionsAnimation();
-                transaction.setLifecycleStateRequest(
-                        ResumeActivityItem.obtain(next.token, topProcessState,
-                                dc.isNextTransitionForward(), next.shouldSendCompatFakeFocus()));
-                mAtmService.getLifecycleManager().scheduleTransaction(transaction);
+                final ResumeActivityItem resumeActivityItem = ResumeActivityItem.obtain(
+                        next.token, topProcessState, dc.isNextTransitionForward(),
+                        next.shouldSendCompatFakeFocus());
+                if (transaction == null) {
+                    mAtmService.getLifecycleManager().scheduleTransactionItem(
+                            appThread, resumeActivityItem);
+                } else {
+                    transaction.setLifecycleStateRequest(resumeActivityItem);
+                    mAtmService.getLifecycleManager().scheduleTransaction(transaction);
+                }
 
                 ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Resumed %s", next);
             } catch (Exception e) {
@@ -1856,7 +1879,7 @@
             // In that case go ahead and remove the freeze this activity has on the screen
             // since it is no longer visible.
             if (prev != null) {
-                prev.stopFreezingScreenLocked(true /*force*/);
+                prev.stopFreezingScreen(true /* unfreezeNow */, true /* force */);
             }
             mPausingActivity = null;
         }
diff --git a/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java b/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java
index 7d22b74..ac244c7 100644
--- a/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java
+++ b/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java
@@ -45,6 +45,10 @@
 
     public TaskTapPointerEventListener(WindowManagerService service,
             DisplayContent displayContent) {
+        // TODO(b/315321016): Remove this class when the flag rollout is complete.
+        if (com.android.input.flags.Flags.removePointerEventTrackingInWm()) {
+            throw new IllegalStateException("TaskTapPointerEventListener should not be used!");
+        }
         mService = service;
         mDisplayContent = displayContent;
     }
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 76c4a0e..f020bfa 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -2868,8 +2868,7 @@
             final WindowContainer<?> wc = mParticipants.valueAt(i);
             final DisplayContent dc = wc.asDisplayContent();
             if (dc == null || !mChanges.get(dc).hasChanged()) continue;
-            final int originalSeq = dc.getConfiguration().seq;
-            dc.sendNewConfiguration();
+            final boolean changed = dc.sendNewConfiguration();
             // Set to ready if no other change controls the ready state. But if there is, such as
             // if an activity is pausing, it will call setReady(ar, false) and wait for the next
             // resumed activity. Then do not set to ready because the transition only contains
@@ -2877,7 +2876,7 @@
             if (!mReadyTrackerOld.mUsed) {
                 setReady(dc, true);
             }
-            if (originalSeq == dc.getConfiguration().seq) continue;
+            if (!changed) continue;
             // If the update is deferred, sendNewConfiguration won't deliver new configuration to
             // clients, then it is the caller's responsibility to deliver the changes.
             if (mController.mAtm.mTaskSupervisor.isRootVisibilityUpdateDeferred()) {
diff --git a/services/core/java/com/android/server/wm/TrustedPresentationListenerController.java b/services/core/java/com/android/server/wm/TrustedPresentationListenerController.java
new file mode 100644
index 0000000..1688a1a
--- /dev/null
+++ b/services/core/java/com/android/server/wm/TrustedPresentationListenerController.java
@@ -0,0 +1,448 @@
+/*
+ * 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 com.android.server.wm;
+
+import static android.graphics.Matrix.MSCALE_X;
+import static android.graphics.Matrix.MSCALE_Y;
+import static android.graphics.Matrix.MSKEW_X;
+import static android.graphics.Matrix.MSKEW_Y;
+
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_TPL;
+
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Region;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.IntArray;
+import android.util.Pair;
+import android.util.Size;
+import android.view.InputWindowHandle;
+import android.window.ITrustedPresentationListener;
+import android.window.TrustedPresentationThresholds;
+import android.window.WindowInfosListener;
+
+import com.android.internal.protolog.common.ProtoLog;
+import com.android.server.wm.utils.RegionUtils;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Optional;
+
+/**
+ * Class to handle TrustedPresentationListener registrations in a thread safe manner. This class
+ * also takes care of cleaning up listeners when the remote process dies.
+ */
+public class TrustedPresentationListenerController {
+
+    // Should only be accessed by the posting to the handler
+    private class Listeners {
+        private final class ListenerDeathRecipient implements IBinder.DeathRecipient {
+            IBinder mListenerBinder;
+            int mInstances;
+
+            ListenerDeathRecipient(IBinder listenerBinder) {
+                mListenerBinder = listenerBinder;
+                mInstances = 0;
+                try {
+                    mListenerBinder.linkToDeath(this, 0);
+                } catch (RemoteException ignore) {
+                }
+            }
+
+            void addInstance() {
+                mInstances++;
+            }
+
+            // return true if there are no instances alive
+            boolean removeInstance() {
+                mInstances--;
+                if (mInstances > 0) {
+                    return false;
+                }
+                mListenerBinder.unlinkToDeath(this, 0);
+                return true;
+            }
+
+            public void binderDied() {
+                mHandler.post(() -> {
+                    mUniqueListeners.remove(mListenerBinder);
+                    removeListeners(mListenerBinder, Optional.empty());
+                });
+            }
+        }
+
+        // tracks binder deaths for cleanup
+        ArrayMap<IBinder, ListenerDeathRecipient> mUniqueListeners = new ArrayMap<>();
+        ArrayMap<IBinder /*window*/, ArrayList<TrustedPresentationInfo>> mWindowToListeners =
+                new ArrayMap<>();
+
+        void register(IBinder window, ITrustedPresentationListener listener,
+                TrustedPresentationThresholds thresholds, int id) {
+            var listenersForWindow = mWindowToListeners.computeIfAbsent(window,
+                    iBinder -> new ArrayList<>());
+            listenersForWindow.add(new TrustedPresentationInfo(thresholds, id, listener));
+
+            // register death listener
+            var listenerBinder = listener.asBinder();
+            var deathRecipient = mUniqueListeners.computeIfAbsent(listenerBinder,
+                    ListenerDeathRecipient::new);
+            deathRecipient.addInstance();
+        }
+
+        void unregister(ITrustedPresentationListener trustedPresentationListener, int id) {
+            var listenerBinder = trustedPresentationListener.asBinder();
+            var deathRecipient = mUniqueListeners.get(listenerBinder);
+            if (deathRecipient == null) {
+                ProtoLog.e(WM_DEBUG_TPL, "unregister failed, couldn't find"
+                        + " deathRecipient for %s with id=%d", trustedPresentationListener, id);
+                return;
+            }
+
+            if (deathRecipient.removeInstance()) {
+                mUniqueListeners.remove(listenerBinder);
+            }
+            removeListeners(listenerBinder, Optional.of(id));
+        }
+
+        boolean isEmpty() {
+            return mWindowToListeners.isEmpty();
+        }
+
+        ArrayList<TrustedPresentationInfo> get(IBinder windowToken) {
+            return mWindowToListeners.get(windowToken);
+        }
+
+        private void removeListeners(IBinder listenerBinder, Optional<Integer> id) {
+            for (int i = mWindowToListeners.size() - 1; i >= 0; i--) {
+                var listeners = mWindowToListeners.valueAt(i);
+                for (int j = listeners.size() - 1; j >= 0; j--) {
+                    var listener = listeners.get(j);
+                    if (listener.mListener.asBinder() == listenerBinder && (id.isEmpty()
+                            || listener.mId == id.get())) {
+                        listeners.remove(j);
+                    }
+                }
+                if (listeners.isEmpty()) {
+                    mWindowToListeners.removeAt(i);
+                }
+            }
+        }
+    }
+
+    private final Object mHandlerThreadLock = new Object();
+    private HandlerThread mHandlerThread;
+    private Handler mHandler;
+
+    private WindowInfosListener mWindowInfosListener;
+
+    Listeners mRegisteredListeners = new Listeners();
+
+    private InputWindowHandle[] mLastWindowHandles;
+
+    private final Object mIgnoredWindowTokensLock = new Object();
+
+    private final ArraySet<IBinder> mIgnoredWindowTokens = new ArraySet<>();
+
+    private void startHandlerThreadIfNeeded() {
+        synchronized (mHandlerThreadLock) {
+            if (mHandler == null) {
+                mHandlerThread = new HandlerThread("WindowInfosListenerForTpl");
+                mHandlerThread.start();
+                mHandler = new Handler(mHandlerThread.getLooper());
+            }
+        }
+    }
+
+    void addIgnoredWindowTokens(IBinder token) {
+        synchronized (mIgnoredWindowTokensLock) {
+            mIgnoredWindowTokens.add(token);
+        }
+    }
+
+    void removeIgnoredWindowTokens(IBinder token) {
+        synchronized (mIgnoredWindowTokensLock) {
+            mIgnoredWindowTokens.remove(token);
+        }
+    }
+
+    void registerListener(IBinder window, ITrustedPresentationListener listener,
+            TrustedPresentationThresholds thresholds, int id) {
+        startHandlerThreadIfNeeded();
+        mHandler.post(() -> {
+            ProtoLog.d(WM_DEBUG_TPL, "Registering listener=%s with id=%d for window=%s with %s",
+                    listener, id, window, thresholds);
+
+            mRegisteredListeners.register(window, listener, thresholds, id);
+            registerWindowInfosListener();
+            // Update the initial state for the new registered listener
+            computeTpl(mLastWindowHandles);
+        });
+    }
+
+    void unregisterListener(ITrustedPresentationListener listener, int id) {
+        startHandlerThreadIfNeeded();
+        mHandler.post(() -> {
+            ProtoLog.d(WM_DEBUG_TPL, "Unregistering listener=%s with id=%d",
+                    listener, id);
+
+            mRegisteredListeners.unregister(listener, id);
+            if (mRegisteredListeners.isEmpty()) {
+                unregisterWindowInfosListener();
+            }
+        });
+    }
+
+    void dump(PrintWriter pw) {
+        final String innerPrefix = "  ";
+        pw.println("TrustedPresentationListenerController:");
+        pw.println(innerPrefix + "Active unique listeners ("
+                + mRegisteredListeners.mUniqueListeners.size() + "):");
+        for (int i = 0; i < mRegisteredListeners.mWindowToListeners.size(); i++) {
+            pw.println(
+                    innerPrefix + "  window=" + mRegisteredListeners.mWindowToListeners.keyAt(i));
+            final var listeners = mRegisteredListeners.mWindowToListeners.valueAt(i);
+            for (int j = 0; j < listeners.size(); j++) {
+                final var listener = listeners.get(j);
+                pw.println(innerPrefix + innerPrefix + "  listener=" + listener.mListener.asBinder()
+                        + " id=" + listener.mId
+                        + " thresholds=" + listener.mThresholds);
+            }
+        }
+    }
+
+    private void registerWindowInfosListener() {
+        if (mWindowInfosListener != null) {
+            return;
+        }
+
+        mWindowInfosListener = new WindowInfosListener() {
+            @Override
+            public void onWindowInfosChanged(InputWindowHandle[] windowHandles,
+                    DisplayInfo[] displayInfos) {
+                mHandler.post(() -> computeTpl(windowHandles));
+            }
+        };
+        mLastWindowHandles = mWindowInfosListener.register().first;
+    }
+
+    private void unregisterWindowInfosListener() {
+        if (mWindowInfosListener == null) {
+            return;
+        }
+
+        mWindowInfosListener.unregister();
+        mWindowInfosListener = null;
+        mLastWindowHandles = null;
+    }
+
+    private void computeTpl(InputWindowHandle[] windowHandles) {
+        mLastWindowHandles = windowHandles;
+        if (mLastWindowHandles == null || mLastWindowHandles.length == 0
+                || mRegisteredListeners.isEmpty()) {
+            return;
+        }
+
+        Rect tmpRect = new Rect();
+        Matrix tmpInverseMatrix = new Matrix();
+        float[] tmpMatrix = new float[9];
+        Region coveredRegionsAbove = new Region();
+        long currTimeMs = System.currentTimeMillis();
+        ProtoLog.v(WM_DEBUG_TPL, "Checking %d windows", mLastWindowHandles.length);
+
+        ArrayMap<ITrustedPresentationListener, Pair<IntArray, IntArray>> listenerUpdates =
+                new ArrayMap<>();
+        ArraySet<IBinder> ignoredWindowTokens;
+        synchronized (mIgnoredWindowTokensLock) {
+            ignoredWindowTokens = new ArraySet<>(mIgnoredWindowTokens);
+        }
+        for (var windowHandle : mLastWindowHandles) {
+            if (ignoredWindowTokens.contains(windowHandle.getWindowToken())) {
+                ProtoLog.v(WM_DEBUG_TPL, "Skipping %s", windowHandle.name);
+                continue;
+            }
+            tmpRect.set(windowHandle.frame);
+            var listeners = mRegisteredListeners.get(windowHandle.getWindowToken());
+            if (listeners != null) {
+                Region region = new Region();
+                region.op(tmpRect, coveredRegionsAbove, Region.Op.DIFFERENCE);
+                windowHandle.transform.invert(tmpInverseMatrix);
+                tmpInverseMatrix.getValues(tmpMatrix);
+                float scaleX = (float) Math.sqrt(tmpMatrix[MSCALE_X] * tmpMatrix[MSCALE_X]
+                        + tmpMatrix[MSKEW_X] * tmpMatrix[MSKEW_X]);
+                float scaleY = (float) Math.sqrt(tmpMatrix[MSCALE_Y] * tmpMatrix[MSCALE_Y]
+                        + tmpMatrix[MSKEW_Y] * tmpMatrix[MSKEW_Y]);
+
+                float fractionRendered = computeFractionRendered(region, new RectF(tmpRect),
+                        windowHandle.contentSize,
+                        scaleX, scaleY);
+
+                checkIfInThreshold(listeners, listenerUpdates, fractionRendered, windowHandle.alpha,
+                        currTimeMs);
+            }
+
+            coveredRegionsAbove.op(tmpRect, Region.Op.UNION);
+            ProtoLog.v(WM_DEBUG_TPL, "coveredRegionsAbove updated with %s frame:%s region:%s",
+                    windowHandle.name, tmpRect.toShortString(), coveredRegionsAbove);
+        }
+
+        for (int i = 0; i < listenerUpdates.size(); i++) {
+            var updates = listenerUpdates.valueAt(i);
+            var listener = listenerUpdates.keyAt(i);
+            try {
+                listener.onTrustedPresentationChanged(updates.first.toArray(),
+                        updates.second.toArray());
+            } catch (RemoteException ignore) {
+            }
+        }
+    }
+
+    private void addListenerUpdate(
+            ArrayMap<ITrustedPresentationListener, Pair<IntArray, IntArray>> listenerUpdates,
+            ITrustedPresentationListener listener, int id, boolean presentationState) {
+        var updates = listenerUpdates.get(listener);
+        if (updates == null) {
+            updates = new Pair<>(new IntArray(), new IntArray());
+            listenerUpdates.put(listener, updates);
+        }
+        if (presentationState) {
+            updates.first.add(id);
+        } else {
+            updates.second.add(id);
+        }
+    }
+
+
+    private void checkIfInThreshold(
+            ArrayList<TrustedPresentationInfo> listeners,
+            ArrayMap<ITrustedPresentationListener, Pair<IntArray, IntArray>> listenerUpdates,
+            float fractionRendered, float alpha, long currTimeMs) {
+        ProtoLog.v(WM_DEBUG_TPL, "checkIfInThreshold fractionRendered=%f alpha=%f currTimeMs=%d",
+                fractionRendered, alpha, currTimeMs);
+        for (int i = 0; i < listeners.size(); i++) {
+            var trustedPresentationInfo = listeners.get(i);
+            var listener = trustedPresentationInfo.mListener;
+            boolean lastState = trustedPresentationInfo.mLastComputedTrustedPresentationState;
+            boolean newState =
+                    (alpha >= trustedPresentationInfo.mThresholds.minAlpha) && (fractionRendered
+                            >= trustedPresentationInfo.mThresholds.minFractionRendered);
+            trustedPresentationInfo.mLastComputedTrustedPresentationState = newState;
+
+            ProtoLog.v(WM_DEBUG_TPL,
+                    "lastState=%s newState=%s alpha=%f minAlpha=%f fractionRendered=%f "
+                            + "minFractionRendered=%f",
+                    lastState, newState, alpha, trustedPresentationInfo.mThresholds.minAlpha,
+                    fractionRendered, trustedPresentationInfo.mThresholds.minFractionRendered);
+
+            if (lastState && !newState) {
+                // We were in the trusted presentation state, but now we left it,
+                // emit the callback if needed
+                if (trustedPresentationInfo.mLastReportedTrustedPresentationState) {
+                    trustedPresentationInfo.mLastReportedTrustedPresentationState = false;
+                    addListenerUpdate(listenerUpdates, listener,
+                            trustedPresentationInfo.mId, /*presentationState*/ false);
+                    ProtoLog.d(WM_DEBUG_TPL, "Adding untrusted state listener=%s with id=%d",
+                            listener, trustedPresentationInfo.mId);
+                }
+                // Reset the timer
+                trustedPresentationInfo.mEnteredTrustedPresentationStateTime = -1;
+            } else if (!lastState && newState) {
+                // We were not in the trusted presentation state, but we entered it, begin the timer
+                // and make sure this gets called at least once more!
+                trustedPresentationInfo.mEnteredTrustedPresentationStateTime = currTimeMs;
+                mHandler.postDelayed(() -> {
+                    computeTpl(mLastWindowHandles);
+                }, (long) (trustedPresentationInfo.mThresholds.stabilityRequirementMs * 1.5));
+            }
+
+            // Has the timer elapsed, but we are still in the state? Emit a callback if needed
+            if (!trustedPresentationInfo.mLastReportedTrustedPresentationState && newState && (
+                    currTimeMs - trustedPresentationInfo.mEnteredTrustedPresentationStateTime
+                            > trustedPresentationInfo.mThresholds.stabilityRequirementMs)) {
+                trustedPresentationInfo.mLastReportedTrustedPresentationState = true;
+                addListenerUpdate(listenerUpdates, listener,
+                        trustedPresentationInfo.mId, /*presentationState*/ true);
+                ProtoLog.d(WM_DEBUG_TPL, "Adding trusted state listener=%s with id=%d",
+                        listener, trustedPresentationInfo.mId);
+            }
+        }
+    }
+
+    private float computeFractionRendered(Region visibleRegion, RectF screenBounds,
+            Size contentSize,
+            float sx, float sy) {
+        ProtoLog.v(WM_DEBUG_TPL,
+                "computeFractionRendered: visibleRegion=%s screenBounds=%s contentSize=%s "
+                        + "scale=%f,%f",
+                visibleRegion, screenBounds, contentSize, sx, sy);
+
+        if (contentSize.getWidth() == 0 || contentSize.getHeight() == 0) {
+            return -1;
+        }
+        if (screenBounds.width() == 0 || screenBounds.height() == 0) {
+            return -1;
+        }
+
+        float fractionRendered = Math.min(sx * sy, 1.0f);
+        ProtoLog.v(WM_DEBUG_TPL, "fractionRendered scale=%f", fractionRendered);
+
+        float boundsOverSourceW = screenBounds.width() / (float) contentSize.getWidth();
+        float boundsOverSourceH = screenBounds.height() / (float) contentSize.getHeight();
+        fractionRendered *= boundsOverSourceW * boundsOverSourceH;
+        ProtoLog.v(WM_DEBUG_TPL, "fractionRendered boundsOverSource=%f", fractionRendered);
+        // Compute the size of all the rects since they may be disconnected.
+        float[] visibleSize = new float[1];
+        RegionUtils.forEachRect(visibleRegion, rect -> {
+            float size = rect.width() * rect.height();
+            visibleSize[0] += size;
+        });
+
+        fractionRendered *= visibleSize[0] / (screenBounds.width() * screenBounds.height());
+        return fractionRendered;
+    }
+
+    private static class TrustedPresentationInfo {
+        boolean mLastComputedTrustedPresentationState = false;
+        boolean mLastReportedTrustedPresentationState = false;
+        long mEnteredTrustedPresentationStateTime = -1;
+        final TrustedPresentationThresholds mThresholds;
+
+        final ITrustedPresentationListener mListener;
+        final int mId;
+
+        private TrustedPresentationInfo(TrustedPresentationThresholds thresholds, int id,
+                ITrustedPresentationListener listener) {
+            mThresholds = thresholds;
+            mId = id;
+            mListener = listener;
+            checkValid(thresholds);
+        }
+
+        private void checkValid(TrustedPresentationThresholds thresholds) {
+            if (thresholds.minAlpha <= 0 || thresholds.minFractionRendered <= 0
+                    || thresholds.stabilityRequirementMs < 1) {
+                throw new IllegalArgumentException(
+                        "TrustedPresentationThresholds values are invalid");
+            }
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index 808a11d..516d37c 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -866,6 +866,11 @@
     public abstract ImeTargetInfo onToggleImeRequested(boolean show,
             @NonNull IBinder focusedToken, @NonNull IBinder requestToken, int displayId);
 
+    /**
+     * Returns the token to identify the target window that the IME is associated with.
+     */
+    public abstract @Nullable IBinder getTargetWindowTokenFromInputToken(IBinder inputToken);
+
     /** The information of input method target when IME is requested to show or hide. */
     public static class ImeTargetInfo {
         public final String focusedWindowName;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 0d2c94d..2125c63 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -303,9 +303,11 @@
 import android.window.ClientWindowFrames;
 import android.window.ISurfaceSyncGroupCompletedListener;
 import android.window.ITaskFpsCallback;
+import android.window.ITrustedPresentationListener;
 import android.window.ScreenCapture;
 import android.window.SystemPerformanceHinter;
 import android.window.TaskSnapshot;
+import android.window.TrustedPresentationThresholds;
 import android.window.WindowContainerToken;
 import android.window.WindowContextInfo;
 
@@ -764,6 +766,9 @@
     private final SurfaceSyncGroupController mSurfaceSyncGroupController =
             new SurfaceSyncGroupController();
 
+    final TrustedPresentationListenerController mTrustedPresentationListenerController =
+            new TrustedPresentationListenerController();
+
     @VisibleForTesting
     final class SettingsObserver extends ContentObserver {
         private final Uri mDisplayInversionEnabledUri =
@@ -7076,7 +7081,7 @@
                 return;
             } else if ("containers".equals(cmd)) {
                 synchronized (mGlobalLock) {
-                    mRoot.dumpChildrenNames(pw, " ");
+                    mRoot.dumpChildrenNames(pw, "");
                     pw.println(" ");
                     mRoot.forAllWindows(w -> {pw.println(w);}, true /* traverseTopToBottom */);
                 }
@@ -7171,6 +7176,7 @@
                 pw.println(separator);
             }
             mSystemPerformanceHinter.dump(pw, "");
+            mTrustedPresentationListenerController.dump(pw);
         }
     }
 
@@ -7302,7 +7308,12 @@
         }
     }
 
-    MousePositionTracker mMousePositionTracker = new MousePositionTracker();
+    // The mouse position tracker will be obsolete after the Pointer Icon Refactor.
+    // TODO(b/293587049): Remove after the refactoring is fully rolled out.
+    @Nullable
+    final MousePositionTracker mMousePositionTracker =
+            com.android.input.flags.Flags.enablePointerChoreographer() ? null
+                    : new MousePositionTracker();
 
     private static class MousePositionTracker implements PointerEventListener {
         private boolean mLatestEventWasMouse;
@@ -7354,6 +7365,9 @@
     };
 
     void updatePointerIcon(IWindow client) {
+        if (mMousePositionTracker == null) {
+            return;
+        }
         int pointerDisplayId;
         float mouseX, mouseY;
 
@@ -7400,6 +7414,9 @@
     }
 
     void restorePointerIconLocked(DisplayContent displayContent, float latestX, float latestY) {
+        if (mMousePositionTracker == null) {
+            return;
+        }
         // Mouse position tracker has not been getting updates while dragging, update it now.
         if (!mMousePositionTracker.updatePosition(
                 displayContent.getDisplayId(), latestX, latestY)) {
@@ -7423,6 +7440,9 @@
         }
     }
     void setMousePointerDisplayId(int displayId) {
+        if (mMousePositionTracker == null) {
+            return;
+        }
         mMousePositionTracker.setPointerDisplayId(displayId);
     }
 
@@ -8532,6 +8552,12 @@
                         fromOrientations, toOrientations);
             }
         }
+
+        @Override
+        public @Nullable IBinder getTargetWindowTokenFromInputToken(IBinder inputToken) {
+            InputTarget inputTarget = WindowManagerService.this.getInputTargetFromToken(inputToken);
+            return inputTarget == null ? null : inputTarget.getWindowToken();
+        }
     }
 
     private final class ImeTargetVisibilityPolicyImpl extends ImeTargetVisibilityPolicy {
@@ -9771,4 +9797,17 @@
             Binder.restoreCallingIdentity(origId);
         }
     }
+
+    @Override
+    public void registerTrustedPresentationListener(IBinder window,
+            ITrustedPresentationListener listener,
+            TrustedPresentationThresholds thresholds, int id) {
+        mTrustedPresentationListenerController.registerListener(window, listener, thresholds, id);
+    }
+
+    @Override
+    public void unregisterTrustedPresentationListener(ITrustedPresentationListener listener,
+            int id) {
+        mTrustedPresentationListenerController.unregisterListener(listener, id);
+    }
 }
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index a872fd0..4b99432 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -63,6 +63,7 @@
 import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_START_SHORTCUT;
 
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER;
+import static com.android.server.wm.ActivityRecord.State.PAUSING;
 import static com.android.server.wm.ActivityTaskManagerService.enforceTaskPermission;
 import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
 import static com.android.server.wm.ActivityTaskSupervisor.REMOVE_FROM_RECENTS;
@@ -1178,6 +1179,14 @@
                 mService.mRootWindowContainer.moveActivityToPinnedRootTask(
                         pipActivity, null /* launchIntoPipHostActivity */,
                         "moveActivityToPinnedRootTask", null /* transition */, entryBounds);
+
+                // Continue the pausing process after potential task reparenting.
+                if (pipActivity.isState(PAUSING) && pipActivity.mPauseSchedulePendingForPip) {
+                    pipActivity.getTask().schedulePauseActivity(
+                            pipActivity, false /* userLeaving */,
+                            false /* pauseImmediately */, true /* autoEnteringPip */, "auto-pip");
+                }
+
                 effects |= TRANSACT_EFFECTS_LIFECYCLE;
                 break;
             }
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 2b18f07..5721750 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -66,6 +66,7 @@
 import android.content.res.Configuration;
 import android.os.Binder;
 import android.os.Build;
+import android.os.DeadObjectException;
 import android.os.FactoryTest;
 import android.os.LocaleList;
 import android.os.Message;
@@ -915,7 +916,7 @@
             int i = mActivities.size();
             while (i > 0) {
                 i--;
-                mActivities.get(i).stopFreezingScreenLocked(true);
+                mActivities.get(i).stopFreezingScreen(true /* unfreezeNow */, true /* force */);
             }
         }
     }
@@ -1675,6 +1676,10 @@
             @NonNull ClientTransactionItem transactionItem) {
         try {
             mAtm.getLifecycleManager().scheduleTransactionItem(thread, transactionItem);
+        } catch (DeadObjectException e) {
+            // Expected if the process has been killed.
+            Slog.w(TAG_CONFIGURATION, "Failed for dead process. ClientTransactionItem="
+                    + transactionItem + " owner=" + mOwner);
         } catch (Exception e) {
             Slog.e(TAG_CONFIGURATION, "Failed to schedule ClientTransactionItem="
                     + transactionItem + " owner=" + mOwner, e);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index e1f1f66..4e9d23c 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -178,6 +178,7 @@
 import static com.android.server.wm.WindowStateProto.VIEW_VISIBILITY;
 import static com.android.server.wm.WindowStateProto.WINDOW_CONTAINER;
 import static com.android.server.wm.WindowStateProto.WINDOW_FRAMES;
+import static com.android.window.flags.Flags.explicitRefreshRateHints;
 import static com.android.window.flags.Flags.secureWindowState;
 import static com.android.window.flags.Flags.surfaceTrustedOverlay;
 
@@ -668,6 +669,12 @@
     boolean mSeamlesslyRotated = false;
 
     /**
+     * Whether the IME insets have been consumed. If {@code true}, this window won't be able to
+     * receive visible IME insets; {@code false}, otherwise.
+     */
+    boolean mImeInsetsConsumed = false;
+
+    /**
      * The insets state of sources provided by windows above the current window.
      */
     final InsetsState mAboveInsetsState = new InsetsState();
@@ -1189,6 +1196,11 @@
             ProtoLog.v(WM_DEBUG_ADD_REMOVE, "Adding %s to %s", this, parentWindow);
             parentWindow.addChild(this, sWindowSubLayerComparator);
         }
+
+        if (token.mRoundedCornerOverlay) {
+            mWmService.mTrustedPresentationListenerController.addIgnoredWindowTokens(
+                    getWindowToken());
+        }
     }
 
     @Override
@@ -1487,7 +1499,9 @@
 
             if (insetsChanged) {
                 mWindowFrames.setInsetsChanged(false);
-                mWmService.mWindowsInsetsChanged--;
+                if (mWmService.mWindowsInsetsChanged > 0) {
+                    mWmService.mWindowsInsetsChanged--;
+                }
                 if (mWmService.mWindowsInsetsChanged == 0) {
                     mWmService.mH.removeMessages(WindowManagerService.H.INSETS_CHANGED);
                 }
@@ -2393,6 +2407,9 @@
         }
 
         mWmService.postWindowRemoveCleanupLocked(this);
+
+        mWmService.mTrustedPresentationListenerController.removeIgnoredWindowTokens(
+                getWindowToken());
     }
 
     @Override
@@ -3796,13 +3813,15 @@
      */
     void notifyInsetsChanged() {
         ProtoLog.d(WM_DEBUG_WINDOW_INSETS, "notifyInsetsChanged for %s ", this);
-        mWindowFrames.setInsetsChanged(true);
+        if (!mWindowFrames.hasInsetsChanged()) {
+            mWindowFrames.setInsetsChanged(true);
 
-        // If the new InsetsState won't be dispatched before releasing WM lock, the following
-        // message will be executed.
-        mWmService.mWindowsInsetsChanged++;
-        mWmService.mH.removeMessages(WindowManagerService.H.INSETS_CHANGED);
-        mWmService.mH.sendEmptyMessage(WindowManagerService.H.INSETS_CHANGED);
+            // If the new InsetsState won't be dispatched before releasing WM lock, the following
+            // message will be executed.
+            mWmService.mWindowsInsetsChanged++;
+            mWmService.mH.removeMessages(WindowManagerService.H.INSETS_CHANGED);
+            mWmService.mH.sendEmptyMessage(WindowManagerService.H.INSETS_CHANGED);
+        }
 
         final WindowContainer p = getParent();
         if (p != null) {
@@ -4192,6 +4211,7 @@
         } else {
             pw.print("null");
         }
+        pw.println();
 
         if (mXOffset != 0 || mYOffset != 0) {
             pw.println(prefix + "mXOffset=" + mXOffset + " mYOffset=" + mYOffset);
@@ -4225,6 +4245,9 @@
         if (computeDragResizing()) {
             pw.println(prefix + "computeDragResizing=" + computeDragResizing());
         }
+        if (mImeInsetsConsumed) {
+            pw.println(prefix + "mImeInsetsConsumed=true");
+        }
         pw.println(prefix + "isOnScreen=" + isOnScreen());
         pw.println(prefix + "isVisible=" + isVisible());
         pw.println(prefix + "keepClearAreas: restricted=" + mKeepClearAreas
@@ -5185,9 +5208,13 @@
 
         boolean voteChanged = refreshRatePolicy.updateFrameRateVote(this);
         if (voteChanged) {
-            getPendingTransaction().setFrameRate(
-                    mSurfaceControl, mFrameRateVote.mRefreshRate,
-                    mFrameRateVote.mCompatibility, Surface.CHANGE_FRAME_RATE_ALWAYS);
+            getPendingTransaction()
+                    .setFrameRate(mSurfaceControl, mFrameRateVote.mRefreshRate,
+                        mFrameRateVote.mCompatibility, Surface.CHANGE_FRAME_RATE_ALWAYS);
+            if (explicitRefreshRateHints()) {
+                getPendingTransaction().setFrameRateSelectionStrategy(mSurfaceControl,
+                        mFrameRateVote.mSelectionStrategy);
+            }
 
         }
     }
@@ -5622,9 +5649,10 @@
         if (mKeyInterceptionInfo == null
                 || mKeyInterceptionInfo.layoutParamsPrivateFlags != getAttrs().privateFlags
                 || mKeyInterceptionInfo.layoutParamsType != getAttrs().type
-                || mKeyInterceptionInfo.windowTitle != getWindowTag()) {
+                || mKeyInterceptionInfo.windowTitle != getWindowTag()
+                || mKeyInterceptionInfo.windowOwnerUid != getOwningUid()) {
             mKeyInterceptionInfo = new KeyInterceptionInfo(getAttrs().type, getAttrs().privateFlags,
-                    getWindowTag().toString());
+                    getWindowTag().toString(), getOwningUid());
         }
         return mKeyInterceptionInfo;
     }
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index aa58902..dff718a 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -210,6 +210,10 @@
         return mInLayout;
     }
 
+    boolean isTraversalScheduled() {
+        return mTraversalScheduled;
+    }
+
     void requestTraversal() {
         if (mTraversalScheduled) {
             return;
diff --git a/services/core/java/com/android/server/wm/utils/DisplayInfoOverrides.java b/services/core/java/com/android/server/wm/utils/DisplayInfoOverrides.java
index 8c8f6a6..193a0c8 100644
--- a/services/core/java/com/android/server/wm/utils/DisplayInfoOverrides.java
+++ b/services/core/java/com/android/server/wm/utils/DisplayInfoOverrides.java
@@ -30,7 +30,7 @@
      * Set of DisplayInfo fields that are overridden in DisplayManager using values from
      * WindowManager
      */
-    public static final DisplayInfoFields WM_OVERRIDE_FIELDS = (out, source) -> {
+    public static final DisplayInfoFieldsUpdater WM_OVERRIDE_FIELDS = (out, source) -> {
         out.appWidth = source.appWidth;
         out.appHeight = source.appHeight;
         out.smallestNominalAppWidth = source.smallestNominalAppWidth;
@@ -55,7 +55,7 @@
     public static void copyDisplayInfoFields(@NonNull DisplayInfo out,
             @NonNull DisplayInfo base,
             @Nullable DisplayInfo override,
-            @NonNull DisplayInfoFields fields) {
+            @NonNull DisplayInfoFieldsUpdater fields) {
         out.copyFrom(base);
 
         if (override != null) {
@@ -66,7 +66,7 @@
     /**
      * Callback interface that allows to specify a subset of fields of DisplayInfo object
      */
-    public interface DisplayInfoFields {
+    public interface DisplayInfoFieldsUpdater {
         /**
          * Copies a subset of fields from {@param source} to {@param out}
          *
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 24ee163..c34e701 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -37,6 +37,7 @@
         "com_android_server_adb_AdbDebuggingManager.cpp",
         "com_android_server_am_BatteryStatsService.cpp",
         "com_android_server_biometrics_SurfaceToNativeHandleConverter.cpp",
+        "com_android_server_BootReceiver.cpp",
         "com_android_server_ConsumerIrService.cpp",
         "com_android_server_companion_virtual_InputController.cpp",
         "com_android_server_devicepolicy_CryptoTestHelper.cpp",
@@ -93,6 +94,16 @@
     header_libs: [
         "bionic_libc_platform_headers",
     ],
+
+    static_libs: [
+        "libunwindstack",
+    ],
+
+    whole_static_libs: [
+        "libdebuggerd_tombstone_proto_to_text",
+    ],
+
+    runtime_libs: ["libdexfile"],
 }
 
 cc_defaults {
@@ -187,7 +198,7 @@
         "android.hardware.power.stats@1.0",
         "android.hardware.power.stats-V1-ndk",
         "android.hardware.thermal@1.0",
-        "android.hardware.thermal-V1-ndk",
+        "android.hardware.thermal-V2-ndk",
         "android.hardware.tv.input@1.0",
         "android.hardware.tv.input-V2-ndk",
         "android.hardware.vibrator-V2-cpp",
diff --git a/services/core/jni/OWNERS b/services/core/jni/OWNERS
index 0e45f61..0d762dfb 100644
--- a/services/core/jni/OWNERS
+++ b/services/core/jni/OWNERS
@@ -30,3 +30,7 @@
 per-file com_android_server_vibrator_* = file:/services/core/java/com/android/server/vibrator/OWNERS
 per-file com_android_server_am_CachedAppOptimizer.cpp = timmurray@google.com, edgararriaga@google.com, dualli@google.com, carmenjackson@google.com, philipcuadra@google.com
 per-file com_android_server_companion_virtual_InputController.cpp = file:/services/companion/java/com/android/server/companion/virtual/OWNERS
+
+# Bug component : 158088 = per-file com_android_server_utils_AnrTimer*.java
+per-file com_android_server_utils_AnrTimer*.java = file:/PERFORMANCE_OWNERS
+per-file com_android_server_BootReceiver.cpp = file:/STABILITY_OWNERS
diff --git a/services/core/jni/com_android_server_BootReceiver.cpp b/services/core/jni/com_android_server_BootReceiver.cpp
new file mode 100644
index 0000000..3892d28
--- /dev/null
+++ b/services/core/jni/com_android_server_BootReceiver.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libdebuggerd/tombstone.h>
+#include <nativehelper/JNIHelp.h>
+
+#include <sstream>
+
+#include "jni.h"
+#include "tombstone.pb.h"
+
+namespace android {
+
+static void writeToString(std::stringstream& ss, const std::string& line, bool should_log) {
+    ss << line << std::endl;
+}
+
+static jstring com_android_server_BootReceiver_getTombstoneText(JNIEnv* env, jobject,
+                                                                jbyteArray tombstoneBytes) {
+    Tombstone tombstone;
+    tombstone.ParseFromArray(env->GetByteArrayElements(tombstoneBytes, 0),
+                             env->GetArrayLength(tombstoneBytes));
+
+    std::stringstream tombstoneString;
+
+    tombstone_proto_to_text(tombstone,
+                            std::bind(&writeToString, std::ref(tombstoneString),
+                                      std::placeholders::_1, std::placeholders::_2));
+
+    return env->NewStringUTF(tombstoneString.str().c_str());
+}
+
+static const JNINativeMethod sMethods[] = {
+        /* name, signature, funcPtr */
+        {"getTombstoneText", "([B)Ljava/lang/String;",
+         (jstring*)com_android_server_BootReceiver_getTombstoneText},
+};
+
+int register_com_android_server_BootReceiver(JNIEnv* env) {
+    return jniRegisterNativeMethods(env, "com/android/server/BootReceiver", sMethods,
+                                    NELEM(sMethods));
+}
+
+} // namespace android
diff --git a/services/core/jni/com_android_server_app_GameManagerService.cpp b/services/core/jni/com_android_server_app_GameManagerService.cpp
index 3028813..f593f40 100644
--- a/services/core/jni/com_android_server_app_GameManagerService.cpp
+++ b/services/core/jni/com_android_server_app_GameManagerService.cpp
@@ -25,15 +25,21 @@
 
 namespace android {
 
-static void android_server_app_GameManagerService_nativeSetOverrideFrameRate(JNIEnv* env,
-                                                                             jclass clazz, jint uid,
-                                                                             jfloat frameRate) {
-    SurfaceComposerClient::setOverrideFrameRate(uid, frameRate);
+static void android_server_app_GameManagerService_nativeSetGameModeFrameRateOverride(
+        JNIEnv* env, jclass clazz, jint uid, jfloat frameRate) {
+    SurfaceComposerClient::setGameModeFrameRateOverride(uid, frameRate);
+}
+
+static void android_server_app_GameManagerService_nativeSetGameDefaultFrameRateOverride(
+        JNIEnv* env, jclass clazz, jint uid, jfloat frameRate) {
+    SurfaceComposerClient::setGameDefaultFrameRateOverride(uid, frameRate);
 }
 
 static const JNINativeMethod gMethods[] = {
-        {"nativeSetOverrideFrameRate", "(IF)V",
-         (void*)android_server_app_GameManagerService_nativeSetOverrideFrameRate},
+        {"nativeSetGameModeFrameRateOverride", "(IF)V",
+         (void*)android_server_app_GameManagerService_nativeSetGameModeFrameRateOverride},
+        {"nativeSetGameDefaultFrameRateOverride", "(IF)V",
+         (void*)android_server_app_GameManagerService_nativeSetGameDefaultFrameRateOverride},
 };
 
 int register_android_server_app_GameManagerService(JNIEnv* env) {
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 6f65965..0dd0564 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -88,6 +88,7 @@
 namespace android {
 
 static const bool ENABLE_POINTER_CHOREOGRAPHER = input_flags::enable_pointer_choreographer();
+static const bool ENABLE_INPUT_FILTER_RUST = input_flags::enable_input_filter_rust_impl();
 
 // The exponent used to calculate the pointer speed scaling factor.
 // The scaling factor is calculated as 2 ^ (speed * exponent),
@@ -2737,6 +2738,23 @@
     im->setStylusPointerIconEnabled(enabled);
 }
 
+static void nativeSetAccessibilityBounceKeysThreshold(JNIEnv* env, jobject nativeImplObj,
+                                                      jint thresholdTimeMs) {
+    NativeInputManager* im = getNativeInputManager(env, nativeImplObj);
+    if (ENABLE_INPUT_FILTER_RUST) {
+        im->getInputManager()->getInputFilter().setAccessibilityBounceKeysThreshold(
+                static_cast<nsecs_t>(thresholdTimeMs) * 1000000);
+    }
+}
+
+static void nativeSetAccessibilityStickyKeysEnabled(JNIEnv* env, jobject nativeImplObj,
+                                                    jboolean enabled) {
+    NativeInputManager* im = getNativeInputManager(env, nativeImplObj);
+    if (ENABLE_INPUT_FILTER_RUST) {
+        im->getInputManager()->getInputFilter().setAccessibilityStickyKeysEnabled(enabled);
+    }
+}
+
 // ----------------------------------------------------------------------------
 
 static const JNINativeMethod gInputManagerMethods[] = {
@@ -2836,6 +2854,10 @@
          (void*)nativeSetStylusButtonMotionEventsEnabled},
         {"getMouseCursorPosition", "()[F", (void*)nativeGetMouseCursorPosition},
         {"setStylusPointerIconEnabled", "(Z)V", (void*)nativeSetStylusPointerIconEnabled},
+        {"setAccessibilityBounceKeysThreshold", "(I)V",
+         (void*)nativeSetAccessibilityBounceKeysThreshold},
+        {"setAccessibilityStickyKeysEnabled", "(Z)V",
+         (void*)nativeSetAccessibilityStickyKeysEnabled},
 };
 
 #define FIND_CLASS(var, className) \
diff --git a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
index 3d4f866..2a0f1e2 100644
--- a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
+++ b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
@@ -182,7 +182,7 @@
 
     auto block_count = 1 + (fileSize - 1) / INCFS_DATA_FILE_BLOCK_SIZE;
     auto hash_block_count = block_count;
-    for (auto i = 0; hash_block_count > 1; i++) {
+    while (hash_block_count > 1) {
         hash_block_count = (hash_block_count + hash_per_block - 1) / hash_per_block;
         total_tree_block_count += hash_block_count;
     }
@@ -468,7 +468,6 @@
                      borrowed_fd incomingFd, bool waitOnEof, std::vector<char>* buffer,
                      std::vector<IncFsDataBlock>* blocks) {
         IncFsSize remaining = size;
-        IncFsSize totalSize = 0;
         IncFsBlockIndex blockIdx = 0;
         while (remaining > 0) {
             constexpr auto capacity = BUFFER_SIZE;
@@ -502,7 +501,6 @@
 
             buffer->resize(size + read);
             remaining -= read;
-            totalSize += read;
         }
         if (!buffer->empty() && !flashToIncFs(incfsFd, kind, true, &blockIdx, buffer, blocks)) {
             return false;
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index 11734da..deae82c 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -65,6 +65,7 @@
 int register_android_server_sensor_SensorService(JavaVM* vm, JNIEnv* env);
 int register_android_server_companion_virtual_InputController(JNIEnv* env);
 int register_android_server_app_GameManagerService(JNIEnv* env);
+int register_com_android_server_BootReceiver(JNIEnv* env);
 int register_com_android_server_wm_TaskFpsCallbackController(JNIEnv* env);
 int register_com_android_server_display_DisplayControl(JNIEnv* env);
 int register_com_android_server_SystemClockTime(JNIEnv* env);
@@ -126,6 +127,7 @@
     register_android_server_sensor_SensorService(vm, env);
     register_android_server_companion_virtual_InputController(env);
     register_android_server_app_GameManagerService(env);
+    register_com_android_server_BootReceiver(env);
     register_com_android_server_wm_TaskFpsCallbackController(env);
     register_com_android_server_display_DisplayControl(env);
     register_com_android_server_SystemClockTime(env);
diff --git a/services/foldables/devicestateprovider/src/com/android/server/policy/feature/device_state_flags.aconfig b/services/foldables/devicestateprovider/src/com/android/server/policy/feature/device_state_flags.aconfig
index 47c2a1b..29e258c 100644
--- a/services/foldables/devicestateprovider/src/com/android/server/policy/feature/device_state_flags.aconfig
+++ b/services/foldables/devicestateprovider/src/com/android/server/policy/feature/device_state_flags.aconfig
@@ -5,4 +5,12 @@
     namespace: "display_manager"
     description: "Feature flag for dual display blocking"
     bug: "278667199"
+}
+
+flag {
+    name: "enable_foldables_posture_based_closed_state"
+    namespace: "windowing_frontend"
+    description: "Enables smarter closed device state state for foldable devices"
+    bug: "309792734"
+    is_fixed_read_only: true
 }
\ No newline at end of file
diff --git a/services/manifest_services.xml b/services/manifest_services.xml
index e2fdfe9..eae159f 100644
--- a/services/manifest_services.xml
+++ b/services/manifest_services.xml
@@ -7,11 +7,6 @@
     <hal format="aidl">
         <name>android.frameworks.vibrator</name>
         <version>1</version>
-        <fqname>IVibratorController/default</fqname>
-    </hal>
-    <hal format="aidl">
-        <name>android.frameworks.vibrator</name>
-        <version>1</version>
         <fqname>IVibratorControlService/default</fqname>
     </hal>
 </manifest>
diff --git a/services/midi/java/com/android/server/midi/MidiService.java b/services/midi/java/com/android/server/midi/MidiService.java
index 39aaab2..a212812 100644
--- a/services/midi/java/com/android/server/midi/MidiService.java
+++ b/services/midi/java/com/android/server/midi/MidiService.java
@@ -31,6 +31,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.Property;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.res.Resources;
@@ -1396,16 +1397,20 @@
         XmlResourceParser parser = null;
 
         try {
-            parser = serviceInfo.loadXmlMetaData(mPackageManager,
-                    MidiDeviceService.SERVICE_INTERFACE);
-            if (parser == null) return;
+            if (serviceInfo == null) {
+                Log.w(TAG, "Skipping null service info");
+                return;
+            }
 
             // ignore virtual device servers that do not require the correct permission
             if (!android.Manifest.permission.BIND_MIDI_DEVICE_SERVICE.equals(
                     serviceInfo.permission)) {
-                Log.w(TAG, "Skipping MIDI device service " + serviceInfo.packageName
-                        + ": it does not require the permission "
-                        + android.Manifest.permission.BIND_MIDI_DEVICE_SERVICE);
+                return;
+            }
+            parser = serviceInfo.loadXmlMetaData(mPackageManager,
+                    MidiDeviceService.SERVICE_INTERFACE);
+            if (parser == null) {
+                Log.w(TAG, "loading xml metadata failed");
                 return;
             }
 
@@ -1533,21 +1538,14 @@
         XmlResourceParser parser = null;
 
         try {
-            ComponentName componentName = new ComponentName(serviceInfo.packageName,
-                    serviceInfo.name);
-            int resId = mPackageManager.getProperty(MidiUmpDeviceService.SERVICE_INTERFACE,
-                    componentName).getResourceId();
-            Resources resources = mPackageManager.getResourcesForApplication(
-                    serviceInfo.packageName);
-            parser = resources.getXml(resId);
-            if (parser == null) return;
+            if (serviceInfo == null) {
+                Log.w(TAG, "Skipping null service info");
+                return;
+            }
 
             // ignore virtual device servers that do not require the correct permission
             if (!android.Manifest.permission.BIND_MIDI_DEVICE_SERVICE.equals(
                     serviceInfo.permission)) {
-                Log.w(TAG, "Skipping MIDI device service " + serviceInfo.packageName
-                        + ": it does not require the permission "
-                        + android.Manifest.permission.BIND_MIDI_DEVICE_SERVICE);
                 return;
             }
 
@@ -1557,6 +1555,31 @@
                 return;
             }
 
+            ComponentName componentName = new ComponentName(serviceInfo.packageName,
+                    serviceInfo.name);
+            Property property = mPackageManager.getProperty(MidiUmpDeviceService.SERVICE_INTERFACE,
+                    componentName);
+            if (property == null) {
+                Log.w(TAG, "Getting MidiUmpDeviceService property failed");
+                return;
+            }
+            int resId = property.getResourceId();
+            if (resId == 0) {
+                Log.w(TAG, "Getting MidiUmpDeviceService resourceId failed");
+                return;
+            }
+            Resources resources = mPackageManager.getResourcesForApplication(
+                    serviceInfo.packageName);
+            if (resources == null) {
+                Log.w(TAG, "Getting resource failed " + serviceInfo.packageName);
+                return;
+            }
+            parser = resources.getXml(resId);
+            if (parser == null) {
+                Log.w(TAG, "Getting XML failed " + resId);
+                return;
+            }
+
             Bundle properties = null;
             int numPorts = 0;
             boolean isPrivate = false;
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 02032c7..f69f628 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
@@ -24,6 +24,7 @@
 import android.os.Build
 import android.util.Slog
 import com.android.internal.os.RoSystemProperties
+import com.android.internal.pm.permission.CompatibilityPermissionInfo
 import com.android.modules.utils.BinaryXmlPullParser
 import com.android.modules.utils.BinaryXmlSerializer
 import com.android.server.permission.access.AccessState
@@ -42,7 +43,6 @@
 import com.android.server.permission.access.util.isInternal
 import com.android.server.pm.KnownPackages
 import com.android.server.pm.parsing.PackageInfoUtils
-import com.android.server.pm.permission.CompatibilityPermissionInfo
 import com.android.server.pm.pkg.AndroidPackage
 import com.android.server.pm.pkg.PackageState
 
diff --git a/services/permission/java/com/android/server/permission/access/permission/DevicePermissionPolicy.kt b/services/permission/java/com/android/server/permission/access/permission/DevicePermissionPolicy.kt
index bb68bc5..a0fb013 100644
--- a/services/permission/java/com/android/server/permission/access/permission/DevicePermissionPolicy.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/DevicePermissionPolicy.kt
@@ -16,9 +16,7 @@
 
 package com.android.server.permission.access.permission
 
-import android.Manifest
 import android.permission.PermissionManager
-import android.permission.flags.Flags
 import android.util.Slog
 import com.android.modules.utils.BinaryXmlPullParser
 import com.android.modules.utils.BinaryXmlSerializer
@@ -61,6 +59,35 @@
         }
     }
 
+    fun MutateStateScope.trimDevicePermissionStates(deviceIds: Set<String>) {
+        newState.userStates.forEachIndexed { _, userId, userState ->
+            userState.appIdDevicePermissionFlags.forEachReversedIndexed { _, appId, _ ->
+                val appIdDevicePermissionFlags =
+                    newState.mutateUserState(userId)!!.mutateAppIdDevicePermissionFlags()
+                val devicePermissionFlags =
+                    appIdDevicePermissionFlags.mutate(appId) ?: return@forEachReversedIndexed
+
+                devicePermissionFlags.forEachReversedIndexed { _, deviceId, _ ->
+                    if (deviceId !in deviceIds) {
+                        devicePermissionFlags -= deviceId
+                    }
+                }
+            }
+        }
+    }
+
+    fun MutateStateScope.onDeviceIdRemoved(deviceId: String) {
+        newState.userStates.forEachIndexed { _, userId, userState ->
+            userState.appIdDevicePermissionFlags.forEachReversedIndexed { _, appId, _ ->
+                val appIdDevicePermissionFlags =
+                    newState.mutateUserState(userId)!!.mutateAppIdDevicePermissionFlags()
+                val devicePermissionFlags =
+                    appIdDevicePermissionFlags.mutate(appId) ?: return@forEachReversedIndexed
+                devicePermissionFlags -= deviceId
+            }
+        }
+    }
+
     override fun MutateStateScope.onStorageVolumeMounted(
         volumeUuid: String?,
         packageNames: List<String>,
@@ -90,6 +117,10 @@
         resetRuntimePermissions(packageName, userId)
     }
 
+    /**
+     * Reset permission states for all permissions requested by the given package, if no other
+     * package (sharing the App ID) request these permissions.
+     */
     fun MutateStateScope.resetRuntimePermissions(packageName: String, userId: Int) {
         // It's okay to skip resetting permissions for packages that are removed,
         // because their states will be trimmed in onPackageRemoved()/onAppIdRemoved()
@@ -112,6 +143,7 @@
         }
     }
 
+    // Trims permission state for permissions not requested by the App ID anymore.
     private fun MutateStateScope.trimPermissionStates(appId: Int) {
         val requestedPermissions = MutableIndexedSet<String>()
         forEachPackageInAppId(appId) {
@@ -213,10 +245,6 @@
         flagMask: Int,
         flagValues: Int
     ): Boolean {
-        if (!isDeviceAwarePermission(permissionName)) {
-            Slog.w(LOG_TAG, "$permissionName is not a device aware permission.")
-            return false
-        }
         val oldFlags =
             newState.userStates[userId]!!
                 .appIdDevicePermissionFlags[appId]
@@ -263,20 +291,8 @@
         synchronized(listenersLock) { listeners = listeners + listener }
     }
 
-    private fun isDeviceAwarePermission(permissionName: String): Boolean =
-        DEVICE_AWARE_PERMISSIONS.contains(permissionName)
-
     companion object {
         private val LOG_TAG = DevicePermissionPolicy::class.java.simpleName
-
-        /** These permissions are supported for virtual devices. */
-        // TODO: b/298661870 - Use new API to get the list of device aware permissions.
-        val DEVICE_AWARE_PERMISSIONS =
-            if (Flags.deviceAwarePermissionApis()) {
-                setOf(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO)
-            } else {
-                emptySet<String>()
-            }
     }
 
     /** Listener for permission flags changes. */
diff --git a/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt b/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
index 7c53950..f469ab5 100644
--- a/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
@@ -1551,10 +1551,11 @@
         permissionName: String,
         deviceId: Int,
     ): Int {
-        return if (!Flags.deviceAwarePermissionApis() || deviceId == Context.DEVICE_ID_DEFAULT) {
+        return if (!Flags.deviceAwarePermissionApisEnabled() ||
+            deviceId == Context.DEVICE_ID_DEFAULT) {
             with(policy) { getPermissionFlags(appId, userId, permissionName) }
         } else {
-            if (permissionName !in DevicePermissionPolicy.DEVICE_AWARE_PERMISSIONS) {
+            if (permissionName !in DEVICE_AWARE_PERMISSIONS) {
                 Slog.i(
                     LOG_TAG,
                     "$permissionName is not device aware permission, " +
@@ -1586,10 +1587,11 @@
         deviceId: Int,
         flags: Int
     ): Boolean {
-        return if (!Flags.deviceAwarePermissionApis() || deviceId == Context.DEVICE_ID_DEFAULT) {
+        return if (!Flags.deviceAwarePermissionApisEnabled() ||
+            deviceId == Context.DEVICE_ID_DEFAULT) {
             with(policy) { setPermissionFlags(appId, userId, permissionName, flags) }
         } else {
-            if (permissionName !in DevicePermissionPolicy.DEVICE_AWARE_PERMISSIONS) {
+            if (permissionName !in DEVICE_AWARE_PERMISSIONS) {
                 Slog.i(
                     LOG_TAG,
                     "$permissionName is not device aware permission, " +
@@ -2312,8 +2314,19 @@
 
     override fun onSystemReady() {
         service.onSystemReady()
+
         virtualDeviceManagerInternal =
             LocalServices.getService(VirtualDeviceManagerInternal::class.java)
+        virtualDeviceManagerInternal?.allPersistentDeviceIds?.let { persistentDeviceIds ->
+            service.mutateState {
+                with(devicePolicy) { trimDevicePermissionStates(persistentDeviceIds) }
+            }
+        }
+        virtualDeviceManagerInternal?.registerPersistentDeviceIdRemovedListener { persistentDeviceId
+            ->
+            service.mutateState { with(devicePolicy) { onDeviceIdRemoved(persistentDeviceId) } }
+        }
+
         permissionControllerManager =
             PermissionControllerManager(context, PermissionThread.getHandler())
     }
@@ -2681,8 +2694,8 @@
                         permissionName in NOTIFICATIONS_PERMISSIONS &&
                             runtimePermissionRevokedUids.get(uid, true)
                 }
-                runtimePermissionChangedUidDevices
-                    .getOrPut(uid) { mutableSetOf() } += persistentDeviceId
+                runtimePermissionChangedUidDevices.getOrPut(uid) { mutableSetOf() } +=
+                    persistentDeviceId
             }
 
             if (permission.hasGids && !wasPermissionGranted && isPermissionGranted) {
@@ -2799,8 +2812,7 @@
 
         fun onPermissionsChanged(uid: Int, persistentDeviceId: String) {
             if (listeners.registeredCallbackCount > 0) {
-                obtainMessage(MSG_ON_PERMISSIONS_CHANGED, uid, 0, persistentDeviceId)
-                    .sendToTarget()
+                obtainMessage(MSG_ON_PERMISSIONS_CHANGED, uid, 0, persistentDeviceId).sendToTarget()
             }
         }
 
@@ -2849,5 +2861,14 @@
             PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE or
                 PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM or
                 PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER
+
+        /** These permissions are supported for virtual devices. */
+        // TODO: b/298661870 - Use new API to get the list of device aware permissions.
+        val DEVICE_AWARE_PERMISSIONS =
+            if (Flags.deviceAwarePermissionApisEnabled()) {
+                setOf(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO)
+            } else {
+                emptySet<String>()
+            }
     }
 }
diff --git a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
index d62da1a..5b222c0 100644
--- a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
+++ b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
@@ -57,11 +57,11 @@
 
 import androidx.test.core.app.ApplicationProvider;
 
+import com.android.internal.pm.parsing.pkg.PackageImpl;
 import com.android.internal.pm.parsing.pkg.ParsedPackage;
 import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
 import com.android.internal.util.FunctionalUtils.ThrowingSupplier;
 import com.android.server.LocalServices;
-import com.android.server.pm.parsing.pkg.PackageImpl;
 import com.android.server.pm.pkg.AndroidPackage;
 import com.android.server.testing.shadows.ShadowApplicationPackageManager;
 import com.android.server.testing.shadows.ShadowUserManager;
diff --git a/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt b/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
index 3011fa1..5c4716d 100644
--- a/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
+++ b/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
@@ -25,6 +25,7 @@
 import android.os.UserHandle
 import android.util.ArrayMap
 import com.android.internal.pm.parsing.pkg.AndroidPackageInternal
+import com.android.internal.pm.parsing.pkg.PackageImpl
 import com.android.internal.pm.parsing.pkg.ParsedPackage
 import com.android.internal.pm.pkg.component.ParsedActivity
 import com.android.server.pm.AppsFilterImpl
@@ -38,7 +39,6 @@
 import com.android.server.pm.SharedLibrariesImpl
 import com.android.server.pm.UserManagerInternal
 import com.android.server.pm.UserManagerService
-import com.android.server.pm.parsing.pkg.PackageImpl
 import com.android.server.pm.pkg.AndroidPackage
 import com.android.server.pm.resolution.ComponentResolver
 import com.android.server.pm.snapshot.PackageDataSnapshot
@@ -49,6 +49,8 @@
 import com.android.server.testutils.whenever
 import com.android.server.wm.ActivityTaskManagerInternal
 import com.google.common.truth.Truth.assertThat
+import java.io.File
+import java.util.UUID
 import org.junit.After
 import org.junit.Before
 import org.junit.BeforeClass
@@ -61,8 +63,6 @@
 import org.mockito.Mockito.intThat
 import org.mockito.Mockito.same
 import org.testng.Assert.assertThrows
-import java.io.File
-import java.util.UUID
 
 @RunWith(Parameterized::class)
 class PackageManagerComponentLabelIconOverrideTest {
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/AppsFilterImplTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/AppsFilterImplTest.java
index 3461bb6..7277fd7 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/AppsFilterImplTest.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/AppsFilterImplTest.java
@@ -49,20 +49,20 @@
 
 import androidx.annotation.NonNull;
 
+import com.android.internal.pm.parsing.pkg.PackageImpl;
 import com.android.internal.pm.parsing.pkg.ParsedPackage;
 import com.android.internal.pm.pkg.component.ParsedActivity;
+import com.android.internal.pm.pkg.component.ParsedActivityImpl;
+import com.android.internal.pm.pkg.component.ParsedComponentImpl;
+import com.android.internal.pm.pkg.component.ParsedInstrumentationImpl;
+import com.android.internal.pm.pkg.component.ParsedIntentInfoImpl;
 import com.android.internal.pm.pkg.component.ParsedPermission;
+import com.android.internal.pm.pkg.component.ParsedPermissionImpl;
+import com.android.internal.pm.pkg.component.ParsedProviderImpl;
+import com.android.internal.pm.pkg.component.ParsedUsesPermissionImpl;
 import com.android.internal.pm.pkg.parsing.ParsingPackage;
 import com.android.server.om.OverlayReferenceMapper;
-import com.android.server.pm.parsing.pkg.PackageImpl;
 import com.android.server.pm.pkg.AndroidPackage;
-import com.android.server.pm.pkg.component.ParsedActivityImpl;
-import com.android.server.pm.pkg.component.ParsedComponentImpl;
-import com.android.server.pm.pkg.component.ParsedInstrumentationImpl;
-import com.android.server.pm.pkg.component.ParsedIntentInfoImpl;
-import com.android.server.pm.pkg.component.ParsedPermissionImpl;
-import com.android.server.pm.pkg.component.ParsedProviderImpl;
-import com.android.server.pm.pkg.component.ParsedUsesPermissionImpl;
 import com.android.server.utils.WatchableTester;
 
 import org.junit.Before;
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/CompatibilityModeTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/CompatibilityModeTest.java
index f0d389b..b1c3e94 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/CompatibilityModeTest.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/CompatibilityModeTest.java
@@ -32,11 +32,11 @@
 import android.os.Build;
 import android.platform.test.annotations.Presubmit;
 
+import com.android.internal.pm.parsing.pkg.PackageImpl;
+import com.android.internal.pm.pkg.parsing.ParsingPackageUtils;
 import com.android.server.pm.parsing.PackageInfoUtils;
-import com.android.server.pm.parsing.pkg.PackageImpl;
 import com.android.server.pm.pkg.PackageStateUnserialized;
 import com.android.server.pm.pkg.PackageUserStateImpl;
-import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java
index a0dc2b6..3d0b389 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -45,7 +45,9 @@
 import android.app.PropertyInvalidatedCache;
 import android.content.ComponentName;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.Flags;
 import android.content.pm.PackageManager;
+import android.content.pm.SharedLibraryInfo;
 import android.content.pm.SuspendDialogInfo;
 import android.content.pm.UserInfo;
 import android.os.BaseBundle;
@@ -54,6 +56,7 @@
 import android.os.Process;
 import android.os.UserHandle;
 import android.platform.test.annotations.Presubmit;
+import android.platform.test.flag.junit.SetFlagsRule;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.AtomicFile;
@@ -63,10 +66,11 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.internal.pm.parsing.pkg.PackageImpl;
 import com.android.internal.pm.parsing.pkg.ParsedPackage;
 import com.android.permission.persistence.RuntimePermissionsPersistence;
 import com.android.server.LocalServices;
-import com.android.server.pm.parsing.pkg.PackageImpl;
+import com.android.server.pm.parsing.PackageInfoUtils;
 import com.android.server.pm.permission.LegacyPermissionDataProvider;
 import com.android.server.pm.pkg.AndroidPackage;
 import com.android.server.pm.pkg.ArchiveState;
@@ -85,6 +89,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -109,6 +114,9 @@
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class PackageManagerSettingsTests {
+
+    @Rule
+    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
     private static final String PACKAGE_NAME_1 = "com.android.app1";
     private static final String PACKAGE_NAME_2 = "com.android.app2";
     private static final String PACKAGE_NAME_3 = "com.android.app3";
@@ -140,6 +148,7 @@
     public void setup() {
         // Disable binder caches in this process.
         PropertyInvalidatedCache.disableForTestMode();
+
     }
 
     @Before
@@ -161,6 +170,107 @@
         deleteFolder(InstrumentationRegistry.getContext().getFilesDir());
     }
 
+    @Test
+    public void testApplicationInfoForUseSdkOptionalEnabled() throws Exception {
+        mSetFlagsRule.enableFlags(Flags.FLAG_SDK_LIB_INDEPENDENCE);
+
+        // Create basic information for SDK lib
+        final PackageSetting ps1 = createPackageSetting(PACKAGE_NAME_1);
+        ps1.setPkg(((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME_1).hideAsParsed())
+                .setUid(ps1.getAppId())
+                .setSystem(true)
+                .hideAsFinal());
+        ps1.setUsesSdkLibraries(new String[] { "com.example.sdk.one" });
+        ps1.setUsesSdkLibrariesVersionsMajor(new long[] { 12 });
+        ps1.setUsesSdkLibrariesOptional(new boolean[] {true});
+        ps1.addUsesLibraryInfo(new SharedLibraryInfo("path1",
+                "packageName1",
+                Collections.emptyList(),
+                "com.example.sdk.one",
+                12 /*version*/,
+                SharedLibraryInfo.TYPE_SDK_PACKAGE,
+                null /*declaringPackage*/,
+                null /*dependentPackages*/,
+                null /*dependencies*/,
+                false /*isNative*/));
+        ps1.addUsesLibraryInfo(new SharedLibraryInfo("path11",
+                "packageName11",
+                Collections.emptyList(),
+                "com.example.sdk.oneone",
+                1212 /*version*/,
+                SharedLibraryInfo.TYPE_STATIC,
+                null /*declaringPackage*/,
+                null /*dependentPackages*/,
+                null /*dependencies*/,
+                false /*isNative*/));
+        ApplicationInfo appInfo1 = PackageInfoUtils.generateApplicationInfo(ps1.getAndroidPackage(),
+                0 /*flags*/, ps1.getUserStateOrDefault(0), 0 /*userId*/,
+                ps1);
+        assertThat(appInfo1, notNullValue());
+        assertThat(appInfo1.sharedLibraryInfos, notNullValue());
+        assertThat(appInfo1.optionalSharedLibraryInfos, notNullValue());
+        assertEquals(appInfo1.sharedLibraryInfos.get(0).getName(), "com.example.sdk.one");
+        assertEquals(appInfo1.optionalSharedLibraryInfos.get(0).getName(), "com.example.sdk.one");
+
+        final PackageSetting ps2 = createPackageSetting(PACKAGE_NAME_2);
+        ps2.setPkg(((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME_2).hideAsParsed())
+                .setUid(ps2.getAppId())
+                .setSystem(true)
+                .hideAsFinal());
+        ps2.setUsesSdkLibraries(new String[] { "com.example.sdk.two" });
+        ps2.setUsesSdkLibrariesVersionsMajor(new long[] { 34 });
+        ps2.setUsesSdkLibrariesOptional(new boolean[] {false});
+        ps2.addUsesLibraryInfo(new SharedLibraryInfo("path2",
+                "packageName2",
+                Collections.emptyList(),
+                "com.example.sdk.two",
+                34 /*version*/,
+                SharedLibraryInfo.TYPE_SDK_PACKAGE,
+                null /*declaringPackage*/,
+                null /*dependentPackages*/,
+                null /*dependencies*/,
+                false /*isNative*/));
+        ApplicationInfo appInfo2 = PackageInfoUtils.generateApplicationInfo(ps2.getAndroidPackage(),
+                0 /*flags*/, ps2.getUserStateOrDefault(0), 0 /*userId*/,
+                ps2);
+        assertThat(appInfo2, notNullValue());
+        assertThat(appInfo2.sharedLibraryInfos, notNullValue());
+        assertThat(appInfo2.optionalSharedLibraryInfos, nullValue());
+        assertEquals(appInfo2.sharedLibraryInfos.get(0).getName(), "com.example.sdk.two");
+    }
+
+    @Test
+    public void testApplicationInfoForUseSdkOptionalDisabled() throws Exception {
+        mSetFlagsRule.disableFlags(Flags.FLAG_SDK_LIB_INDEPENDENCE);
+
+        // Create basic information for SDK lib
+        final PackageSetting ps1 = createPackageSetting(PACKAGE_NAME_1);
+        ps1.setPkg(((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME_1).hideAsParsed())
+                .setUid(ps1.getAppId())
+                .setSystem(true)
+                .hideAsFinal());
+        ps1.setUsesSdkLibraries(new String[] { "com.example.sdk.one" });
+        ps1.setUsesSdkLibrariesVersionsMajor(new long[] { 12 });
+        ps1.setUsesSdkLibrariesOptional(new boolean[] {true});
+        ps1.addUsesLibraryInfo(new SharedLibraryInfo("path1",
+                "packageName1",
+                Collections.emptyList(),
+                "com.example.sdk.one",
+                12 /*version*/,
+                SharedLibraryInfo.TYPE_SDK_PACKAGE,
+                null /*declaringPackage*/,
+                null /*dependentPackages*/,
+                null /*dependencies*/,
+                false /*isNative*/));
+        ApplicationInfo appInfo1 = PackageInfoUtils.generateApplicationInfo(ps1.getAndroidPackage(),
+                0 /*flags*/, ps1.getUserStateOrDefault(0), 0 /*userId*/,
+                ps1);
+        assertThat(appInfo1, notNullValue());
+        assertThat(appInfo1.sharedLibraryInfos, notNullValue());
+        assertThat(appInfo1.optionalSharedLibraryInfos, nullValue());
+        assertEquals(appInfo1.sharedLibraryInfos.get(0).getName(), "com.example.sdk.one");
+    }
+
     /** make sure our initialized KeySetManagerService metadata matches packages.xml */
     @Test
     public void testReadKeySetSettings() throws Exception {
@@ -817,12 +927,14 @@
 
         ps1.setUsesSdkLibraries(new String[] { "com.example.sdk.one" });
         ps1.setUsesSdkLibrariesVersionsMajor(new long[] { 12 });
+        ps1.setUsesSdkLibrariesOptional(new boolean[] {true});
         ps1.setFlags(ps1.getFlags() | ApplicationInfo.FLAG_SYSTEM);
         settingsUnderTest.mPackages.put(PACKAGE_NAME_1, ps1);
         assertThat(settingsUnderTest.disableSystemPackageLPw(PACKAGE_NAME_1, false), is(true));
 
         ps2.setUsesSdkLibraries(new String[] { "com.example.sdk.two" });
         ps2.setUsesSdkLibrariesVersionsMajor(new long[] { 34 });
+        ps2.setUsesSdkLibrariesOptional(new boolean[] {false});
         settingsUnderTest.mPackages.put(PACKAGE_NAME_2, ps2);
 
         settingsUnderTest.writeLPr(computer, /*sync=*/true);
@@ -838,19 +950,30 @@
         Truth.assertThat(readPs1).isNotNull();
         Truth.assertThat(readPs1.getUsesSdkLibraries()).isNotNull();
         Truth.assertThat(readPs1.getUsesSdkLibrariesVersionsMajor()).isNotNull();
+        Truth.assertThat(readPs1.getUsesSdkLibrariesOptional()).isNotNull();
         Truth.assertThat(readPs2).isNotNull();
         Truth.assertThat(readPs2.getUsesSdkLibraries()).isNotNull();
         Truth.assertThat(readPs2.getUsesSdkLibrariesVersionsMajor()).isNotNull();
+        Truth.assertThat(readPs2.getUsesSdkLibrariesOptional()).isNotNull();
 
         List<Long> ps1VersionsAsList = new ArrayList<>();
         for (long version : ps1.getUsesSdkLibrariesVersionsMajor()) {
             ps1VersionsAsList.add(version);
         }
 
+        List<Boolean> ps1RequireAsList = new ArrayList<>();
+        for (boolean optional : ps1.getUsesSdkLibrariesOptional()) {
+            ps1RequireAsList.add(optional);
+        }
+
         List<Long> ps2VersionsAsList = new ArrayList<>();
         for (long version : ps2.getUsesSdkLibrariesVersionsMajor()) {
             ps2VersionsAsList.add(version);
         }
+        List<Boolean> ps2RequireAsList = new ArrayList<>();
+        for (boolean optional : ps2.getUsesSdkLibrariesOptional()) {
+            ps2RequireAsList.add(optional);
+        }
 
         Truth.assertThat(readPs1.getUsesSdkLibraries()).asList()
                 .containsExactlyElementsIn(ps1.getUsesSdkLibraries()).inOrder();
@@ -858,11 +981,17 @@
         Truth.assertThat(readPs1.getUsesSdkLibrariesVersionsMajor()).asList()
                 .containsExactlyElementsIn(ps1VersionsAsList).inOrder();
 
+        Truth.assertThat(readPs1.getUsesSdkLibrariesOptional()).asList()
+                .containsExactlyElementsIn(ps1RequireAsList).inOrder();
+
         Truth.assertThat(readPs2.getUsesSdkLibraries()).asList()
                 .containsExactlyElementsIn(ps2.getUsesSdkLibraries()).inOrder();
 
         Truth.assertThat(readPs2.getUsesSdkLibrariesVersionsMajor()).asList()
                 .containsExactlyElementsIn(ps2VersionsAsList).inOrder();
+
+        Truth.assertThat(readPs2.getUsesSdkLibrariesOptional()).asList()
+                .containsExactlyElementsIn(ps2RequireAsList).inOrder();
     }
 
     @Test
@@ -1047,6 +1176,7 @@
                 UserManagerService.getInstance(),
                 null /*usesSdkLibraries*/,
                 null /*usesSdkLibrariesVersions*/,
+                null /*usesSdkLibrariesOptional*/,
                 null /*usesStaticLibraries*/,
                 null /*usesStaticLibrariesVersions*/,
                 null /*mimeGroups*/,
@@ -1087,6 +1217,7 @@
                 UserManagerService.getInstance(),
                 null /*usesSdkLibraries*/,
                 null /*usesSdkLibrariesVersions*/,
+                null /*usesSdkLibrariesOptional*/,
                 null /*usesStaticLibraries*/,
                 null /*usesStaticLibrariesVersions*/,
                 null /*mimeGroups*/,
@@ -1129,6 +1260,7 @@
                     UserManagerService.getInstance(),
                     null /*usesSdkLibraries*/,
                     null /*usesSdkLibrariesVersions*/,
+                    null /*usesSdkLibrariesOptional*/,
                     null /*usesStaticLibraries*/,
                     null /*usesStaticLibrariesVersions*/,
                     null /*mimeGroups*/,
@@ -1167,6 +1299,7 @@
                 UserManagerService.getInstance(),
                 null /*usesSdkLibraries*/,
                 null /*usesSdkLibrariesVersions*/,
+                null /*usesSdkLibrariesOptional*/,
                 null /*usesStaticLibraries*/,
                 null /*usesStaticLibrariesVersions*/,
                 null /*mimeGroups*/,
@@ -1214,6 +1347,7 @@
                 UserManagerService.getInstance(),
                 null /*usesSdkLibraries*/,
                 null /*usesSdkLibrariesVersions*/,
+                null /*usesSdkLibrariesOptional*/,
                 null /*usesStaticLibraries*/,
                 null /*usesStaticLibrariesVersions*/,
                 null /*mimeGroups*/,
@@ -1263,6 +1397,7 @@
                 null /*usesSdkLibrariesVersions*/,
                 null /*usesStaticLibraries*/,
                 null /*usesStaticLibrariesVersions*/,
+                null /*usesSdkLibrariesOptional*/,
                 null /*mimeGroups*/,
                 UUID.randomUUID(),
                 34 /*targetSdkVersion*/,
@@ -1311,6 +1446,7 @@
                 null /*usesSdkLibrariesVersions*/,
                 null /*usesStaticLibraries*/,
                 null /*usesStaticLibrariesVersions*/,
+                null /*usesSdkLibrariesOptional*/,
                 null /*mimeGroups*/,
                 UUID.randomUUID(),
                 34 /*targetSdkVersion*/,
@@ -1356,6 +1492,7 @@
                 null /*usesSdkLibrariesVersions*/,
                 null /*usesStaticLibraries*/,
                 null /*usesStaticLibrariesVersions*/,
+                null /*usesSdkLibrariesOptional*/,
                 null /*mimeGroups*/,
                 UUID.randomUUID(),
                 34 /*targetSdkVersion*/,
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerTests.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerTests.java
index 9c48af8..285c059 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerTests.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerTests.java
@@ -73,7 +73,7 @@
 import com.android.compatibility.common.util.CddTest;
 import com.android.internal.content.InstallLocationUtils;
 import com.android.internal.pm.parsing.pkg.ParsedPackage;
-import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
+import com.android.server.pm.parsing.ParsingUtils;
 import com.android.server.pm.test.service.server.R;
 
 import dalvik.system.VMRuntime;
@@ -346,7 +346,7 @@
 
     private ParsedPackage parsePackage(Uri packageURI) {
         final String archiveFilePath = packageURI.getPath();
-        ParseResult<ParsedPackage> result = ParsingPackageUtils.parseDefaultOneTime(
+        ParseResult<ParsedPackage> result = ParsingUtils.parseDefaultOneTime(
                 new File(archiveFilePath), 0 /*flags*/, Collections.emptyList(),
                 false /*collectCertificates*/);
         if (result.isError()) {
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageParserTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageParserTest.java
index ea88ec2..03e45a2 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageParserTest.java
@@ -15,7 +15,7 @@
  */
 package com.android.server.pm;
 
-import static com.android.server.pm.permission.CompatibilityPermissionInfo.COMPAT_PERMS;
+import static com.android.internal.pm.permission.CompatibilityPermissionInfo.COMPAT_PERMS;
 
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
@@ -58,17 +58,28 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.internal.pm.parsing.pkg.PackageImpl;
 import com.android.internal.pm.parsing.pkg.ParsedPackage;
+import com.android.internal.pm.permission.CompatibilityPermissionInfo;
 import com.android.internal.pm.pkg.component.ParsedActivity;
+import com.android.internal.pm.pkg.component.ParsedActivityImpl;
 import com.android.internal.pm.pkg.component.ParsedApexSystemService;
 import com.android.internal.pm.pkg.component.ParsedComponent;
 import com.android.internal.pm.pkg.component.ParsedInstrumentation;
+import com.android.internal.pm.pkg.component.ParsedInstrumentationImpl;
 import com.android.internal.pm.pkg.component.ParsedIntentInfo;
+import com.android.internal.pm.pkg.component.ParsedIntentInfoImpl;
 import com.android.internal.pm.pkg.component.ParsedPermission;
 import com.android.internal.pm.pkg.component.ParsedPermissionGroup;
+import com.android.internal.pm.pkg.component.ParsedPermissionGroupImpl;
+import com.android.internal.pm.pkg.component.ParsedPermissionImpl;
+import com.android.internal.pm.pkg.component.ParsedPermissionUtils;
 import com.android.internal.pm.pkg.component.ParsedProvider;
+import com.android.internal.pm.pkg.component.ParsedProviderImpl;
 import com.android.internal.pm.pkg.component.ParsedService;
+import com.android.internal.pm.pkg.component.ParsedServiceImpl;
 import com.android.internal.pm.pkg.component.ParsedUsesPermission;
+import com.android.internal.pm.pkg.component.ParsedUsesPermissionImpl;
 import com.android.internal.pm.pkg.parsing.ParsingPackage;
 import com.android.internal.util.ArrayUtils;
 import com.android.server.pm.parsing.PackageCacher;
@@ -76,19 +87,8 @@
 import com.android.server.pm.parsing.PackageParser2;
 import com.android.server.pm.parsing.TestPackageParser2;
 import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
-import com.android.server.pm.parsing.pkg.PackageImpl;
-import com.android.server.pm.permission.CompatibilityPermissionInfo;
 import com.android.server.pm.pkg.AndroidPackage;
 import com.android.server.pm.pkg.PackageUserStateInternal;
-import com.android.server.pm.pkg.component.ParsedActivityImpl;
-import com.android.server.pm.pkg.component.ParsedInstrumentationImpl;
-import com.android.server.pm.pkg.component.ParsedIntentInfoImpl;
-import com.android.server.pm.pkg.component.ParsedPermissionGroupImpl;
-import com.android.server.pm.pkg.component.ParsedPermissionImpl;
-import com.android.server.pm.pkg.component.ParsedPermissionUtils;
-import com.android.server.pm.pkg.component.ParsedProviderImpl;
-import com.android.server.pm.pkg.component.ParsedServiceImpl;
-import com.android.server.pm.pkg.component.ParsedUsesPermissionImpl;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -725,6 +725,16 @@
                 public boolean hasFeature(String feature) {
                     return false;
                 }
+
+                @Override
+                public Set<String> getHiddenApiWhitelistedApps() {
+                    return new ArraySet<>();
+                }
+
+                @Override
+                public Set<String> getInstallConstraintsAllowlist() {
+                    return new ArraySet<>();
+                }
             });
             if (cacheDir != null) {
                 setCacheDir(cacheDir);
@@ -1062,7 +1072,7 @@
                 .addProtectedBroadcast("foo8")
                 .setSdkLibraryName("sdk12")
                 .setSdkLibVersionMajor(42)
-                .addUsesSdkLibrary("sdk23", 200, new String[]{"digest2"})
+                .addUsesSdkLibrary("sdk23", 200, new String[]{"digest2"}, true)
                 .setStaticSharedLibraryName("foo23")
                 .setStaticSharedLibraryVersion(100)
                 .addUsesStaticLibrary("foo23", 100, new String[]{"digest"})
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/ScanTests.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/ScanTests.java
index decb44c..c1271bb 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/ScanTests.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/ScanTests.java
@@ -50,13 +50,13 @@
 import android.platform.test.annotations.Presubmit;
 import android.util.Pair;
 
+import com.android.internal.pm.parsing.pkg.PackageImpl;
 import com.android.internal.pm.parsing.pkg.ParsedPackage;
+import com.android.internal.pm.pkg.component.ParsedUsesPermissionImpl;
 import com.android.internal.pm.pkg.parsing.ParsingPackage;
 import com.android.server.compat.PlatformCompat;
 import com.android.server.pm.parsing.PackageInfoUtils;
-import com.android.server.pm.parsing.pkg.PackageImpl;
 import com.android.server.pm.pkg.AndroidPackage;
-import com.android.server.pm.pkg.component.ParsedUsesPermissionImpl;
 import com.android.server.pm.verify.domain.DomainVerificationManagerInternal;
 
 import org.hamcrest.BaseMatcher;
@@ -376,7 +376,7 @@
         // Create the ParsedPackage for the apex
         final ParsedPackage basicPackage =
                 ((ParsedPackage) new PackageImpl(DUMMY_PACKAGE_NAME, codePath, codePath,
-                        mock(TypedArray.class), false)
+                        mock(TypedArray.class), false, null)
                         .setVolumeUuid(UUID_ONE.toString())
                         .hideAsParsed())
                         .setVersionCodeMajor(1)
@@ -595,12 +595,12 @@
         // TODO(b/135203078): Make this use PackageImpl.forParsing and separate the steps
         return (ParsingPackage) ((ParsedPackage) new PackageImpl(packageName,
                 "/data/tmp/randompath/base.apk", createCodePath(packageName),
-                mock(TypedArray.class), false)
+                mock(TypedArray.class), false, null)
                 .setVolumeUuid(UUID_ONE.toString())
                 .addUsesStaticLibrary("some.static.library", 234L, new String[]{"testCert1"})
                 .addUsesStaticLibrary("some.other.static.library", 456L, new String[]{"testCert2"})
-                .addUsesSdkLibrary("some.sdk.library", 123L, new String[]{"testCert3"})
-                .addUsesSdkLibrary("some.other.sdk.library", 789L, new String[]{"testCert4"})
+                .addUsesSdkLibrary("some.sdk.library", 123L, new String[]{"testCert3"}, false)
+                .addUsesSdkLibrary("some.other.sdk.library", 789L, new String[]{"testCert4"}, true)
                 .hideAsParsed())
                 .setNativeLibraryRootDir("/data/tmp/randompath/base.apk:/lib")
                 .setVersionCodeMajor(1)
@@ -628,6 +628,7 @@
         assertThat(pkgSetting.getUsesSdkLibraries(),
                 arrayContaining("some.sdk.library", "some.other.sdk.library"));
         assertThat(pkgSetting.getUsesSdkLibrariesVersionsMajor(), is(new long[]{123L, 789L}));
+        assertThat(pkgSetting.getUsesSdkLibrariesOptional(), is(new boolean[]{false, true}));
         assertThat(pkgSetting.getPkg(), is(scanResult.mRequest.mParsedPackage));
         assertThat(pkgSetting.getPath(), is(new File(createCodePath(packageName))));
         assertThat(pkgSetting.getVersionCode(),
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/PackageParserLegacyCoreTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/PackageParserLegacyCoreTest.java
index b102ab4..b63950c 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/PackageParserLegacyCoreTest.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/PackageParserLegacyCoreTest.java
@@ -39,14 +39,14 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.pm.parsing.pkg.ParsedPackage;
+import com.android.internal.pm.pkg.component.ParsedActivityUtils;
 import com.android.internal.pm.pkg.component.ParsedComponent;
 import com.android.internal.pm.pkg.component.ParsedIntentInfo;
 import com.android.internal.pm.pkg.component.ParsedPermission;
+import com.android.internal.pm.pkg.component.ParsedPermissionUtils;
 import com.android.internal.util.ArrayUtils;
 import com.android.server.pm.PackageManagerException;
 import com.android.server.pm.pkg.AndroidPackage;
-import com.android.server.pm.pkg.component.ParsedActivityUtils;
-import com.android.server.pm.pkg.component.ParsedPermissionUtils;
 import com.android.server.pm.test.service.server.R;
 
 import com.google.common.truth.Expect;
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/PackageParsingDeferErrorTest.kt b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/PackageParsingDeferErrorTest.kt
index 67b91d2..c435b94 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/PackageParsingDeferErrorTest.kt
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/PackageParsingDeferErrorTest.kt
@@ -22,7 +22,6 @@
 import android.platform.test.annotations.Presubmit
 import androidx.test.InstrumentationRegistry
 import com.android.internal.pm.parsing.pkg.ParsedPackage
-import com.android.server.pm.pkg.parsing.ParsingPackageUtils
 import com.android.server.pm.test.service.server.R
 import com.google.common.truth.Truth.assertThat
 import com.google.common.truth.Truth.assertWithMessage
@@ -121,7 +120,7 @@
                 input.copyTo(output)
             }
         }
-        return ParsingPackageUtils.parseDefaultOneTime(file, 0 /*flags*/, emptyList(),
+        return ParsingUtils.parseDefaultOneTime(file, 0 /*flags*/, emptyList(),
                 false /*collectCertificates*/)
     }
 }
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/ParsingUtils.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/ParsingUtils.java
new file mode 100644
index 0000000..a9eac95
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/ParsingUtils.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.parsing;
+
+import android.annotation.NonNull;
+import android.content.pm.parsing.result.ParseInput;
+import android.content.pm.parsing.result.ParseResult;
+import android.content.pm.parsing.result.ParseTypeImpl;
+import android.content.res.TypedArray;
+import android.permission.PermissionManager;
+
+import com.android.internal.pm.parsing.pkg.PackageImpl;
+import com.android.internal.pm.parsing.pkg.ParsedPackage;
+import com.android.internal.pm.pkg.parsing.ParsingPackage;
+import com.android.internal.pm.pkg.parsing.ParsingPackageUtils;
+import com.android.server.SystemConfig;
+
+import java.io.File;
+import java.util.List;
+import java.util.Set;
+
+/** @hide **/
+public class ParsingUtils {
+
+    /**
+     * @see ParsingPackageUtils#parseDefault(ParseInput, File, int, List, boolean,
+     * ParsingPackageUtils.Callback)
+     */
+    @NonNull
+    public static ParseResult<ParsedPackage> parseDefaultOneTime(File file,
+            @ParsingPackageUtils.ParseFlags int parseFlags,
+            @NonNull List<PermissionManager.SplitPermissionInfo> splitPermissions,
+            boolean collectCertificates) {
+        ParseInput input = ParseTypeImpl.forDefaultParsing().reset();
+        return ParsingPackageUtils.parseDefault(input, file, parseFlags, splitPermissions, collectCertificates,
+                new ParsingPackageUtils.Callback() {
+            @Override
+            public boolean hasFeature(String feature) {
+                // Assume the device doesn't support anything. This will affect permission
+                // parsing and will force <uses-permission/> declarations to include all
+                // requiredNotFeature permissions and exclude all requiredFeature
+                // permissions. This mirrors the old behavior.
+                return false;
+            }
+
+            @Override
+            public ParsingPackage startParsingPackage(
+                    @NonNull String packageName,
+                    @NonNull String baseApkPath,
+                    @NonNull String path,
+                    @NonNull TypedArray manifestArray, boolean isCoreApp) {
+                return PackageImpl.forParsing(packageName, baseApkPath, path, manifestArray,
+                        isCoreApp, this);
+            }
+
+            @Override
+            public Set<String> getHiddenApiWhitelistedApps() {
+                return SystemConfig.getInstance().getHiddenApiWhitelistedApps();
+            }
+
+            @Override
+            public Set<String> getInstallConstraintsAllowlist() {
+                return SystemConfig.getInstance().getInstallConstraintsAllowlist();
+            }
+        });
+    }
+}
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/SystemPartitionParseTest.kt b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/SystemPartitionParseTest.kt
index 1f57b6c..98af63c 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/SystemPartitionParseTest.kt
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/SystemPartitionParseTest.kt
@@ -17,15 +17,15 @@
 package com.android.server.pm.parsing
 
 import android.content.pm.PackageManager
-import com.android.server.pm.pkg.parsing.ParsingPackageUtils
 import android.platform.test.annotations.Postsubmit
+import com.android.internal.pm.pkg.parsing.ParsingPackageUtils
 import com.android.server.pm.PackageManagerException
 import com.android.server.pm.PackageManagerService
 import com.android.server.pm.PackageManagerServiceUtils
+import java.io.File
 import org.junit.Rule
 import org.junit.Test
 import org.junit.rules.TemporaryFolder
-import java.io.File
 
 /**
  * This test parses all the system APKs on the device image to ensure that they succeed.
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/AndroidHidlUpdaterTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/AndroidHidlUpdaterTest.java
index 6cd7123..9517e49 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/AndroidHidlUpdaterTest.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/AndroidHidlUpdaterTest.java
@@ -24,8 +24,8 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.internal.pm.parsing.pkg.PackageImpl;
 import com.android.internal.pm.parsing.pkg.ParsedPackage;
-import com.android.server.pm.parsing.pkg.PackageImpl;
 import com.android.server.pm.pkg.AndroidPackage;
 
 import org.junit.Test;
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/AndroidNetIpSecIkeUpdaterTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/AndroidNetIpSecIkeUpdaterTest.java
index 27fd781..01fad8f 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/AndroidNetIpSecIkeUpdaterTest.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/AndroidNetIpSecIkeUpdaterTest.java
@@ -21,8 +21,8 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.internal.pm.parsing.pkg.PackageImpl;
 import com.android.internal.pm.parsing.pkg.ParsedPackage;
-import com.android.server.pm.parsing.pkg.PackageImpl;
 import com.android.server.pm.pkg.AndroidPackage;
 
 import org.junit.Test;
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/AndroidTestBaseUpdaterTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/AndroidTestBaseUpdaterTest.java
index b13d6de..b1f26c2 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/AndroidTestBaseUpdaterTest.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/AndroidTestBaseUpdaterTest.java
@@ -23,8 +23,8 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.internal.pm.parsing.pkg.PackageImpl;
 import com.android.internal.pm.parsing.pkg.ParsedPackage;
-import com.android.server.pm.parsing.pkg.PackageImpl;
 import com.android.server.pm.pkg.AndroidPackage;
 
 import org.junit.Test;
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/AndroidTestRunnerSplitUpdaterTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/AndroidTestRunnerSplitUpdaterTest.java
index fa69f84..349763a 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/AndroidTestRunnerSplitUpdaterTest.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/AndroidTestRunnerSplitUpdaterTest.java
@@ -24,9 +24,9 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.internal.pm.parsing.pkg.PackageImpl;
 import com.android.internal.pm.parsing.pkg.ParsedPackage;
 import com.android.server.pm.parsing.library.PackageBackwardCompatibility.AndroidTestRunnerSplitUpdater;
-import com.android.server.pm.parsing.pkg.PackageImpl;
 import com.android.server.pm.pkg.AndroidPackage;
 
 import org.junit.Test;
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/ApexSharedLibraryUpdaterTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/ApexSharedLibraryUpdaterTest.java
index 856013a..71bdacb 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/ApexSharedLibraryUpdaterTest.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/ApexSharedLibraryUpdaterTest.java
@@ -22,9 +22,9 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.internal.pm.parsing.pkg.PackageImpl;
 import com.android.internal.pm.parsing.pkg.ParsedPackage;
 import com.android.server.SystemConfig;
-import com.android.server.pm.parsing.pkg.PackageImpl;
 import com.android.server.pm.pkg.AndroidPackage;
 
 import org.junit.Before;
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/ComGoogleAndroidMapsUpdaterTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/ComGoogleAndroidMapsUpdaterTest.java
index ae5ea21..6aa0c2d 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/ComGoogleAndroidMapsUpdaterTest.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/ComGoogleAndroidMapsUpdaterTest.java
@@ -21,8 +21,8 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.internal.pm.parsing.pkg.PackageImpl;
 import com.android.internal.pm.parsing.pkg.ParsedPackage;
-import com.android.server.pm.parsing.pkg.PackageImpl;
 import com.android.server.pm.pkg.AndroidPackage;
 
 import org.junit.Test;
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/OrgApacheHttpLegacyUpdaterTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/OrgApacheHttpLegacyUpdaterTest.java
index e126ffc..44098d0 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/OrgApacheHttpLegacyUpdaterTest.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/OrgApacheHttpLegacyUpdaterTest.java
@@ -23,8 +23,8 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.internal.pm.parsing.pkg.PackageImpl;
 import com.android.internal.pm.parsing.pkg.ParsedPackage;
-import com.android.server.pm.parsing.pkg.PackageImpl;
 import com.android.server.pm.pkg.AndroidPackage;
 
 import org.junit.Test;
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/PackageBackwardCompatibilityTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/PackageBackwardCompatibilityTest.java
index d0b0cf8..9d5ce8a 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/PackageBackwardCompatibilityTest.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/PackageBackwardCompatibilityTest.java
@@ -28,10 +28,10 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.internal.pm.parsing.pkg.PackageImpl;
 import com.android.internal.pm.parsing.pkg.ParsedPackage;
 import com.android.internal.pm.pkg.parsing.ParsingPackage;
 import com.android.server.pm.parsing.library.PackageBackwardCompatibility.RemoveUnnecessaryAndroidTestBaseLibrary;
-import com.android.server.pm.parsing.pkg.PackageImpl;
 import com.android.server.pm.pkg.AndroidPackage;
 
 import org.junit.Assume;
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/RemoveUnnecessaryAndroidTestBaseLibraryTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/RemoveUnnecessaryAndroidTestBaseLibraryTest.java
index c141c03..bffeb72 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/RemoveUnnecessaryAndroidTestBaseLibraryTest.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/RemoveUnnecessaryAndroidTestBaseLibraryTest.java
@@ -23,9 +23,9 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.internal.pm.parsing.pkg.PackageImpl;
 import com.android.internal.pm.parsing.pkg.ParsedPackage;
 import com.android.server.pm.parsing.library.PackageBackwardCompatibility.RemoveUnnecessaryAndroidTestBaseLibrary;
-import com.android.server.pm.parsing.pkg.PackageImpl;
 import com.android.server.pm.pkg.AndroidPackage;
 
 import org.junit.Test;
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest.java
index a58604b..b114cd3 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/parsing/library/RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest.java
@@ -23,9 +23,9 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.internal.pm.parsing.pkg.PackageImpl;
 import com.android.internal.pm.parsing.pkg.ParsedPackage;
 import com.android.server.pm.parsing.library.PackageBackwardCompatibility.RemoveUnnecessaryOrgApacheHttpLegacyLibrary;
-import com.android.server.pm.parsing.pkg.PackageImpl;
 import com.android.server.pm.pkg.AndroidPackage;
 
 import org.junit.Test;
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
index 170faf6..ef9c62f 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
@@ -30,21 +30,21 @@
 import android.util.SparseArray
 import android.util.SparseIntArray
 import com.android.internal.R
-import com.android.server.pm.parsing.pkg.AndroidPackageUtils
-import com.android.server.pm.parsing.pkg.PackageImpl
+import com.android.internal.pm.parsing.pkg.AndroidPackageLegacyUtils
+import com.android.internal.pm.parsing.pkg.PackageImpl
+import com.android.internal.pm.pkg.component.ParsedActivityImpl
+import com.android.internal.pm.pkg.component.ParsedApexSystemServiceImpl
+import com.android.internal.pm.pkg.component.ParsedAttributionImpl
+import com.android.internal.pm.pkg.component.ParsedComponentImpl
+import com.android.internal.pm.pkg.component.ParsedInstrumentationImpl
+import com.android.internal.pm.pkg.component.ParsedIntentInfoImpl
+import com.android.internal.pm.pkg.component.ParsedPermissionGroupImpl
+import com.android.internal.pm.pkg.component.ParsedPermissionImpl
+import com.android.internal.pm.pkg.component.ParsedProcessImpl
+import com.android.internal.pm.pkg.component.ParsedProviderImpl
+import com.android.internal.pm.pkg.component.ParsedServiceImpl
+import com.android.internal.pm.pkg.component.ParsedUsesPermissionImpl
 import com.android.server.pm.pkg.AndroidPackage
-import com.android.server.pm.pkg.component.ParsedActivityImpl
-import com.android.server.pm.pkg.component.ParsedApexSystemServiceImpl
-import com.android.server.pm.pkg.component.ParsedAttributionImpl
-import com.android.server.pm.pkg.component.ParsedComponentImpl
-import com.android.server.pm.pkg.component.ParsedInstrumentationImpl
-import com.android.server.pm.pkg.component.ParsedIntentInfoImpl
-import com.android.server.pm.pkg.component.ParsedPermissionGroupImpl
-import com.android.server.pm.pkg.component.ParsedPermissionImpl
-import com.android.server.pm.pkg.component.ParsedProcessImpl
-import com.android.server.pm.pkg.component.ParsedProviderImpl
-import com.android.server.pm.pkg.component.ParsedServiceImpl
-import com.android.server.pm.pkg.component.ParsedUsesPermissionImpl
 import com.android.server.testutils.mockThrowOnUnmocked
 import com.android.server.testutils.whenever
 import java.security.KeyPairGenerator
@@ -127,6 +127,7 @@
         "getUsesSdkLibraries",
         "getUsesSdkLibrariesVersionsMajor",
         "getUsesSdkLibrariesCertDigests",
+        "getUsesSdkLibrariesOptional",
         // Tested through addUsesStaticLibrary
         "addUsesStaticLibrary",
         "getUsesStaticLibraries",
@@ -533,34 +534,34 @@
             }
         ),
         getter(AndroidPackage::getKnownActivityEmbeddingCerts, setOf("TESTEMBEDDINGCERT")),
-        getSetByValue({ AndroidPackageUtils.isOdm(it) }, "isOdm", PackageImpl::setOdm, true),
-        getSetByValue({ AndroidPackageUtils.isOem(it) }, "isOem", PackageImpl::setOem, true),
+        getSetByValue({ AndroidPackageLegacyUtils.isOdm(it) }, "isOdm", PackageImpl::setOdm, true),
+        getSetByValue({ AndroidPackageLegacyUtils.isOem(it) }, "isOem", PackageImpl::setOem, true),
         getSetByValue(
-            { AndroidPackageUtils.isPrivileged(it) },
+            { AndroidPackageLegacyUtils.isPrivileged(it) },
             "isPrivileged",
             PackageImpl::setPrivileged,
             true
         ),
         getSetByValue(
-            { AndroidPackageUtils.isProduct(it) },
+            { AndroidPackageLegacyUtils.isProduct(it) },
             "isProduct",
             PackageImpl::setProduct,
             true
         ),
         getSetByValue(
-            { AndroidPackageUtils.isVendor(it) },
+            { AndroidPackageLegacyUtils.isVendor(it) },
             "isVendor",
             PackageImpl::setVendor,
             true
         ),
         getSetByValue(
-            { AndroidPackageUtils.isSystem(it) },
+            { AndroidPackageLegacyUtils.isSystem(it) },
             "isSystem",
             PackageImpl::setSystem,
             true
         ),
         getSetByValue(
-            { AndroidPackageUtils.isSystemExt(it) },
+            { AndroidPackageLegacyUtils.isSystemExt(it) },
             "isSystemExt",
             PackageImpl::setSystemExt,
             true
@@ -592,7 +593,7 @@
                 )
             ) { "" }
         },
-        true
+        true, null
     )
         .asSplit(
             arrayOf("testSplitNameZero", "testSplitNameOne"),
@@ -608,7 +609,7 @@
         .setSplitHasCode(1, false)
         .setSplitClassLoaderName(0, "testSplitClassLoaderNameZero")
         .setSplitClassLoaderName(1, "testSplitClassLoaderNameOne")
-        .addUsesSdkLibrary("testSdk", 2L, arrayOf("testCertDigest1"))
+        .addUsesSdkLibrary("testSdk", 2L, arrayOf("testCertDigest1"), true)
         .addUsesStaticLibrary("testStatic", 3L, arrayOf("testCertDigest2"))
 
     override fun finalizeObject(parcelable: Parcelable) {
@@ -661,6 +662,7 @@
         expect.that(after.usesSdkLibrariesCertDigests!!.size).isEqualTo(1)
         expect.that(after.usesSdkLibrariesCertDigests!![0]).asList()
                 .containsExactly("testCertDigest1")
+        expect.that(after.usesSdkLibrariesOptional).asList().containsExactly(true)
 
         expect.that(after.usesStaticLibraries).containsExactly("testStatic")
         expect.that(after.usesStaticLibrariesVersions).asList().containsExactly(3L)
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedActivityTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedActivityTest.kt
index 2646854..2c8b1cd 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedActivityTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedActivityTest.kt
@@ -18,7 +18,7 @@
 
 import android.content.pm.ActivityInfo
 import com.android.internal.pm.pkg.component.ParsedActivity
-import com.android.server.pm.pkg.component.ParsedActivityImpl
+import com.android.internal.pm.pkg.component.ParsedActivityImpl
 import kotlin.contracts.ExperimentalContracts
 
 @ExperimentalContracts
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedAttributionTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedAttributionTest.kt
index 52d5b3b..ad53746 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedAttributionTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedAttributionTest.kt
@@ -17,7 +17,7 @@
 package com.android.server.pm.test.parsing.parcelling
 
 import com.android.internal.pm.pkg.component.ParsedAttribution
-import com.android.server.pm.pkg.component.ParsedAttributionImpl
+import com.android.internal.pm.pkg.component.ParsedAttributionImpl
 import kotlin.contracts.ExperimentalContracts
 
 @ExperimentalContracts
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedComponentTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedComponentTest.kt
index af0c0de..3ac4853 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedComponentTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedComponentTest.kt
@@ -18,8 +18,8 @@
 
 import android.content.pm.PackageManager
 import com.android.internal.pm.pkg.component.ParsedComponent
-import com.android.server.pm.pkg.component.ParsedComponentImpl
-import com.android.server.pm.pkg.component.ParsedIntentInfoImpl
+import com.android.internal.pm.pkg.component.ParsedComponentImpl
+import com.android.internal.pm.pkg.component.ParsedIntentInfoImpl
 import android.os.Bundle
 import android.os.Parcelable
 import kotlin.contracts.ExperimentalContracts
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedInstrumentationTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedInstrumentationTest.kt
index dc0f194..2bd4f61 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedInstrumentationTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedInstrumentationTest.kt
@@ -17,7 +17,7 @@
 package com.android.server.pm.test.parsing.parcelling
 
 import com.android.internal.pm.pkg.component.ParsedInstrumentation
-import com.android.server.pm.pkg.component.ParsedInstrumentationImpl
+import com.android.internal.pm.pkg.component.ParsedInstrumentationImpl
 import kotlin.contracts.ExperimentalContracts
 
 @ExperimentalContracts
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedIntentInfoTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedIntentInfoTest.kt
index 5224f23..af385e2 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedIntentInfoTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedIntentInfoTest.kt
@@ -17,7 +17,7 @@
 package com.android.server.pm.test.parsing.parcelling
 
 import com.android.internal.pm.pkg.component.ParsedIntentInfo
-import com.android.server.pm.pkg.component.ParsedIntentInfoImpl
+import com.android.internal.pm.pkg.component.ParsedIntentInfoImpl
 import android.os.Parcelable
 import android.os.PatternMatcher
 import kotlin.contracts.ExperimentalContracts
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedMainComponentTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedMainComponentTest.kt
index dfff602..061e39d 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedMainComponentTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedMainComponentTest.kt
@@ -17,7 +17,7 @@
 package com.android.server.pm.test.parsing.parcelling
 
 import com.android.internal.pm.pkg.component.ParsedMainComponent
-import com.android.server.pm.pkg.component.ParsedMainComponentImpl
+import com.android.internal.pm.pkg.component.ParsedMainComponentImpl
 import android.os.Parcelable
 import java.util.Arrays
 import kotlin.contracts.ExperimentalContracts
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedPermissionGroupTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedPermissionGroupTest.kt
index ccbf558..3a64188 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedPermissionGroupTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedPermissionGroupTest.kt
@@ -17,7 +17,7 @@
 package com.android.server.pm.test.parsing.parcelling
 
 import com.android.internal.pm.pkg.component.ParsedPermissionGroup
-import com.android.server.pm.pkg.component.ParsedPermissionGroupImpl
+import com.android.internal.pm.pkg.component.ParsedPermissionGroupImpl
 import kotlin.contracts.ExperimentalContracts
 
 @ExperimentalContracts
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedPermissionTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedPermissionTest.kt
index 2814783..551f16d 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedPermissionTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedPermissionTest.kt
@@ -18,8 +18,8 @@
 
 import com.android.internal.pm.pkg.component.ParsedPermission
 import com.android.internal.pm.pkg.component.ParsedPermissionGroup
-import com.android.server.pm.pkg.component.ParsedPermissionGroupImpl
-import com.android.server.pm.pkg.component.ParsedPermissionImpl
+import com.android.internal.pm.pkg.component.ParsedPermissionGroupImpl
+import com.android.internal.pm.pkg.component.ParsedPermissionImpl
 import kotlin.contracts.ExperimentalContracts
 
 @ExperimentalContracts
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedProcessTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedProcessTest.kt
index 2e96046..93bdeae 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedProcessTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedProcessTest.kt
@@ -16,9 +16,9 @@
 
 package com.android.server.pm.test.parsing.parcelling
 
-import com.android.internal.pm.pkg.component.ParsedProcess
-import com.android.server.pm.pkg.component.ParsedProcessImpl
 import android.util.ArrayMap
+import com.android.internal.pm.pkg.component.ParsedProcess
+import com.android.internal.pm.pkg.component.ParsedProcessImpl
 import kotlin.contracts.ExperimentalContracts
 
 @ExperimentalContracts
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedProviderTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedProviderTest.kt
index 290dbd6..1e84470 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedProviderTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedProviderTest.kt
@@ -17,9 +17,9 @@
 package com.android.server.pm.test.parsing.parcelling
 
 import android.content.pm.PathPermission
-import com.android.internal.pm.pkg.component.ParsedProvider
-import com.android.server.pm.pkg.component.ParsedProviderImpl
 import android.os.PatternMatcher
+import com.android.internal.pm.pkg.component.ParsedProvider
+import com.android.internal.pm.pkg.component.ParsedProviderImpl
 import kotlin.contracts.ExperimentalContracts
 
 @ExperimentalContracts
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedServiceTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedServiceTest.kt
index 3ae7e92..79d5a4f 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedServiceTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedServiceTest.kt
@@ -17,7 +17,7 @@
 package com.android.server.pm.test.parsing.parcelling
 
 import com.android.internal.pm.pkg.component.ParsedService
-import com.android.server.pm.pkg.component.ParsedServiceImpl
+import com.android.internal.pm.pkg.component.ParsedServiceImpl
 import kotlin.contracts.ExperimentalContracts
 
 @ExperimentalContracts
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedUsesPermissionTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedUsesPermissionTest.kt
index 67dfc6d..d0ad09b 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedUsesPermissionTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedUsesPermissionTest.kt
@@ -17,7 +17,7 @@
 package com.android.server.pm.test.parsing.parcelling
 
 import com.android.internal.pm.pkg.component.ParsedUsesPermission
-import com.android.server.pm.pkg.component.ParsedUsesPermissionImpl
+import com.android.internal.pm.pkg.component.ParsedUsesPermissionImpl
 import kotlin.contracts.ExperimentalContracts
 
 @ExperimentalContracts
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/pkg/PackageStateTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/pkg/PackageStateTest.kt
index 1da3a22..b21c349 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/pkg/PackageStateTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/pkg/PackageStateTest.kt
@@ -17,37 +17,34 @@
 package com.android.server.pm.test.pkg
 
 import android.content.Intent
-import android.content.pm.overlay.OverlayPaths
 import android.content.pm.PackageManager
 import android.content.pm.PathPermission
 import android.content.pm.SharedLibraryInfo
 import android.content.pm.VersionedPackage
+import android.content.pm.overlay.OverlayPaths
 import android.os.PatternMatcher
 import android.util.ArraySet
+import com.android.internal.pm.parsing.pkg.PackageImpl
 import com.android.internal.pm.pkg.component.ParsedActivity
+import com.android.internal.pm.pkg.component.ParsedActivityImpl
+import com.android.internal.pm.pkg.component.ParsedComponentImpl
 import com.android.internal.pm.pkg.component.ParsedInstrumentation
+import com.android.internal.pm.pkg.component.ParsedIntentInfoImpl
 import com.android.internal.pm.pkg.component.ParsedPermission
 import com.android.internal.pm.pkg.component.ParsedPermissionGroup
+import com.android.internal.pm.pkg.component.ParsedPermissionImpl
 import com.android.internal.pm.pkg.component.ParsedProcess
+import com.android.internal.pm.pkg.component.ParsedProcessImpl
 import com.android.internal.pm.pkg.component.ParsedProvider
+import com.android.internal.pm.pkg.component.ParsedProviderImpl
 import com.android.internal.pm.pkg.component.ParsedService
 import com.android.server.pm.PackageSetting
 import com.android.server.pm.PackageSettingBuilder
-import com.android.server.pm.parsing.pkg.PackageImpl
 import com.android.server.pm.pkg.AndroidPackage
 import com.android.server.pm.pkg.PackageState
 import com.android.server.pm.pkg.PackageUserState
-import com.android.server.pm.pkg.component.ParsedActivityImpl
-import com.android.server.pm.pkg.component.ParsedComponentImpl
-import com.android.server.pm.pkg.component.ParsedIntentInfoImpl
-import com.android.server.pm.pkg.component.ParsedPermissionImpl
-import com.android.server.pm.pkg.component.ParsedProcessImpl
-import com.android.server.pm.pkg.component.ParsedProviderImpl
 import com.android.server.pm.test.parsing.parcelling.AndroidPackageTest
 import com.google.common.truth.Expect
-import org.junit.Rule
-import org.junit.Test
-import org.junit.rules.TemporaryFolder
 import kotlin.contracts.ExperimentalContracts
 import kotlin.reflect.KClass
 import kotlin.reflect.KFunction
@@ -55,6 +52,9 @@
 import kotlin.reflect.full.isSubtypeOf
 import kotlin.reflect.full.memberFunctions
 import kotlin.reflect.full.starProjectedType
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TemporaryFolder
 
 class PackageStateTest {
 
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationCollectorTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationCollectorTest.kt
index 9341e9d..5e73d19 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationCollectorTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationCollectorTest.kt
@@ -22,11 +22,11 @@
 import android.os.PatternMatcher
 import android.util.ArraySet
 import com.android.internal.pm.parsing.pkg.AndroidPackageInternal
+import com.android.internal.pm.pkg.component.ParsedActivityImpl
+import com.android.internal.pm.pkg.component.ParsedIntentInfoImpl
 import com.android.server.SystemConfig
 import com.android.server.compat.PlatformCompat
 import com.android.server.pm.pkg.AndroidPackage
-import com.android.server.pm.pkg.component.ParsedActivityImpl
-import com.android.server.pm.pkg.component.ParsedIntentInfoImpl
 import com.android.server.pm.verify.domain.DomainVerificationCollector
 import com.android.server.testutils.mockThrowOnUnmocked
 import com.android.server.testutils.whenever
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationEnforcerTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationEnforcerTest.kt
index a737b90..d307608 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationEnforcerTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationEnforcerTest.kt
@@ -29,17 +29,22 @@
 import android.util.SparseArray
 import androidx.test.platform.app.InstrumentationRegistry
 import com.android.internal.pm.parsing.pkg.AndroidPackageInternal
+import com.android.internal.pm.pkg.component.ParsedActivityImpl
+import com.android.internal.pm.pkg.component.ParsedIntentInfoImpl
 import com.android.server.pm.Computer
 import com.android.server.pm.pkg.PackageStateInternal
 import com.android.server.pm.pkg.PackageUserStateInternal
-import com.android.server.pm.pkg.component.ParsedActivityImpl
-import com.android.server.pm.pkg.component.ParsedIntentInfoImpl
 import com.android.server.pm.verify.domain.DomainVerificationEnforcer
 import com.android.server.pm.verify.domain.DomainVerificationManagerInternal
 import com.android.server.pm.verify.domain.DomainVerificationService
 import com.android.server.pm.verify.domain.proxy.DomainVerificationProxy
 import com.android.server.testutils.mockThrowOnUnmocked
 import com.android.server.testutils.whenever
+import java.util.UUID
+import java.util.concurrent.atomic.AtomicBoolean
+import java.util.concurrent.atomic.AtomicInteger
+import kotlin.test.assertFailsWith
+import kotlin.test.fail
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
@@ -51,11 +56,6 @@
 import org.mockito.Mockito.eq
 import org.mockito.Mockito.mock
 import org.mockito.Mockito.verifyNoMoreInteractions
-import java.util.UUID
-import java.util.concurrent.atomic.AtomicBoolean
-import java.util.concurrent.atomic.AtomicInteger
-import kotlin.test.assertFailsWith
-import kotlin.test.fail
 
 @RunWith(Parameterized::class)
 class DomainVerificationEnforcerTest {
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationManagerApiTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationManagerApiTest.kt
index f38df22..5edf30a3 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationManagerApiTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationManagerApiTest.kt
@@ -30,24 +30,24 @@
 import android.util.ArraySet
 import android.util.SparseArray
 import com.android.internal.pm.parsing.pkg.AndroidPackageInternal
+import com.android.internal.pm.pkg.component.ParsedActivityImpl
+import com.android.internal.pm.pkg.component.ParsedIntentInfoImpl
 import com.android.server.pm.pkg.PackageStateInternal
 import com.android.server.pm.pkg.PackageUserStateInternal
-import com.android.server.pm.pkg.component.ParsedActivityImpl
-import com.android.server.pm.pkg.component.ParsedIntentInfoImpl
 import com.android.server.pm.verify.domain.DomainVerificationManagerStub
 import com.android.server.pm.verify.domain.DomainVerificationService
 import com.android.server.testutils.mockThrowOnUnmocked
 import com.android.server.testutils.whenever
 import com.google.common.truth.Truth.assertThat
+import java.util.UUID
+import java.util.concurrent.atomic.AtomicBoolean
+import kotlin.test.assertFailsWith
 import org.junit.Test
 import org.mockito.ArgumentMatchers.any
 import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.ArgumentMatchers.anyLong
 import org.mockito.ArgumentMatchers.anyString
 import org.mockito.Mockito.doReturn
-import java.util.UUID
-import java.util.concurrent.atomic.AtomicBoolean
-import kotlin.test.assertFailsWith
 
 class DomainVerificationManagerApiTest {
 
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationPackageTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationPackageTest.kt
index 874e0d2..85f0125 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationPackageTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationPackageTest.kt
@@ -37,27 +37,27 @@
 import android.util.SparseArray
 import android.util.Xml
 import com.android.internal.pm.parsing.pkg.AndroidPackageInternal
+import com.android.internal.pm.pkg.component.ParsedActivityImpl
+import com.android.internal.pm.pkg.component.ParsedIntentInfoImpl
 import com.android.server.pm.Computer
 import com.android.server.pm.pkg.PackageStateInternal
 import com.android.server.pm.pkg.PackageUserStateInternal
-import com.android.server.pm.pkg.component.ParsedActivityImpl
-import com.android.server.pm.pkg.component.ParsedIntentInfoImpl
 import com.android.server.pm.verify.domain.DomainVerificationService
 import com.android.server.testutils.mock
 import com.android.server.testutils.mockThrowOnUnmocked
 import com.android.server.testutils.spy
 import com.android.server.testutils.whenever
 import com.google.common.truth.Truth.assertThat
+import java.io.ByteArrayInputStream
+import java.io.ByteArrayOutputStream
+import java.security.PublicKey
+import java.util.UUID
 import org.junit.Test
 import org.mockito.ArgumentMatchers.any
 import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.ArgumentMatchers.anyLong
 import org.mockito.ArgumentMatchers.anyString
 import org.mockito.Mockito.doReturn
-import java.io.ByteArrayInputStream
-import java.io.ByteArrayOutputStream
-import java.security.PublicKey
-import java.util.UUID
 
 class DomainVerificationPackageTest {
 
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationSettingsMutationTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationSettingsMutationTest.kt
index 3207e6c..a5c4f6c 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationSettingsMutationTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationSettingsMutationTest.kt
@@ -25,15 +25,16 @@
 import android.util.ArraySet
 import android.util.SparseArray
 import com.android.internal.pm.parsing.pkg.AndroidPackageInternal
+import com.android.internal.pm.pkg.component.ParsedActivityImpl
+import com.android.internal.pm.pkg.component.ParsedIntentInfoImpl
 import com.android.server.pm.pkg.PackageStateInternal
 import com.android.server.pm.pkg.PackageUserStateInternal
-import com.android.server.pm.pkg.component.ParsedActivityImpl
-import com.android.server.pm.pkg.component.ParsedIntentInfoImpl
 import com.android.server.pm.verify.domain.DomainVerificationManagerInternal
 import com.android.server.pm.verify.domain.DomainVerificationService
 import com.android.server.pm.verify.domain.proxy.DomainVerificationProxy
 import com.android.server.testutils.mockThrowOnUnmocked
 import com.android.server.testutils.whenever
+import java.util.UUID
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
@@ -44,7 +45,6 @@
 import org.mockito.Mockito.doReturn
 import org.mockito.Mockito.eq
 import org.mockito.Mockito.verify
-import java.util.UUID
 
 @RunWith(Parameterized::class)
 class DomainVerificationSettingsMutationTest {
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationUserSelectionOverrideTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationUserSelectionOverrideTest.kt
index a90b7d5..ae570a3 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationUserSelectionOverrideTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationUserSelectionOverrideTest.kt
@@ -27,14 +27,15 @@
 import android.util.ArraySet
 import android.util.SparseArray
 import com.android.internal.pm.parsing.pkg.AndroidPackageInternal
+import com.android.internal.pm.pkg.component.ParsedActivityImpl
+import com.android.internal.pm.pkg.component.ParsedIntentInfoImpl
 import com.android.server.pm.pkg.PackageStateInternal
 import com.android.server.pm.pkg.PackageUserStateInternal
-import com.android.server.pm.pkg.component.ParsedActivityImpl
-import com.android.server.pm.pkg.component.ParsedIntentInfoImpl
 import com.android.server.pm.verify.domain.DomainVerificationService
 import com.android.server.testutils.mockThrowOnUnmocked
 import com.android.server.testutils.whenever
 import com.google.common.truth.Truth.assertThat
+import java.util.UUID
 import org.junit.Test
 import org.mockito.ArgumentMatchers.any
 import org.mockito.ArgumentMatchers.anyInt
@@ -42,8 +43,6 @@
 import org.mockito.ArgumentMatchers.anyString
 import org.mockito.Mockito.doReturn
 
-import java.util.UUID
-
 class DomainVerificationUserStateOverrideTest {
 
     companion object {
diff --git a/services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/AppIdPermissionPolicyPermissionDefinitionsTest.kt b/services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/AppIdPermissionPolicyPermissionDefinitionsTest.kt
index 832136c..925dad8 100644
--- a/services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/AppIdPermissionPolicyPermissionDefinitionsTest.kt
+++ b/services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/AppIdPermissionPolicyPermissionDefinitionsTest.kt
@@ -38,7 +38,7 @@
  * AppIdPermissionPolicyPermissionStatesTest because these concepts don't apply to onUserAdded().
  */
 @RunWith(Parameterized::class)
-class AppIdPermissionPolicyPermissionDefinitionsTest : BaseAppIdPermissionPolicyTest() {
+class AppIdPermissionPolicyPermissionDefinitionsTest : BasePermissionPolicyTest() {
     @Parameterized.Parameter(0) lateinit var action: Action
 
     @Test
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 0547719..1237095 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
@@ -29,7 +29,7 @@
  * and resetRuntimePermissions() in AppIdPermissionPolicy
  */
 @RunWith(Parameterized::class)
-class AppIdPermissionPolicyPermissionResetTest : BaseAppIdPermissionPolicyTest() {
+class AppIdPermissionPolicyPermissionResetTest : BasePermissionPolicyTest() {
     @Parameterized.Parameter(0) lateinit var action: Action
 
     @Test
diff --git a/services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/AppIdPermissionPolicyPermissionStatesTest.kt b/services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/AppIdPermissionPolicyPermissionStatesTest.kt
index c44b2c5..6b9c9c2 100644
--- a/services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/AppIdPermissionPolicyPermissionStatesTest.kt
+++ b/services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/AppIdPermissionPolicyPermissionStatesTest.kt
@@ -39,7 +39,7 @@
  * states for onUserAdded(), onStorageVolumeAdded() and onPackageAdded() in AppIdPermissionPolicy
  */
 @RunWith(Parameterized::class)
-class AppIdPermissionPolicyPermissionStatesTest : BaseAppIdPermissionPolicyTest() {
+class AppIdPermissionPolicyPermissionStatesTest : BasePermissionPolicyTest() {
     @Parameterized.Parameter(0) lateinit var action: Action
 
     @Before
diff --git a/services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/AppIdPermissionPolicyTest.kt b/services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/AppIdPermissionPolicyTest.kt
index e4e3368..cde46ab 100644
--- a/services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/AppIdPermissionPolicyTest.kt
+++ b/services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/AppIdPermissionPolicyTest.kt
@@ -30,7 +30,7 @@
 import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
 
-class AppIdPermissionPolicyTest : BaseAppIdPermissionPolicyTest() {
+class AppIdPermissionPolicyTest : BasePermissionPolicyTest() {
     @Test
     fun testOnAppIdRemoved_appIdIsRemoved_permissionFlagsCleared() {
         val parsedPermission = mockParsedPermission(PERMISSION_NAME_0, PACKAGE_NAME_0)
diff --git a/services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/BaseAppIdPermissionPolicyTest.kt b/services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/BasePermissionPolicyTest.kt
similarity index 99%
rename from services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/BaseAppIdPermissionPolicyTest.kt
rename to services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/BasePermissionPolicyTest.kt
index 316f338..7b3f216 100644
--- a/services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/BaseAppIdPermissionPolicyTest.kt
+++ b/services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/BasePermissionPolicyTest.kt
@@ -53,7 +53,7 @@
  * Mocking unit test for AppIdPermissionPolicy.
  */
 @RunWith(AndroidJUnit4::class)
-abstract class BaseAppIdPermissionPolicyTest {
+abstract class BasePermissionPolicyTest {
     protected lateinit var oldState: MutableAccessState
     protected lateinit var newState: MutableAccessState
 
diff --git a/services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/DevicePermissionPolicyTest.kt b/services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/DevicePermissionPolicyTest.kt
new file mode 100644
index 0000000..996dd9d
--- /dev/null
+++ b/services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/DevicePermissionPolicyTest.kt
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.permission.test
+
+import com.android.server.permission.access.GetStateScope
+import com.android.server.permission.access.MutableAccessState
+import com.android.server.permission.access.MutableDevicePermissionFlags
+import com.android.server.permission.access.immutable.* // ktlint-disable no-wildcard-imports
+import com.android.server.permission.access.permission.DevicePermissionPolicy
+import com.android.server.permission.access.permission.PermissionFlags
+import com.android.server.testutils.mock
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+
+/**
+ * This class tests permissions for external devices, we have separate policy to
+ * manage external device permissions.
+ */
+class DevicePermissionPolicyTest : BasePermissionPolicyTest() {
+    private val devicePermissionPolicy = DevicePermissionPolicy()
+
+    @Test
+    fun testOnAppIdRemoved_clearPermissionFlags() {
+        val packageState = mockPackageState(
+            APP_ID_1,
+            mockAndroidPackage(PACKAGE_NAME_1, requestedPermissions = setOf(PERMISSION_NAME_0))
+        )
+        addPackageState(packageState)
+        setPermissionFlags(
+            APP_ID_1, DEVICE_ID_1, USER_ID_0, PERMISSION_NAME_0, PermissionFlags.RUNTIME_GRANTED
+        )
+        assertThat(
+            getPermissionFlags(APP_ID_1, DEVICE_ID_1, USER_ID_0, PERMISSION_NAME_0, oldState)
+        ).isEqualTo(PermissionFlags.RUNTIME_GRANTED)
+
+        mutateState {
+            with(devicePermissionPolicy) {
+                onAppIdRemoved(APP_ID_1)
+            }
+        }
+        assertThat(getPermissionFlags(APP_ID_1, DEVICE_ID_1, USER_ID_0, PERMISSION_NAME_0))
+            .isEqualTo(0)
+    }
+
+    @Test
+    fun testOnDeviceIdRemoved_clearPermissionFlags() {
+        val requestingPackageState = mockPackageState(
+            APP_ID_1,
+            mockAndroidPackage(PACKAGE_NAME_1, requestedPermissions = setOf(PERMISSION_NAME_0))
+        )
+        addPackageState(requestingPackageState)
+        setPermissionFlags(
+            APP_ID_1, DEVICE_ID_1, USER_ID_0, PERMISSION_NAME_0, PermissionFlags.RUNTIME_GRANTED
+        )
+        setPermissionFlags(
+            APP_ID_1, DEVICE_ID_2, USER_ID_0, PERMISSION_NAME_0, PermissionFlags.RUNTIME_GRANTED
+        )
+        assertThat(
+            getPermissionFlags(APP_ID_1, DEVICE_ID_1, USER_ID_0, PERMISSION_NAME_0, oldState)
+        ).isEqualTo(PermissionFlags.RUNTIME_GRANTED)
+        assertThat(
+            getPermissionFlags(APP_ID_1, DEVICE_ID_2, USER_ID_0, PERMISSION_NAME_0, oldState)
+        ).isEqualTo(PermissionFlags.RUNTIME_GRANTED)
+
+        mutateState {
+            with(devicePermissionPolicy) {
+                onDeviceIdRemoved(DEVICE_ID_1)
+            }
+        }
+        assertThat(getPermissionFlags(APP_ID_1, DEVICE_ID_1, USER_ID_0, PERMISSION_NAME_0))
+            .isEqualTo(0)
+        assertThat(getPermissionFlags(APP_ID_1, DEVICE_ID_2, USER_ID_0, PERMISSION_NAME_0))
+            .isEqualTo(PermissionFlags.RUNTIME_GRANTED)
+    }
+
+    @Test
+    fun testRemoveInactiveDevicesPermission_clearPermissionFlags() {
+        val requestingPackageState = mockPackageState(
+            APP_ID_1,
+            mockAndroidPackage(PACKAGE_NAME_1, requestedPermissions = setOf(PERMISSION_NAME_0))
+        )
+        addPackageState(requestingPackageState)
+        setPermissionFlags(
+            APP_ID_1, DEVICE_ID_1, USER_ID_0, PERMISSION_NAME_0, PermissionFlags.RUNTIME_GRANTED
+        )
+        setPermissionFlags(
+            APP_ID_1, DEVICE_ID_2, USER_ID_0, PERMISSION_NAME_0, PermissionFlags.RUNTIME_GRANTED
+        )
+        assertThat(
+            getPermissionFlags(APP_ID_1, DEVICE_ID_1, USER_ID_0, PERMISSION_NAME_0, oldState)
+        ).isEqualTo(PermissionFlags.RUNTIME_GRANTED)
+        assertThat(
+            getPermissionFlags(APP_ID_1, DEVICE_ID_2, USER_ID_0, PERMISSION_NAME_0, oldState)
+        ).isEqualTo(PermissionFlags.RUNTIME_GRANTED)
+
+        mutateState {
+            with(devicePermissionPolicy) {
+                trimDevicePermissionStates(setOf(DEVICE_ID_2))
+            }
+        }
+        assertThat(getPermissionFlags(APP_ID_1, DEVICE_ID_1, USER_ID_0, PERMISSION_NAME_0))
+            .isEqualTo(0)
+        assertThat(getPermissionFlags(APP_ID_1, DEVICE_ID_2, USER_ID_0, PERMISSION_NAME_0))
+            .isEqualTo(PermissionFlags.RUNTIME_GRANTED)
+    }
+
+    @Test
+    fun testOnStateMutated_notEmpty_isCalledForEachListener() {
+        val mockListener =
+                mock<DevicePermissionPolicy.OnDevicePermissionFlagsChangedListener> {}
+        devicePermissionPolicy.addOnPermissionFlagsChangedListener(mockListener)
+
+        GetStateScope(oldState).apply {
+            with(devicePermissionPolicy) {
+                onStateMutated()
+            }
+        }
+
+        verify(mockListener, times(1)).onStateMutated()
+    }
+
+    @Test
+    fun testOnStorageVolumeMounted_trimsPermissionsNotRequestAnymore() {
+        val packageState = mockPackageState(
+            APP_ID_1,
+            mockAndroidPackage(
+                PACKAGE_NAME_1, requestedPermissions = setOf(PERMISSION_NAME_1, PERMISSION_NAME_0)
+            )
+        )
+        addPackageState(packageState)
+        setPermissionFlags(
+            APP_ID_1, DEVICE_ID_1, USER_ID_0, PERMISSION_NAME_1, PermissionFlags.RUNTIME_GRANTED
+        )
+        setPermissionFlags(
+            APP_ID_1, DEVICE_ID_1, USER_ID_0, PERMISSION_NAME_0, PermissionFlags.RUNTIME_GRANTED
+        )
+        assertThat(
+            getPermissionFlags(APP_ID_1, DEVICE_ID_1, USER_ID_0, PERMISSION_NAME_1, oldState)
+        ).isEqualTo(PermissionFlags.RUNTIME_GRANTED)
+        assertThat(
+            getPermissionFlags(APP_ID_1, DEVICE_ID_1, USER_ID_0, PERMISSION_NAME_0, oldState)
+        ).isEqualTo(PermissionFlags.RUNTIME_GRANTED)
+
+        val installedPackageState = mockPackageState(
+                APP_ID_1,
+                mockAndroidPackage(PACKAGE_NAME_1, requestedPermissions = setOf(PERMISSION_NAME_1))
+        )
+        addPackageState(installedPackageState)
+
+        mutateState {
+            with(devicePermissionPolicy) {
+                onStorageVolumeMounted(null, listOf(PACKAGE_NAME_1), false)
+            }
+        }
+
+        assertThat(getPermissionFlags(APP_ID_1, DEVICE_ID_1, USER_ID_0, PERMISSION_NAME_1))
+            .isEqualTo(PermissionFlags.RUNTIME_GRANTED)
+        assertThat(getPermissionFlags(APP_ID_1, DEVICE_ID_1, USER_ID_0, PERMISSION_NAME_0))
+            .isEqualTo(0)
+    }
+
+
+    @Test
+    fun testResetRuntimePermissions_trimsPermissionStates() {
+        val packageState = mockPackageState(
+            APP_ID_1,
+            mockAndroidPackage(PACKAGE_NAME_1, requestedPermissions = setOf(PERMISSION_NAME_1))
+        )
+        addPackageState(packageState)
+        setPermissionFlags(
+            APP_ID_1, DEVICE_ID_1, USER_ID_0, PERMISSION_NAME_1, PermissionFlags.RUNTIME_GRANTED
+        )
+        assertThat(
+            getPermissionFlags(APP_ID_1, DEVICE_ID_1, USER_ID_0, PERMISSION_NAME_1, oldState)
+        ).isEqualTo(PermissionFlags.RUNTIME_GRANTED)
+
+        mutateState {
+            with(devicePermissionPolicy) {
+                resetRuntimePermissions(PACKAGE_NAME_1, USER_ID_0)
+            }
+        }
+        assertThat(getPermissionFlags(APP_ID_1, DEVICE_ID_1, USER_ID_0, PERMISSION_NAME_1))
+                .isEqualTo(0)
+    }
+
+    @Test
+    fun testResetRuntimePermissions_keepsPermissionStates() {
+        val packageState = mockPackageState(
+            APP_ID_1,
+            mockAndroidPackage(
+                PACKAGE_NAME_1,
+                requestedPermissions = setOf(PERMISSION_NAME_1, PERMISSION_NAME_0)
+            )
+        )
+        val packageState2 = mockPackageState(
+            APP_ID_1,
+            mockAndroidPackage(PACKAGE_NAME_2, requestedPermissions = setOf(PERMISSION_NAME_0))
+        )
+        addPackageState(packageState)
+        addPackageState(packageState2)
+        setPermissionFlags(
+            APP_ID_1, DEVICE_ID_1, USER_ID_0, PERMISSION_NAME_1, PermissionFlags.RUNTIME_GRANTED
+        )
+        setPermissionFlags(
+            APP_ID_1, DEVICE_ID_1, USER_ID_0, PERMISSION_NAME_0, PermissionFlags.RUNTIME_GRANTED
+        )
+        assertThat(
+            getPermissionFlags(APP_ID_1, DEVICE_ID_1, USER_ID_0, PERMISSION_NAME_1, oldState)
+        ).isEqualTo(PermissionFlags.RUNTIME_GRANTED)
+        assertThat(
+            getPermissionFlags(APP_ID_1, DEVICE_ID_1, USER_ID_0, PERMISSION_NAME_0, oldState)
+        ).isEqualTo(PermissionFlags.RUNTIME_GRANTED)
+
+        mutateState {
+            with(devicePermissionPolicy) {
+                resetRuntimePermissions(PACKAGE_NAME_1, USER_ID_0)
+            }
+        }
+        assertThat(getPermissionFlags(APP_ID_1, DEVICE_ID_1, USER_ID_0, PERMISSION_NAME_1))
+                .isEqualTo(0)
+        assertThat(getPermissionFlags(APP_ID_1, DEVICE_ID_1, USER_ID_0, PERMISSION_NAME_0))
+                .isEqualTo(PermissionFlags.RUNTIME_GRANTED)
+    }
+
+    private fun getPermissionFlags(
+        appId: Int,
+        deviceId: String,
+        userId: Int,
+        permissionName: String,
+        state: MutableAccessState = newState
+    ): Int = state.userStates[userId]
+                ?.appIdDevicePermissionFlags
+                ?.get(appId)
+                ?.get(deviceId)
+                ?.getWithDefault(permissionName, 0)
+                ?: 0
+
+
+   private fun setPermissionFlags(
+        appId: Int,
+        deviceId: String,
+        userId: Int,
+        permissionName: String,
+        newFlags: Int,
+        state: MutableAccessState = oldState
+    ) {
+       val appIdDevicePermissionFlags =
+           state.mutateUserState(userId)!!.mutateAppIdDevicePermissionFlags()
+       val devicePermissionFlags =
+           appIdDevicePermissionFlags.mutateOrPut(appId) { MutableDevicePermissionFlags() }
+       val permissionFlags =
+           devicePermissionFlags.mutateOrPut(deviceId) { MutableIndexedMap() }
+       permissionFlags.putWithDefault(permissionName, newFlags, 0)
+       if (permissionFlags.isEmpty()) {
+           devicePermissionFlags -= deviceId
+           if (devicePermissionFlags.isEmpty()) {
+               appIdDevicePermissionFlags -= appId
+           }
+       }
+   }
+
+    companion object {
+        private const val DEVICE_ID_1 = "cdm:1"
+        private const val DEVICE_ID_2 = "cdm:2"
+    }
+}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/mode/SettingsObserverTest.kt b/services/tests/displayservicetests/src/com/android/server/display/mode/SettingsObserverTest.kt
new file mode 100644
index 0000000..ebb4f18
--- /dev/null
+++ b/services/tests/displayservicetests/src/com/android/server/display/mode/SettingsObserverTest.kt
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display.mode
+
+import android.content.Context
+import android.content.ContextWrapper
+import android.provider.Settings
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.filters.SmallTest
+import com.android.internal.util.test.FakeSettingsProvider
+import com.android.server.display.feature.DisplayManagerFlags
+import com.android.server.testutils.TestHandler
+import com.google.common.truth.Truth.assertThat
+import com.google.testing.junit.testparameterinjector.TestParameter
+import com.google.testing.junit.testparameterinjector.TestParameterInjector
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito
+import org.mockito.junit.MockitoJUnit
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.whenever
+
+@SmallTest
+@RunWith(TestParameterInjector::class)
+class SettingsObserverTest {
+
+    @get:Rule
+    val mockitoRule = MockitoJUnit.rule()
+
+    @get:Rule
+    val settingsProviderRule = FakeSettingsProvider.rule()
+
+    private lateinit var spyContext: Context
+    private val mockInjector = mock<DisplayModeDirector.Injector>()
+    private val mockFlags = mock<DisplayManagerFlags>()
+
+    private val testHandler = TestHandler(null)
+
+    @Before
+    fun setUp() {
+        spyContext = Mockito.spy(ContextWrapper(ApplicationProvider.getApplicationContext()))
+    }
+
+    @Test
+    fun testLowPowerMode(@TestParameter testCase: SettingsObserverTestCase) {
+        whenever(mockFlags.isVsyncLowPowerVoteEnabled).thenReturn(testCase.vsyncLowPowerVoteEnabled)
+        whenever(spyContext.contentResolver)
+                .thenReturn(settingsProviderRule.mockContentResolver(null))
+        val lowPowerModeSetting = if (testCase.lowPowerModeEnabled) 1 else 0
+        Settings.Global.putInt(
+                spyContext.contentResolver, Settings.Global.LOW_POWER_MODE, lowPowerModeSetting)
+
+        val displayModeDirector = DisplayModeDirector(
+                spyContext, testHandler, mockInjector, mockFlags)
+        val settingsObserver = displayModeDirector.SettingsObserver(
+                spyContext, testHandler, testCase.dvrrSupported, mockFlags)
+
+        settingsObserver.onChange(
+                false, Settings.Global.getUriFor(Settings.Global.LOW_POWER_MODE), 1)
+
+        assertThat(displayModeDirector.getVote(VotesStorage.GLOBAL_ID,
+                Vote.PRIORITY_LOW_POWER_MODE)).isEqualTo(testCase.expectedVote)
+    }
+
+    enum class SettingsObserverTestCase(
+            val dvrrSupported: Boolean,
+            val vsyncLowPowerVoteEnabled: Boolean,
+            val lowPowerModeEnabled: Boolean,
+            internal val expectedVote: Vote?
+    ) {
+        ALL_ENABLED(true, true, true,
+                SupportedModesVote(listOf(
+                        SupportedModesVote.SupportedMode(60f, 240f),
+                        SupportedModesVote.SupportedMode(60f, 60f)
+                ))),
+        LOW_POWER_OFF(true, true, false, null),
+        DVRR_NOT_SUPPORTED_LOW_POWER_ON(false, true, true,
+                RefreshRateVote.RenderVote(0f, 60f)),
+        DVRR_NOT_SUPPORTED_LOW_POWER_OFF(false, true, false, null),
+        VSYNC_VOTE_DISABLED_SUPPORTED_LOW_POWER_ON(true, false, true,
+                RefreshRateVote.RenderVote(0f, 60f)),
+        VSYNC_VOTE_DISABLED_LOW_POWER_OFF(true, false, false, null),
+    }
+}
\ No newline at end of file
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
index 820e44f..0fd424b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
@@ -334,6 +334,7 @@
         final boolean dead = (behavior == ProcessBehavior.DEAD);
 
         final ProcessRecord r = spy(new ProcessRecord(mAms, ai, processName, ai.uid));
+        r.mState = spy(r.mState);
         r.setPid(mNextPid.getAndIncrement());
         mActiveProcesses.add(r);
 
@@ -788,8 +789,8 @@
         }) {
             // Confirm expected OOM adjustments; we were invoked once to upgrade
             // and once to downgrade
-            assertEquals(String.valueOf(receiverApp), ActivityManager.PROCESS_STATE_RECEIVER,
-                    receiverApp.mState.getReportedProcState());
+            verify(receiverApp.mState, times(1).description(String.valueOf(receiverApp)))
+                    .setReportedProcState(ActivityManager.PROCESS_STATE_RECEIVER);
             verify(mAms, times(2)).enqueueOomAdjTargetLocked(eq(receiverApp));
 
             if ((mImpl == Impl.DEFAULT) && (receiverApp == receiverBlueApp)) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java b/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java
index 6906dec..3b83e3c 100644
--- a/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java
@@ -18,7 +18,10 @@
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
 import static com.android.server.app.GameManagerService.CANCEL_GAME_LOADING_MODE;
+import static com.android.server.app.GameManagerService.Injector;
 import static com.android.server.app.GameManagerService.LOADING_BOOST_MAX_DURATION;
+import static com.android.server.app.GameManagerService.PROPERTY_DEBUG_GFX_GAME_DEFAULT_FRAME_RATE_DISABLED;
+import static com.android.server.app.GameManagerService.PROPERTY_RO_SURFACEFLINGER_GAME_DEFAULT_FRAME_RATE;
 import static com.android.server.app.GameManagerService.SET_GAME_STATE;
 import static com.android.server.app.GameManagerService.WRITE_DELAY_MILLIS;
 import static com.android.server.app.GameManagerService.WRITE_GAME_MODE_INTERVENTION_LIST_FILE;
@@ -33,6 +36,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyFloat;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.any;
@@ -72,9 +76,12 @@
 import android.os.PowerManagerInternal;
 import android.os.RemoteException;
 import android.os.UserManager;
+import android.os.test.FakePermissionEnforcer;
 import android.os.test.TestLooper;
 import android.platform.test.annotations.Presubmit;
+import android.platform.test.flag.junit.SetFlagsRule;
 import android.provider.DeviceConfig;
+import android.server.app.Flags;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
@@ -85,6 +92,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
@@ -108,6 +116,7 @@
 @Presubmit
 public class GameManagerServiceTests {
     @Mock MockContext mMockContext;
+    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
     private static final String TAG = "GameManagerServiceTests";
     private static final String PACKAGE_NAME_INVALID = "com.android.app";
     private static final int USER_ID_1 = 1001;
@@ -126,6 +135,11 @@
     private UserManager mMockUserManager;
     private BroadcastReceiver mShutDownActionReceiver;
 
+    private FakePermissionEnforcer mFakePermissionEnforcer = new FakePermissionEnforcer();
+
+    @Mock
+    private GameManagerServiceSystemPropertiesWrapper mSysPropsMock;
+
     @Captor
     ArgumentCaptor<IBinder.DeathRecipient> mDeathRecipientCaptor;
 
@@ -193,6 +207,8 @@
             switch (name) {
                 case Context.USER_SERVICE:
                     return mMockUserManager;
+                case Context.PERMISSION_ENFORCER_SERVICE:
+                    return mFakePermissionEnforcer;
             }
             throw new UnsupportedOperationException("Couldn't find system service: " + name);
         }
@@ -222,6 +238,8 @@
         when(mMockPackageManager.getPackageUidAsUser(mPackageName, USER_ID_1)).thenReturn(
                 DEFAULT_PACKAGE_UID);
         LocalServices.addService(PowerManagerInternal.class, mMockPowerManager);
+
+        mSetFlagsRule.enableFlags(Flags.FLAG_GAME_DEFAULT_FRAME_RATE);
     }
 
     private void mockAppCategory(String packageName, @ApplicationInfo.Category int category)
@@ -1695,9 +1713,8 @@
         mockModifyGameModeGranted();
         final Context context = InstrumentationRegistry.getContext();
         GameManagerService gameManagerService =
-                new GameManagerService(mMockContext,
-                        mTestLooper.getLooper(),
-                        context.getFilesDir());
+                new GameManagerService(mMockContext, mTestLooper.getLooper(), context.getFilesDir(),
+                        new Injector());
         startUser(gameManagerService, USER_ID_1);
         startUser(gameManagerService, USER_ID_2);
 
@@ -1786,7 +1803,7 @@
         mockDeviceConfigBattery();
         final Context context = InstrumentationRegistry.getContext();
         GameManagerService gameManagerService = new GameManagerService(mMockContext,
-                mTestLooper.getLooper(), context.getFilesDir());
+                mTestLooper.getLooper(), context.getFilesDir(), new Injector());
         startUser(gameManagerService, USER_ID_1);
         startUser(gameManagerService, USER_ID_2);
         gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_BATTERY, USER_ID_1);
@@ -1962,7 +1979,7 @@
         assertTrue(
                 gameManagerService.mHandler.hasEqualMessages(WRITE_GAME_MODE_INTERVENTION_LIST_FILE,
                         USER_ID_1));
-        Mockito.verify(gameManagerService).setOverrideFrameRate(
+        Mockito.verify(gameManagerService).setGameModeFrameRateOverride(
                 ArgumentMatchers.eq(DEFAULT_PACKAGE_UID),
                 ArgumentMatchers.eq(60.0f));
         checkFps(gameManagerService, GameManager.GAME_MODE_CUSTOM, 60);
@@ -2035,7 +2052,7 @@
                 mTestLooper.getLooper()));
         startUser(gameManagerService, USER_ID_1);
         gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_PERFORMANCE, USER_ID_1);
-        Mockito.verify(gameManagerService).setOverrideFrameRate(
+        Mockito.verify(gameManagerService).setGameModeFrameRateOverride(
                 ArgumentMatchers.eq(DEFAULT_PACKAGE_UID),
                 ArgumentMatchers.eq(90.0f));
         checkFps(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 90);
@@ -2044,7 +2061,7 @@
         when(DeviceConfig.getProperty(anyString(), anyString()))
                 .thenReturn(configStringAfter);
         gameManagerService.updateConfigsForUser(USER_ID_1, false, mPackageName);
-        Mockito.verify(gameManagerService).setOverrideFrameRate(
+        Mockito.verify(gameManagerService).setGameModeFrameRateOverride(
                 ArgumentMatchers.eq(DEFAULT_PACKAGE_UID),
                 ArgumentMatchers.eq(0.0f));
     }
@@ -2061,14 +2078,14 @@
                 mTestLooper.getLooper()));
         startUser(gameManagerService, USER_ID_1);
         gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_PERFORMANCE, USER_ID_1);
-        Mockito.verify(gameManagerService).setOverrideFrameRate(
+        Mockito.verify(gameManagerService).setGameModeFrameRateOverride(
                 ArgumentMatchers.eq(DEFAULT_PACKAGE_UID),
                 ArgumentMatchers.eq(90.0f));
         checkFps(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 90);
 
         mockInterventionsDisabledNoOptInFromXml();
         gameManagerService.updateConfigsForUser(USER_ID_1, false, mPackageName);
-        Mockito.verify(gameManagerService).setOverrideFrameRate(
+        Mockito.verify(gameManagerService).setGameModeFrameRateOverride(
                 ArgumentMatchers.eq(DEFAULT_PACKAGE_UID),
                 ArgumentMatchers.eq(0.0f));
         checkFps(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 0);
@@ -2087,14 +2104,14 @@
         startUser(gameManagerService, USER_ID_1);
 
         gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_PERFORMANCE, USER_ID_1);
-        Mockito.verify(gameManagerService).setOverrideFrameRate(
+        Mockito.verify(gameManagerService).setGameModeFrameRateOverride(
                 ArgumentMatchers.eq(DEFAULT_PACKAGE_UID),
                 ArgumentMatchers.eq(90.0f));
         checkFps(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 90);
 
         mockInterventionsEnabledAllOptInFromXml();
         gameManagerService.updateConfigsForUser(USER_ID_1, false, mPackageName);
-        Mockito.verify(gameManagerService).setOverrideFrameRate(
+        Mockito.verify(gameManagerService).setGameModeFrameRateOverride(
                 ArgumentMatchers.eq(DEFAULT_PACKAGE_UID),
                 ArgumentMatchers.eq(0.0f));
     }
@@ -2390,4 +2407,115 @@
                 DEFAULT_PACKAGE_UID, ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND, 0, 0);
         verify(mMockPowerManager, times(0)).setPowerMode(Mode.GAME, false);
     }
+
+    @Test
+    public void testGameDefaultFrameRate_FlagOn() throws Exception {
+        mFakePermissionEnforcer.grant(Manifest.permission.MANAGE_GAME_MODE);
+
+        GameManagerService gameManagerService = Mockito.spy(
+                new GameManagerService(mMockContext, mTestLooper.getLooper(),
+                        InstrumentationRegistry.getContext().getFilesDir(),
+                        new Injector(){
+                            @Override
+                            public GameManagerServiceSystemPropertiesWrapper
+                                    createSystemPropertiesWrapper() {
+                                return mSysPropsMock;
+                            }
+                        }));
+
+        when(mSysPropsMock.getInt(
+                ArgumentMatchers.eq(PROPERTY_RO_SURFACEFLINGER_GAME_DEFAULT_FRAME_RATE),
+                anyInt())).thenReturn(60);
+        when(mSysPropsMock.getBoolean(
+                ArgumentMatchers.eq(PROPERTY_DEBUG_GFX_GAME_DEFAULT_FRAME_RATE_DISABLED),
+                ArgumentMatchers.eq(false))).thenReturn(false);
+        gameManagerService.onBootCompleted();
+
+        // Set up a game in the foreground.
+        String[] packages = {mPackageName};
+        when(mMockPackageManager.getPackagesForUid(DEFAULT_PACKAGE_UID)).thenReturn(packages);
+        gameManagerService.mUidObserver.onUidStateChanged(
+                DEFAULT_PACKAGE_UID, ActivityManager.PROCESS_STATE_TOP, 0, 0);
+
+        // Toggle game default frame rate on.
+        gameManagerService.toggleGameDefaultFrameRate(true);
+
+        // Verify that:
+        // setDefaultFrameRateOverride is called with correct arguments
+        Mockito.verify(gameManagerService, times(1))
+                .setGameDefaultFrameRateOverride(ArgumentMatchers.eq(DEFAULT_PACKAGE_UID),
+                                                 ArgumentMatchers.eq(60.0f));
+
+        // Adding another game to the foreground.
+        String anotherGamePkg = "another.game";
+        String[] packages2 = {anotherGamePkg};
+        mockAppCategory(anotherGamePkg, ApplicationInfo.CATEGORY_GAME);
+        int somePackageId = DEFAULT_PACKAGE_UID + 1;
+        when(mMockPackageManager.getPackagesForUid(somePackageId)).thenReturn(packages2);
+
+        gameManagerService.mUidObserver.onUidStateChanged(
+                somePackageId, ActivityManager.PROCESS_STATE_TOP, 0, 0);
+
+        // Toggle game default frame rate off.
+        gameManagerService.toggleGameDefaultFrameRate(false);
+
+        // Verify that:
+        // setDefaultFrameRateOverride is called with correct arguments
+        Mockito.verify(gameManagerService).setGameDefaultFrameRateOverride(
+                ArgumentMatchers.eq(DEFAULT_PACKAGE_UID), ArgumentMatchers.eq(0.0f));
+        Mockito.verify(gameManagerService).setGameDefaultFrameRateOverride(
+                ArgumentMatchers.eq(somePackageId), ArgumentMatchers.eq(0.0f));
+    }
+
+    @Test
+    public void testGameDefaultFrameRate_FlagOff() throws Exception {
+        mSetFlagsRule.disableFlags(Flags.FLAG_GAME_DEFAULT_FRAME_RATE);
+        mFakePermissionEnforcer.grant(Manifest.permission.MANAGE_GAME_MODE);
+
+        GameManagerService gameManagerService = Mockito.spy(
+                new GameManagerService(mMockContext, mTestLooper.getLooper(),
+                        InstrumentationRegistry.getContext().getFilesDir(),
+                        new Injector(){
+                            @Override
+                            public GameManagerServiceSystemPropertiesWrapper
+                                    createSystemPropertiesWrapper() {
+                                return mSysPropsMock;
+                            }
+                        }));
+
+        // Set up a game in the foreground.
+        String[] packages = {mPackageName};
+        when(mMockPackageManager.getPackagesForUid(DEFAULT_PACKAGE_UID)).thenReturn(packages);
+        gameManagerService.mUidObserver.onUidStateChanged(
+                DEFAULT_PACKAGE_UID, ActivityManager.PROCESS_STATE_TOP, 0, 0);
+
+        // Toggle game default frame rate on.
+        when(mSysPropsMock.getInt(
+                ArgumentMatchers.eq(PROPERTY_RO_SURFACEFLINGER_GAME_DEFAULT_FRAME_RATE),
+                anyInt())).thenReturn(60);
+
+        gameManagerService.toggleGameDefaultFrameRate(true);
+
+        // Verify that:
+        // setGameDefaultFrameRateOverride() should never be called if the flag is disabled.
+        Mockito.verify(gameManagerService, never())
+                .setGameDefaultFrameRateOverride(anyInt(), anyFloat());
+
+        // Toggle game default frame rate off.
+        String anotherGamePkg = "another.game";
+        String[] packages2 = {anotherGamePkg};
+        mockAppCategory(anotherGamePkg, ApplicationInfo.CATEGORY_GAME);
+        int somePackageId = DEFAULT_PACKAGE_UID + 1;
+        when(mMockPackageManager.getPackagesForUid(somePackageId)).thenReturn(packages2);
+        gameManagerService.mUidObserver.onUidStateChanged(
+                somePackageId, ActivityManager.PROCESS_STATE_TOP, 0, 0);
+        gameManagerService.mUidObserver.onUidStateChanged(
+                somePackageId, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0, 0);
+
+        gameManagerService.toggleGameDefaultFrameRate(false);
+        // Verify that:
+        // setGameDefaultFrameRateOverride() should never be called if the flag is disabled.
+        Mockito.verify(gameManagerService, never())
+                .setGameDefaultFrameRateOverride(anyInt(), anyFloat());
+    }
 }
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/BackgroundJobsControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/BackgroundJobsControllerTest.java
index cdae8c6..00fe3d9 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/BackgroundJobsControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/BackgroundJobsControllerTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 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.
@@ -25,6 +25,7 @@
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -167,6 +168,15 @@
     }
 
     private void setStoppedState(int uid, String pkgName, boolean stopped) {
+        try {
+            doReturn(stopped).when(mPackageManagerInternal).isPackageStopped(pkgName, uid);
+            sendPackageStoppedBroadcast(uid, pkgName, stopped);
+        } catch (PackageManager.NameNotFoundException e) {
+            fail("Unable to set stopped state for unknown package: " + pkgName);
+        }
+    }
+
+    private void sendPackageStoppedBroadcast(int uid, String pkgName, boolean stopped) {
         Intent intent = new Intent(
                 stopped ? Intent.ACTION_PACKAGE_RESTARTED : Intent.ACTION_PACKAGE_UNSTOPPED);
         intent.putExtra(Intent.EXTRA_UID, uid);
@@ -174,14 +184,6 @@
         mStoppedReceiver.onReceive(mContext, intent);
     }
 
-    private void setUidBias(int uid, int bias) {
-        int prevBias = mJobSchedulerService.getUidBias(uid);
-        doReturn(bias).when(mJobSchedulerService).getUidBias(uid);
-        synchronized (mBackgroundJobsController.mLock) {
-            mBackgroundJobsController.onUidBiasChangedLocked(uid, prevBias, bias);
-        }
-    }
-
     private void trackJobs(JobStatus... jobs) {
         for (JobStatus job : jobs) {
             mJobStore.add(job);
@@ -208,6 +210,47 @@
     }
 
     @Test
+    public void testRestartedBroadcastWithoutStopping() {
+        mSetFlagsRule.enableFlags(android.content.pm.Flags.FLAG_STAY_STOPPED);
+        // Scheduled by SOURCE_UID:SOURCE_PACKAGE for itself.
+        JobStatus directJob1 = createJobStatus("testStopped", SOURCE_PACKAGE, SOURCE_UID,
+                createBaseJobInfoBuilder(SOURCE_PACKAGE, 1).build());
+        // Scheduled by ALTERNATE_UID:ALTERNATE_SOURCE_PACKAGE for itself.
+        JobStatus directJob2 = createJobStatus("testStopped",
+                ALTERNATE_SOURCE_PACKAGE, ALTERNATE_UID,
+                createBaseJobInfoBuilder(ALTERNATE_SOURCE_PACKAGE, 2).build());
+        // Scheduled by CALLING_PACKAGE for SOURCE_PACKAGE.
+        JobStatus proxyJob1 = createJobStatus("testStopped", SOURCE_PACKAGE, CALLING_UID,
+                createBaseJobInfoBuilder(CALLING_PACKAGE, 3).build());
+        // Scheduled by CALLING_PACKAGE for ALTERNATE_SOURCE_PACKAGE.
+        JobStatus proxyJob2 = createJobStatus("testStopped",
+                ALTERNATE_SOURCE_PACKAGE, CALLING_UID,
+                createBaseJobInfoBuilder(CALLING_PACKAGE, 4).build());
+
+        trackJobs(directJob1, directJob2, proxyJob1, proxyJob2);
+
+        sendPackageStoppedBroadcast(ALTERNATE_UID, ALTERNATE_SOURCE_PACKAGE, true);
+        assertTrue(directJob1.isConstraintSatisfied(CONSTRAINT_BACKGROUND_NOT_RESTRICTED));
+        assertFalse(directJob1.isUserBgRestricted());
+        assertTrue(directJob2.isConstraintSatisfied(CONSTRAINT_BACKGROUND_NOT_RESTRICTED));
+        assertFalse(directJob2.isUserBgRestricted());
+        assertTrue(proxyJob1.isConstraintSatisfied(CONSTRAINT_BACKGROUND_NOT_RESTRICTED));
+        assertFalse(proxyJob1.isUserBgRestricted());
+        assertTrue(proxyJob2.isConstraintSatisfied(CONSTRAINT_BACKGROUND_NOT_RESTRICTED));
+        assertFalse(proxyJob2.isUserBgRestricted());
+
+        sendPackageStoppedBroadcast(ALTERNATE_UID, ALTERNATE_SOURCE_PACKAGE, false);
+        assertTrue(directJob1.isConstraintSatisfied(CONSTRAINT_BACKGROUND_NOT_RESTRICTED));
+        assertFalse(directJob1.isUserBgRestricted());
+        assertTrue(directJob2.isConstraintSatisfied(CONSTRAINT_BACKGROUND_NOT_RESTRICTED));
+        assertFalse(directJob2.isUserBgRestricted());
+        assertTrue(proxyJob1.isConstraintSatisfied(CONSTRAINT_BACKGROUND_NOT_RESTRICTED));
+        assertFalse(proxyJob1.isUserBgRestricted());
+        assertTrue(proxyJob2.isConstraintSatisfied(CONSTRAINT_BACKGROUND_NOT_RESTRICTED));
+        assertFalse(proxyJob2.isUserBgRestricted());
+    }
+
+    @Test
     public void testStopped_disabled() {
         mSetFlagsRule.disableFlags(android.content.pm.Flags.FLAG_STAY_STOPPED);
         // Scheduled by SOURCE_UID:SOURCE_PACKAGE for itself.
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java
index 4fb9472..650c473 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java
@@ -30,15 +30,16 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
 import static com.android.server.job.controllers.FlexibilityController.FcConfig.DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_MS;
 import static com.android.server.job.controllers.FlexibilityController.FcConfig.DEFAULT_UNSEEN_CONSTRAINT_GRACE_PERIOD_MS;
+import static com.android.server.job.controllers.FlexibilityController.FcConfig.KEY_APPLIED_CONSTRAINTS;
 import static com.android.server.job.controllers.FlexibilityController.FcConfig.KEY_DEADLINE_PROXIMITY_LIMIT;
 import static com.android.server.job.controllers.FlexibilityController.FcConfig.KEY_FALLBACK_FLEXIBILITY_DEADLINE;
-import static com.android.server.job.controllers.FlexibilityController.FcConfig.KEY_FLEXIBILITY_ENABLED;
 import static com.android.server.job.controllers.FlexibilityController.FcConfig.KEY_PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS;
-import static com.android.server.job.controllers.FlexibilityController.NUM_FLEXIBLE_CONSTRAINTS;
+import static com.android.server.job.controllers.FlexibilityController.FLEXIBLE_CONSTRAINTS;
 import static com.android.server.job.controllers.FlexibilityController.SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS;
 import static com.android.server.job.controllers.JobStatus.CONSTRAINT_BATTERY_NOT_LOW;
 import static com.android.server.job.controllers.JobStatus.CONSTRAINT_CHARGING;
 import static com.android.server.job.controllers.JobStatus.CONSTRAINT_CONNECTIVITY;
+import static com.android.server.job.controllers.JobStatus.CONSTRAINT_CONTENT_TRIGGER;
 import static com.android.server.job.controllers.JobStatus.CONSTRAINT_FLEXIBLE;
 import static com.android.server.job.controllers.JobStatus.CONSTRAINT_IDLE;
 import static com.android.server.job.controllers.JobStatus.MIN_WINDOW_FOR_FLEXIBILITY_MS;
@@ -66,6 +67,7 @@
 import android.provider.DeviceConfig;
 import android.util.ArraySet;
 
+import com.android.server.AppSchedulingModuleThread;
 import com.android.server.LocalServices;
 import com.android.server.job.JobSchedulerService;
 import com.android.server.job.JobStore;
@@ -129,6 +131,7 @@
         when(mContext.getPackageManager()).thenReturn(mPackageManager);
         when(mPackageManager.hasSystemFeature(
                 PackageManager.FEATURE_AUTOMOTIVE)).thenReturn(false);
+        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_EMBEDDED)).thenReturn(false);
         // Used in FlexibilityController.FcConstants.
         doAnswer((Answer<Void>) invocationOnMock -> null)
                 .when(() -> DeviceConfig.addOnPropertiesChangedListener(
@@ -161,7 +164,8 @@
 
         setDeviceConfigString(KEY_PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS, "50,60,70,80");
         setDeviceConfigLong(KEY_DEADLINE_PROXIMITY_LIMIT, 0L);
-        setDeviceConfigBoolean(KEY_FLEXIBILITY_ENABLED, true);
+        setDeviceConfigInt(KEY_APPLIED_CONSTRAINTS, FLEXIBLE_CONSTRAINTS);
+        waitForQuietModuleThread();
     }
 
     @After
@@ -171,17 +175,22 @@
         }
     }
 
-    private void setDeviceConfigBoolean(String key, boolean val) {
-        mDeviceConfigPropertiesBuilder.setBoolean(key, val);
-        synchronized (mFlexibilityController.mLock) {
-            mFlexibilityController.prepareForUpdatedConstantsLocked();
-            mFcConfig.processConstantLocked(mDeviceConfigPropertiesBuilder.build(), key);
-            mFlexibilityController.onConstantsUpdatedLocked();
-        }
+    private void setDeviceConfigInt(String key, int val) {
+        mDeviceConfigPropertiesBuilder.setInt(key, val);
+        updateDeviceConfig(key);
     }
 
     private void setDeviceConfigLong(String key, Long val) {
         mDeviceConfigPropertiesBuilder.setLong(key, val);
+        updateDeviceConfig(key);
+    }
+
+    private void setDeviceConfigString(String key, String val) {
+        mDeviceConfigPropertiesBuilder.setString(key, val);
+        updateDeviceConfig(key);
+    }
+
+    private void updateDeviceConfig(String key) {
         synchronized (mFlexibilityController.mLock) {
             mFlexibilityController.prepareForUpdatedConstantsLocked();
             mFcConfig.processConstantLocked(mDeviceConfigPropertiesBuilder.build(), key);
@@ -189,13 +198,9 @@
         }
     }
 
-    private void setDeviceConfigString(String key, String val) {
-        mDeviceConfigPropertiesBuilder.setString(key, val);
-        synchronized (mFlexibilityController.mLock) {
-            mFlexibilityController.prepareForUpdatedConstantsLocked();
-            mFcConfig.processConstantLocked(mDeviceConfigPropertiesBuilder.build(), key);
-            mFlexibilityController.onConstantsUpdatedLocked();
-        }
+    private void waitForQuietModuleThread() {
+        assertTrue("Failed to wait for quiet module thread",
+                AppSchedulingModuleThread.getHandler().runWithScissors(() -> {}, 10_000L));
     }
 
     private static JobInfo.Builder createJob(int id) {
@@ -207,6 +212,10 @@
         JobStatus js = JobStatus.createFromJobInfo(
                 jobInfo, 1000, SOURCE_PACKAGE, SOURCE_USER_ID, "FCTest", testTag);
         js.enqueueTime = FROZEN_TIME;
+        if (js.hasFlexibilityConstraint()) {
+            js.setNumAppliedFlexibleConstraints(Integer.bitCount(
+                    mFlexibilityController.getRelevantAppliedConstraintsLocked(js)));
+        }
         return js;
     }
 
@@ -215,18 +224,120 @@
      */
     @Test
     public void testDefaultVariableValues() {
-        assertEquals(NUM_FLEXIBLE_CONSTRAINTS,
+        assertEquals(Integer.bitCount(FLEXIBLE_CONSTRAINTS),
                 mFlexibilityController.mFcConfig.DEFAULT_PERCENT_TO_DROP_FLEXIBLE_CONSTRAINTS.length
         );
     }
 
     @Test
-    public void testOnConstantsUpdated_DefaultFlexibility() {
+    public void testAppliedConstraints() {
+        setDeviceConfigInt(KEY_APPLIED_CONSTRAINTS, FLEXIBLE_CONSTRAINTS);
+
+        // Add connectivity to require 4 constraints
+        JobStatus connJs = createJobStatus("testAppliedConstraints",
+                createJob(0).setRequiredNetworkType(NETWORK_TYPE_ANY));
+        JobStatus nonConnJs = createJobStatus("testAppliedConstraints",
+                createJob(1).setRequiredNetworkType(NETWORK_TYPE_NONE));
+
+        mFlexibilityController.maybeStartTrackingJobLocked(connJs, null);
+        mFlexibilityController.maybeStartTrackingJobLocked(nonConnJs, null);
+
+        assertEquals(4, connJs.getNumAppliedFlexibleConstraints());
+        assertEquals(3, nonConnJs.getNumAppliedFlexibleConstraints());
+
+        mFlexibilityController.setConstraintSatisfied(
+                CONSTRAINT_BATTERY_NOT_LOW, true,
+                JobSchedulerService.sElapsedRealtimeClock.millis() - HOUR_IN_MILLIS);
+        mFlexibilityController.setConstraintSatisfied(
+                CONSTRAINT_CHARGING, false,
+                JobSchedulerService.sElapsedRealtimeClock.millis() - HOUR_IN_MILLIS);
+        mFlexibilityController.setConstraintSatisfied(
+                CONSTRAINT_IDLE, false,
+                JobSchedulerService.sElapsedRealtimeClock.millis() - HOUR_IN_MILLIS);
+        mFlexibilityController.setConstraintSatisfied(
+                CONSTRAINT_CONNECTIVITY, true,
+                JobSchedulerService.sElapsedRealtimeClock.millis() - HOUR_IN_MILLIS);
+        connJs.setTransportAffinitiesSatisfied(true);
+
+        synchronized (mFlexibilityController.mLock) {
+            assertFalse(mFlexibilityController.hasEnoughSatisfiedConstraintsLocked(connJs));
+            assertFalse(mFlexibilityController.hasEnoughSatisfiedConstraintsLocked(nonConnJs));
+        }
+
+        setDeviceConfigInt(KEY_APPLIED_CONSTRAINTS,
+                CONSTRAINT_BATTERY_NOT_LOW | CONSTRAINT_CONNECTIVITY);
+        waitForQuietModuleThread();
+
+        // Only battery-not-low (which is satisfied) applies to the non-connectivity job, so it
+        // should be able to run.
+        assertEquals(2, connJs.getNumAppliedFlexibleConstraints());
+        assertEquals(1, nonConnJs.getNumAppliedFlexibleConstraints());
+        synchronized (mFlexibilityController.mLock) {
+            assertTrue(mFlexibilityController.hasEnoughSatisfiedConstraintsLocked(connJs));
+            assertTrue(mFlexibilityController.hasEnoughSatisfiedConstraintsLocked(nonConnJs));
+        }
+
+        setDeviceConfigInt(KEY_APPLIED_CONSTRAINTS, CONSTRAINT_BATTERY_NOT_LOW);
+        waitForQuietModuleThread();
+
+        assertEquals(1, connJs.getNumAppliedFlexibleConstraints());
+        assertEquals(1, nonConnJs.getNumAppliedFlexibleConstraints());
+        synchronized (mFlexibilityController.mLock) {
+            assertTrue(mFlexibilityController.hasEnoughSatisfiedConstraintsLocked(connJs));
+            assertTrue(mFlexibilityController.hasEnoughSatisfiedConstraintsLocked(nonConnJs));
+        }
+
+        setDeviceConfigInt(KEY_APPLIED_CONSTRAINTS, CONSTRAINT_CONNECTIVITY);
+        waitForQuietModuleThread();
+
+        // No constraints apply to the non-connectivity job, so it should be able to run.
+        assertEquals(1, connJs.getNumAppliedFlexibleConstraints());
+        assertEquals(0, nonConnJs.getNumAppliedFlexibleConstraints());
+        synchronized (mFlexibilityController.mLock) {
+            assertTrue(mFlexibilityController.hasEnoughSatisfiedConstraintsLocked(connJs));
+            assertTrue(mFlexibilityController.hasEnoughSatisfiedConstraintsLocked(nonConnJs));
+        }
+
+        setDeviceConfigInt(KEY_APPLIED_CONSTRAINTS, CONSTRAINT_CHARGING);
+        waitForQuietModuleThread();
+
+        assertEquals(1, connJs.getNumAppliedFlexibleConstraints());
+        assertEquals(1, nonConnJs.getNumAppliedFlexibleConstraints());
+        synchronized (mFlexibilityController.mLock) {
+            assertFalse(mFlexibilityController.hasEnoughSatisfiedConstraintsLocked(connJs));
+            assertFalse(mFlexibilityController.hasEnoughSatisfiedConstraintsLocked(nonConnJs));
+        }
+
+        setDeviceConfigInt(KEY_APPLIED_CONSTRAINTS, 0);
+        waitForQuietModuleThread();
+
+        // No constraints apply, so they should be able to run.
+        assertEquals(0, connJs.getNumAppliedFlexibleConstraints());
+        assertEquals(0, nonConnJs.getNumAppliedFlexibleConstraints());
+        synchronized (mFlexibilityController.mLock) {
+            assertTrue(mFlexibilityController.hasEnoughSatisfiedConstraintsLocked(connJs));
+            assertTrue(mFlexibilityController.hasEnoughSatisfiedConstraintsLocked(nonConnJs));
+        }
+
+        // Invalid constraint to apply.
+        setDeviceConfigInt(KEY_APPLIED_CONSTRAINTS, CONSTRAINT_CONTENT_TRIGGER);
+        waitForQuietModuleThread();
+
+        // No constraints apply, so they should be able to run.
+        assertEquals(0, connJs.getNumAppliedFlexibleConstraints());
+        assertEquals(0, nonConnJs.getNumAppliedFlexibleConstraints());
+        synchronized (mFlexibilityController.mLock) {
+            assertTrue(mFlexibilityController.hasEnoughSatisfiedConstraintsLocked(connJs));
+            assertTrue(mFlexibilityController.hasEnoughSatisfiedConstraintsLocked(nonConnJs));
+        }
+    }
+
+    @Test
+    public void testOnConstantsUpdated_AppliedConstraints() {
         JobStatus js = createJobStatus("testDefaultFlexibilityConfig", createJob(0));
-        assertFalse(mFlexibilityController.isFlexibilitySatisfiedLocked(js));
-        setDeviceConfigBoolean(KEY_FLEXIBILITY_ENABLED, false);
+        setDeviceConfigInt(KEY_APPLIED_CONSTRAINTS, 0);
         assertTrue(mFlexibilityController.isFlexibilitySatisfiedLocked(js));
-        setDeviceConfigBoolean(KEY_FLEXIBILITY_ENABLED, true);
+        setDeviceConfigInt(KEY_APPLIED_CONSTRAINTS, FLEXIBLE_CONSTRAINTS);
         assertFalse(mFlexibilityController.isFlexibilitySatisfiedLocked(js));
     }
 
@@ -261,10 +372,10 @@
                 new int[] {10, 20, 30, 40});
         assertEquals(FROZEN_TIME + MIN_WINDOW_FOR_FLEXIBILITY_MS / 10,
                 mFlexibilityController.getNextConstraintDropTimeElapsedLocked(js));
-        js.adjustNumRequiredFlexibleConstraints(-1);
+        js.setNumDroppedFlexibleConstraints(1);
         assertEquals(FROZEN_TIME + MIN_WINDOW_FOR_FLEXIBILITY_MS / 10 * 2,
                 mFlexibilityController.getNextConstraintDropTimeElapsedLocked(js));
-        js.adjustNumRequiredFlexibleConstraints(-1);
+        js.setNumDroppedFlexibleConstraints(2);
         assertEquals(FROZEN_TIME + MIN_WINDOW_FOR_FLEXIBILITY_MS / 10 * 3,
                 mFlexibilityController.getNextConstraintDropTimeElapsedLocked(js));
     }
@@ -303,12 +414,12 @@
                 .getNextConstraintDropTimeElapsedLocked(js);
         assertEquals(FROZEN_TIME + MIN_WINDOW_FOR_FLEXIBILITY_MS / 10 * 5,
                 nextTimeToDropNumConstraints);
-        js.adjustNumRequiredFlexibleConstraints(-1);
+        js.setNumDroppedFlexibleConstraints(1);
         nextTimeToDropNumConstraints = mFlexibilityController
                 .getNextConstraintDropTimeElapsedLocked(js);
         assertEquals(FROZEN_TIME + MIN_WINDOW_FOR_FLEXIBILITY_MS / 10 * 6,
                 nextTimeToDropNumConstraints);
-        js.adjustNumRequiredFlexibleConstraints(-1);
+        js.setNumDroppedFlexibleConstraints(2);
         nextTimeToDropNumConstraints = mFlexibilityController
                 .getNextConstraintDropTimeElapsedLocked(js);
         assertEquals(FROZEN_TIME + MIN_WINDOW_FOR_FLEXIBILITY_MS / 10 * 7,
@@ -321,11 +432,11 @@
         nextTimeToDropNumConstraints = mFlexibilityController
                 .getNextConstraintDropTimeElapsedLocked(js);
         assertEquals(130400100, nextTimeToDropNumConstraints);
-        js.adjustNumRequiredFlexibleConstraints(-1);
+        js.setNumDroppedFlexibleConstraints(1);
         nextTimeToDropNumConstraints = mFlexibilityController
                 .getNextConstraintDropTimeElapsedLocked(js);
         assertEquals(156320100L, nextTimeToDropNumConstraints);
-        js.adjustNumRequiredFlexibleConstraints(-1);
+        js.setNumDroppedFlexibleConstraints(2);
         nextTimeToDropNumConstraints = mFlexibilityController
                 .getNextConstraintDropTimeElapsedLocked(js);
         assertEquals(182240100L, nextTimeToDropNumConstraints);
@@ -337,11 +448,11 @@
         nextTimeToDropNumConstraints = mFlexibilityController
                 .getNextConstraintDropTimeElapsedLocked(js);
         assertEquals(129600100, nextTimeToDropNumConstraints);
-        js.adjustNumRequiredFlexibleConstraints(-1);
+        js.setNumDroppedFlexibleConstraints(1);
         nextTimeToDropNumConstraints = mFlexibilityController
                 .getNextConstraintDropTimeElapsedLocked(js);
         assertEquals(155520100L, nextTimeToDropNumConstraints);
-        js.adjustNumRequiredFlexibleConstraints(-1);
+        js.setNumDroppedFlexibleConstraints(2);
         nextTimeToDropNumConstraints = mFlexibilityController
                 .getNextConstraintDropTimeElapsedLocked(js);
         assertEquals(181440100L, nextTimeToDropNumConstraints);
@@ -357,12 +468,12 @@
                 .getNextConstraintDropTimeElapsedLocked(js);
         assertEquals(windowStart + MIN_WINDOW_FOR_FLEXIBILITY_MS / 10 * 5,
                 nextTimeToDropNumConstraints);
-        js.adjustNumRequiredFlexibleConstraints(-1);
+        js.setNumDroppedFlexibleConstraints(1);
         nextTimeToDropNumConstraints = mFlexibilityController
                 .getNextConstraintDropTimeElapsedLocked(js);
         assertEquals(windowStart + MIN_WINDOW_FOR_FLEXIBILITY_MS / 10 * 6,
                 nextTimeToDropNumConstraints);
-        js.adjustNumRequiredFlexibleConstraints(-1);
+        js.setNumDroppedFlexibleConstraints(2);
         nextTimeToDropNumConstraints = mFlexibilityController
                 .getNextConstraintDropTimeElapsedLocked(js);
         assertEquals(windowStart + MIN_WINDOW_FOR_FLEXIBILITY_MS / 10 * 7,
@@ -580,10 +691,10 @@
     }
 
     @Test
-    public void testWontStopJobFromRunning() {
-        JobStatus js = createJobStatus("testWontStopJobFromRunning", createJob(101));
+    public void testWontStopAlreadyRunningJob() {
+        JobStatus js = createJobStatus("testWontStopAlreadyRunningJob", createJob(101));
         // Stop satisfied constraints from causing a false positive.
-        js.adjustNumRequiredFlexibleConstraints(100);
+        js.setNumAppliedFlexibleConstraints(100);
         synchronized (mFlexibilityController.mLock) {
             when(mJobSchedulerService.isCurrentlyRunningLocked(js)).thenReturn(true);
             assertTrue(mFlexibilityController.isFlexibilitySatisfiedLocked(js));
@@ -593,10 +704,9 @@
     @Test
     public void testFlexibilityTracker() {
         FlexibilityController.FlexibilityTracker flexTracker =
-                mFlexibilityController.new
-                        FlexibilityTracker(NUM_FLEXIBLE_CONSTRAINTS);
+                mFlexibilityController.new FlexibilityTracker(4);
         // Plus one for jobs with 0 required constraint.
-        assertEquals(NUM_FLEXIBLE_CONSTRAINTS + 1, flexTracker.size());
+        assertEquals(4 + 1, flexTracker.size());
         JobStatus[] jobs = new JobStatus[4];
         JobInfo.Builder jb;
         for (int i = 0; i < jobs.length; i++) {
@@ -622,21 +732,21 @@
             assertEquals(3, trackedJobs.get(3).size());
             assertEquals(0, trackedJobs.get(4).size());
 
-            flexTracker.adjustJobsRequiredConstraints(jobs[0], -1, FROZEN_TIME);
+            flexTracker.setNumDroppedFlexibleConstraints(jobs[0], 1);
             assertEquals(1, trackedJobs.get(0).size());
             assertEquals(0, trackedJobs.get(1).size());
             assertEquals(1, trackedJobs.get(2).size());
             assertEquals(2, trackedJobs.get(3).size());
             assertEquals(0, trackedJobs.get(4).size());
 
-            flexTracker.adjustJobsRequiredConstraints(jobs[0], -1, FROZEN_TIME);
+            flexTracker.setNumDroppedFlexibleConstraints(jobs[0], 2);
             assertEquals(1, trackedJobs.get(0).size());
             assertEquals(1, trackedJobs.get(1).size());
             assertEquals(0, trackedJobs.get(2).size());
             assertEquals(2, trackedJobs.get(3).size());
             assertEquals(0, trackedJobs.get(4).size());
 
-            flexTracker.adjustJobsRequiredConstraints(jobs[0], -1, FROZEN_TIME);
+            flexTracker.setNumDroppedFlexibleConstraints(jobs[0], 3);
             assertEquals(2, trackedJobs.get(0).size());
             assertEquals(0, trackedJobs.get(1).size());
             assertEquals(0, trackedJobs.get(2).size());
@@ -650,14 +760,14 @@
             assertEquals(1, trackedJobs.get(3).size());
             assertEquals(0, trackedJobs.get(4).size());
 
-            flexTracker.resetJobNumDroppedConstraints(jobs[0], FROZEN_TIME);
+            flexTracker.calculateNumDroppedConstraints(jobs[0], FROZEN_TIME);
             assertEquals(1, trackedJobs.get(0).size());
             assertEquals(0, trackedJobs.get(1).size());
             assertEquals(0, trackedJobs.get(2).size());
             assertEquals(2, trackedJobs.get(3).size());
             assertEquals(0, trackedJobs.get(4).size());
 
-            flexTracker.adjustJobsRequiredConstraints(jobs[0], -2, FROZEN_TIME);
+            flexTracker.setNumDroppedFlexibleConstraints(jobs[0], 2);
             assertEquals(1, trackedJobs.get(0).size());
             assertEquals(1, trackedJobs.get(1).size());
             assertEquals(0, trackedJobs.get(2).size());
@@ -669,7 +779,7 @@
             JobSchedulerService.sElapsedRealtimeClock =
                     Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
 
-            flexTracker.resetJobNumDroppedConstraints(jobs[0], nowElapsed);
+            flexTracker.calculateNumDroppedConstraints(jobs[0], nowElapsed);
             assertEquals(1, trackedJobs.get(0).size());
             assertEquals(0, trackedJobs.get(1).size());
             assertEquals(1, trackedJobs.get(2).size());
@@ -779,9 +889,9 @@
         mFlexibilityController.setConstraintSatisfied(
                 SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS, false, FROZEN_TIME);
         // Require only a single constraint
-        jsAny.adjustNumRequiredFlexibleConstraints(-3);
-        jsCell.adjustNumRequiredFlexibleConstraints(-2);
-        jsWifi.adjustNumRequiredFlexibleConstraints(-2);
+        jsAny.setNumAppliedFlexibleConstraints(1);
+        jsCell.setNumAppliedFlexibleConstraints(1);
+        jsWifi.setNumAppliedFlexibleConstraints(1);
         synchronized (mFlexibilityController.mLock) {
             jsAny.setTransportAffinitiesSatisfied(false);
             jsCell.setTransportAffinitiesSatisfied(false);
@@ -1008,9 +1118,9 @@
     }
 
     @Test
-    public void testResetJobNumDroppedConstraints() {
+    public void testCalculateNumDroppedConstraints() {
         JobInfo.Builder jb = createJob(22);
-        JobStatus js = createJobStatus("testResetJobNumDroppedConstraints", jb);
+        JobStatus js = createJobStatus("testCalculateNumDroppedConstraints", jb);
         long nowElapsed = FROZEN_TIME;
 
         mFlexibilityController.mFlexibilityTracker.add(js);
@@ -1025,14 +1135,14 @@
                 Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
 
         mFlexibilityController.mFlexibilityTracker
-                .adjustJobsRequiredConstraints(js, -1, nowElapsed);
+                .setNumDroppedFlexibleConstraints(js, 1);
 
         assertEquals(2, js.getNumRequiredFlexibleConstraints());
         assertEquals(1, js.getNumDroppedFlexibleConstraints());
         assertEquals(1, mFlexibilityController
                 .mFlexibilityTracker.getJobsByNumRequiredConstraints(2).size());
 
-        mFlexibilityController.mFlexibilityTracker.resetJobNumDroppedConstraints(js, nowElapsed);
+        mFlexibilityController.mFlexibilityTracker.calculateNumDroppedConstraints(js, nowElapsed);
 
         assertEquals(2, js.getNumRequiredFlexibleConstraints());
         assertEquals(1, js.getNumDroppedFlexibleConstraints());
@@ -1043,7 +1153,7 @@
         JobSchedulerService.sElapsedRealtimeClock =
                 Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
 
-        mFlexibilityController.mFlexibilityTracker.resetJobNumDroppedConstraints(js, nowElapsed);
+        mFlexibilityController.mFlexibilityTracker.calculateNumDroppedConstraints(js, nowElapsed);
 
         assertEquals(3, js.getNumRequiredFlexibleConstraints());
         assertEquals(0, js.getNumDroppedFlexibleConstraints());
@@ -1054,7 +1164,7 @@
         JobSchedulerService.sElapsedRealtimeClock =
                 Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
 
-        mFlexibilityController.mFlexibilityTracker.resetJobNumDroppedConstraints(js, nowElapsed);
+        mFlexibilityController.mFlexibilityTracker.calculateNumDroppedConstraints(js, nowElapsed);
 
         assertEquals(0, js.getNumRequiredFlexibleConstraints());
         assertEquals(3, js.getNumDroppedFlexibleConstraints());
@@ -1063,7 +1173,7 @@
         JobSchedulerService.sElapsedRealtimeClock =
                 Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
 
-        mFlexibilityController.mFlexibilityTracker.resetJobNumDroppedConstraints(js, nowElapsed);
+        mFlexibilityController.mFlexibilityTracker.calculateNumDroppedConstraints(js, nowElapsed);
 
         assertEquals(1, js.getNumRequiredFlexibleConstraints());
         assertEquals(2, js.getNumDroppedFlexibleConstraints());
@@ -1139,20 +1249,28 @@
     }
 
     @Test
-    public void testDeviceDisabledFlexibility_Auto() {
-        when(mPackageManager.hasSystemFeature(
-                PackageManager.FEATURE_AUTOMOTIVE)).thenReturn(true);
+    public void testUnsupportedDevice_Auto() {
+        runTestUnsupportedDevice(PackageManager.FEATURE_AUTOMOTIVE);
+    }
+
+    @Test
+    public void testUnsupportedDevice_Embedded() {
+        runTestUnsupportedDevice(PackageManager.FEATURE_EMBEDDED);
+    }
+
+    private void runTestUnsupportedDevice(String feature) {
+        when(mPackageManager.hasSystemFeature(feature)).thenReturn(true);
         mFlexibilityController =
                 new FlexibilityController(mJobSchedulerService, mPrefetchController);
-        assertFalse(mFlexibilityController.mFlexibilityEnabled);
+        assertFalse(mFlexibilityController.isEnabled());
 
-        JobStatus js = createJobStatus("testIsAuto", createJob(0));
+        JobStatus js = createJobStatus("testUnsupportedDevice", createJob(0));
 
         mFlexibilityController.maybeStartTrackingJobLocked(js, null);
         assertTrue(js.isConstraintSatisfied(CONSTRAINT_FLEXIBLE));
 
-        setDeviceConfigBoolean(KEY_FLEXIBILITY_ENABLED, true);
-        assertFalse(mFlexibilityController.mFlexibilityEnabled);
+        setDeviceConfigInt(KEY_APPLIED_CONSTRAINTS, FLEXIBLE_CONSTRAINTS);
+        assertFalse(mFlexibilityController.isEnabled());
 
         ArrayList<ArraySet<JobStatus>> jobs =
                 mFlexibilityController.mFlexibilityTracker.getArrayList();
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
index 8397b877..293391f 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
@@ -232,6 +232,19 @@
     }
 
     @Test
+    public void testFlexibleConstraintCounts() {
+        JobStatus js = createJobStatus(new JobInfo.Builder(101, new ComponentName("foo", "bar"))
+                .setUserInitiated(false)
+                .build());
+
+        js.setNumAppliedFlexibleConstraints(3);
+        js.setNumDroppedFlexibleConstraints(2);
+        assertEquals(3, js.getNumAppliedFlexibleConstraints());
+        assertEquals(2, js.getNumDroppedFlexibleConstraints());
+        assertEquals(1, js.getNumRequiredFlexibleConstraints());
+    }
+
+    @Test
     public void testIsUserVisibleJob() {
         JobInfo jobInfo = new JobInfo.Builder(101, new ComponentName("foo", "bar"))
                 .setUserInitiated(false)
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
index a250ac7..0702764 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
@@ -368,10 +368,15 @@
         }
     }
 
+    private JobInfo.Builder createJobInfoBuilder(int jobId) {
+        return new JobInfo.Builder(jobId, new ComponentName(mContext, "TestQuotaJobService"));
+    }
+
     private JobStatus createJobStatus(String testTag, int jobId) {
-        JobInfo jobInfo = new JobInfo.Builder(jobId,
-                new ComponentName(mContext, "TestQuotaJobService"))
-                .build();
+        return createJobStatus(testTag, createJobInfoBuilder(jobId).build());
+    }
+
+    private JobStatus createJobStatus(String testTag, JobInfo jobInfo) {
         return createJobStatus(testTag, SOURCE_PACKAGE, CALLING_UID, jobInfo);
     }
 
@@ -1333,39 +1338,70 @@
         mQuotaController.saveTimingSession(0, SOURCE_PACKAGE,
                 createTimingSession(sElapsedRealtimeClock.millis() - (6 * MINUTE_IN_MILLIS),
                         3 * MINUTE_IN_MILLIS, 5), false);
+        final long timeUntilQuotaConsumedMs = 7 * MINUTE_IN_MILLIS;
         JobStatus job = createJobStatus("testGetMaxJobExecutionTimeLocked", 0);
+        //noinspection deprecation
+        JobStatus jobDefIWF = createJobStatus("testGetMaxJobExecutionTimeLocked",
+                createJobInfoBuilder(1)
+                        .setImportantWhileForeground(true)
+                        .setPriority(JobInfo.PRIORITY_DEFAULT)
+                        .build());
+        JobStatus jobHigh = createJobStatus("testGetMaxJobExecutionTimeLocked",
+                createJobInfoBuilder(2).setPriority(JobInfo.PRIORITY_HIGH).build());
         setStandbyBucket(RARE_INDEX, job);
+        setStandbyBucket(RARE_INDEX, jobDefIWF);
+        setStandbyBucket(RARE_INDEX, jobHigh);
 
         setCharging();
         synchronized (mQuotaController.mLock) {
             assertEquals(JobSchedulerService.Constants.DEFAULT_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                     mQuotaController.getMaxJobExecutionTimeMsLocked((job)));
+            assertEquals(JobSchedulerService.Constants.DEFAULT_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                    mQuotaController.getMaxJobExecutionTimeMsLocked((jobDefIWF)));
+            assertEquals(JobSchedulerService.Constants.DEFAULT_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                    mQuotaController.getMaxJobExecutionTimeMsLocked((jobHigh)));
         }
 
         setDischarging();
         setProcessState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
         synchronized (mQuotaController.mLock) {
-            assertEquals(JobSchedulerService.Constants.DEFAULT_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+            assertEquals(timeUntilQuotaConsumedMs,
                     mQuotaController.getMaxJobExecutionTimeMsLocked((job)));
+            assertEquals(JobSchedulerService.Constants.DEFAULT_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                    mQuotaController.getMaxJobExecutionTimeMsLocked((jobDefIWF)));
+            assertEquals(JobSchedulerService.Constants.DEFAULT_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                    mQuotaController.getMaxJobExecutionTimeMsLocked((jobHigh)));
         }
 
         // Top-started job
         setProcessState(ActivityManager.PROCESS_STATE_TOP);
         synchronized (mQuotaController.mLock) {
-            mQuotaController.maybeStartTrackingJobLocked(job, null);
+            trackJobs(job, jobDefIWF, jobHigh);
             mQuotaController.prepareForExecutionLocked(job);
+            mQuotaController.prepareForExecutionLocked(jobDefIWF);
+            mQuotaController.prepareForExecutionLocked(jobHigh);
         }
         setProcessState(ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
         synchronized (mQuotaController.mLock) {
-            assertEquals(JobSchedulerService.Constants.DEFAULT_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+            assertEquals(timeUntilQuotaConsumedMs,
                     mQuotaController.getMaxJobExecutionTimeMsLocked((job)));
+            assertEquals(JobSchedulerService.Constants.DEFAULT_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                    mQuotaController.getMaxJobExecutionTimeMsLocked((jobDefIWF)));
+            assertEquals(JobSchedulerService.Constants.DEFAULT_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                    mQuotaController.getMaxJobExecutionTimeMsLocked((jobHigh)));
             mQuotaController.maybeStopTrackingJobLocked(job, null);
+            mQuotaController.maybeStopTrackingJobLocked(jobDefIWF, null);
+            mQuotaController.maybeStopTrackingJobLocked(jobHigh, null);
         }
 
         setProcessState(ActivityManager.PROCESS_STATE_RECEIVER);
         synchronized (mQuotaController.mLock) {
-            assertEquals(7 * MINUTE_IN_MILLIS,
+            assertEquals(timeUntilQuotaConsumedMs,
                     mQuotaController.getMaxJobExecutionTimeMsLocked(job));
+            assertEquals(timeUntilQuotaConsumedMs,
+                    mQuotaController.getMaxJobExecutionTimeMsLocked(jobDefIWF));
+            assertEquals(timeUntilQuotaConsumedMs,
+                    mQuotaController.getMaxJobExecutionTimeMsLocked(jobHigh));
         }
     }
 
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java
index de8b308..c2b52b4 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java
@@ -45,14 +45,15 @@
 import android.os.RemoteException;
 import android.os.ServiceSpecificException;
 import android.platform.test.annotations.Presubmit;
+import android.util.ArraySet;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.internal.pm.parsing.pkg.AndroidPackageLegacyUtils;
+import com.android.internal.pm.pkg.parsing.ParsingPackageUtils;
 import com.android.server.pm.parsing.PackageParser2;
-import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
 import com.android.server.pm.pkg.AndroidPackage;
-import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -67,6 +68,7 @@
 import java.io.OutputStream;
 import java.util.List;
 import java.util.Objects;
+import java.util.Set;
 
 @SmallTest
 @Presubmit
@@ -106,6 +108,18 @@
             public boolean hasFeature(String feature) {
                 return true;
             }
+
+            @androidx.annotation.NonNull
+            @Override
+            public Set<String> getHiddenApiWhitelistedApps() {
+                return new ArraySet<>();
+            }
+
+            @androidx.annotation.NonNull
+            @Override
+            public Set<String> getInstallConstraintsAllowlist() {
+                return new ArraySet<>();
+            }
         });
 
         mMockSystem.system().stageNominalSystemState();
@@ -385,7 +399,7 @@
                 findFactory(results, "test.apex.rebootless").apexInfo);
         assertThat(factoryPkg.getBaseApkPath()).isEqualTo(activeApexInfo.modulePath);
         assertThat(factoryPkg.getLongVersionCode()).isEqualTo(1);
-        assertThat(AndroidPackageUtils.isSystem(factoryPkg)).isTrue();
+        assertThat(AndroidPackageLegacyUtils.isSystem(factoryPkg)).isTrue();
     }
 
     @Test
@@ -416,7 +430,7 @@
                 findFactory(results, "test.apex.rebootless").apexInfo);
         assertThat(factoryPkg.getBaseApkPath()).isEqualTo(factoryApexInfo.modulePath);
         assertThat(factoryPkg.getLongVersionCode()).isEqualTo(1);
-        assertThat(AndroidPackageUtils.isSystem(factoryPkg)).isTrue();
+        assertThat(AndroidPackageLegacyUtils.isSystem(factoryPkg)).isTrue();
     }
 
     @Test
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/DistractingPackageHelperTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/DistractingPackageHelperTest.kt
index cf81f0a..e131a98 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/DistractingPackageHelperTest.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/DistractingPackageHelperTest.kt
@@ -16,12 +16,14 @@
 
 package com.android.server.pm
 
+import android.app.AppOpsManager
 import android.content.Intent
 import android.content.pm.PackageManager
 import android.os.Binder
 import com.android.server.testutils.any
 import com.android.server.testutils.eq
 import com.android.server.testutils.nullable
+import com.android.server.testutils.whenever
 import com.google.common.truth.Truth.assertThat
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -31,6 +33,7 @@
 import org.mockito.Mockito.never
 import org.mockito.Mockito.verify
 
+
 @RunWith(JUnit4::class)
 class DistractingPackageHelperTest : PackageHelperTestBase() {
 
@@ -40,6 +43,9 @@
         super.setup()
         distractingPackageHelper = DistractingPackageHelper(
                 pms, broadcastHelper, suspendPackageHelper)
+        whenever(rule.mocks().appOpsManager.checkOpNoThrow(
+                eq(AppOpsManager.OP_SYSTEM_EXEMPT_FROM_SUSPENSION), any(), any()))
+                .thenReturn(AppOpsManager.MODE_DEFAULT)
     }
 
     @Test
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
index 46806f3..7b29e2a 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
@@ -15,6 +15,7 @@
  */
 package com.android.server.pm
 
+import android.app.AppOpsManager
 import android.app.PropertyInvalidatedCache
 import android.content.Context
 import android.content.Intent
@@ -55,8 +56,10 @@
 import com.android.dx.mockito.inline.extended.StaticMockitoSession
 import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder
 import com.android.internal.R
+import com.android.internal.pm.parsing.pkg.PackageImpl
 import com.android.internal.pm.parsing.pkg.ParsedPackage
 import com.android.internal.pm.pkg.parsing.ParsingPackage
+import com.android.internal.pm.pkg.parsing.ParsingPackageUtils
 import com.android.server.LocalManagerRegistry
 import com.android.server.LocalServices
 import com.android.server.LockGuard
@@ -67,10 +70,8 @@
 import com.android.server.pm.dex.DexManager
 import com.android.server.pm.dex.DynamicCodeLogger
 import com.android.server.pm.parsing.PackageParser2
-import com.android.server.pm.parsing.pkg.PackageImpl
 import com.android.server.pm.permission.PermissionManagerServiceInternal
 import com.android.server.pm.pkg.AndroidPackage
-import com.android.server.pm.pkg.parsing.ParsingPackageUtils
 import com.android.server.pm.resolution.ComponentResolver
 import com.android.server.pm.snapshot.PackageDataSnapshot
 import com.android.server.pm.verify.domain.DomainVerificationManagerInternal
@@ -80,14 +81,6 @@
 import com.android.server.testutils.nullable
 import com.android.server.testutils.whenever
 import com.android.server.utils.WatchedArrayMap
-import libcore.util.HexEncoding
-import org.junit.Assert
-import org.junit.rules.TestRule
-import org.junit.runner.Description
-import org.junit.runners.model.Statement
-import org.mockito.AdditionalMatchers.or
-import org.mockito.Mockito
-import org.mockito.quality.Strictness
 import java.io.File
 import java.io.IOException
 import java.nio.file.Files
@@ -96,6 +89,14 @@
 import java.util.Arrays
 import java.util.Random
 import java.util.concurrent.FutureTask
+import libcore.util.HexEncoding
+import org.junit.Assert
+import org.junit.rules.TestRule
+import org.junit.runner.Description
+import org.junit.runners.model.Statement
+import org.mockito.AdditionalMatchers.or
+import org.mockito.Mockito
+import org.mockito.quality.Strictness
 
 /**
  * A utility for mocking behavior of the system and dependencies when testing PackageManagerService
@@ -151,7 +152,7 @@
                 .mockStatic(EventLog::class.java)
                 .mockStatic(LocalServices::class.java)
                 .mockStatic(LocalManagerRegistry::class.java)
-                .mockStatic(DeviceConfig::class.java)
+                .mockStatic(DeviceConfig::class.java, Mockito.CALLS_REAL_METHODS)
                 .mockStatic(HexEncoding::class.java)
                 .apply(withSession)
         session = apply.startMocking()
@@ -192,6 +193,7 @@
         val userManagerService: UserManagerService = mock()
         val componentResolver: ComponentResolver = mock()
         val permissionManagerInternal: PermissionManagerServiceInternal = mock()
+        val appOpsManager: AppOpsManager = mock()
         val incrementalManager: IncrementalManager = mock()
         val platformCompat: PlatformCompat = mock()
         val settings: Settings = mock()
@@ -304,6 +306,7 @@
         whenever(mocks.injector.defaultAppProvider) { mocks.defaultAppProvider }
         whenever(mocks.injector.backgroundHandler) { mocks.backgroundHandler }
         whenever(mocks.injector.updateOwnershipHelper) { mocks.updateOwnershipHelper }
+        whenever(mocks.injector.getSystemService(AppOpsManager::class.java)) { mocks.appOpsManager }
         wheneverStatic { SystemConfig.getInstance() }.thenReturn(mocks.systemConfig)
         whenever(mocks.systemConfig.availableFeatures).thenReturn(DEFAULT_AVAILABLE_FEATURES_MAP)
         whenever(mocks.systemConfig.sharedLibraries).thenReturn(DEFAULT_SHARED_LIBRARIES_LIST)
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java
index 2332988..e5ecdc4 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java
@@ -62,6 +62,7 @@
 import android.os.UserHandle;
 import android.platform.test.annotations.Presubmit;
 import android.text.TextUtils;
+import android.util.SparseArray;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
@@ -174,6 +175,7 @@
         mUserState = new PackageUserStateImpl().setInstalled(true);
         mPackageSetting.setUserState(mUserId, mUserState);
         when(mPackageState.getUserStateOrDefault(eq(mUserId))).thenReturn(mUserState);
+        when(mPackageState.getUserStates()).thenReturn(new SparseArray<>());
 
         when(mContext.getSystemService(LauncherApps.class)).thenReturn(mLauncherApps);
         when(mContext.getSystemService(AppOpsManager.class)).thenReturn(
@@ -343,7 +345,7 @@
 
     @Test
     public void archiveApp_appOptedOutOfArchiving() {
-        when(mAppOpsManager.checkOp(
+        when(mAppOpsManager.checkOpNoThrow(
                 eq(AppOpsManager.OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED),
                 anyInt(), eq(PACKAGE))).thenReturn(MODE_IGNORED);
 
@@ -430,7 +432,7 @@
     @Test
     public void isAppArchivable_appOptedOutOfArchiving()
             throws PackageManager.NameNotFoundException {
-        when(mAppOpsManager.checkOp(
+        when(mAppOpsManager.checkOpNoThrow(
                 eq(AppOpsManager.OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED),
                 anyInt(), eq(PACKAGE))).thenReturn(MODE_IGNORED);
 
@@ -551,22 +553,12 @@
         when(mComputer.getPackageStateFiltered(eq(PACKAGE), anyInt(), anyInt())).thenReturn(
                 null);
 
-        Exception e = assertThrows(
-                ParcelableException.class,
-                () -> mArchiveManager.getArchivedAppIcon(PACKAGE, UserHandle.CURRENT));
-        assertThat(e.getCause()).isInstanceOf(PackageManager.NameNotFoundException.class);
-        assertThat(e.getCause()).hasMessageThat().isEqualTo(
-                String.format("Package %s not found.", PACKAGE));
+        assertThat(mArchiveManager.getArchivedAppIcon(PACKAGE, UserHandle.CURRENT)).isNull();
     }
 
     @Test
     public void getArchivedAppIcon_notArchived() {
-        Exception e = assertThrows(
-                ParcelableException.class,
-                () -> mArchiveManager.getArchivedAppIcon(PACKAGE, UserHandle.CURRENT));
-        assertThat(e.getCause()).isInstanceOf(PackageManager.NameNotFoundException.class);
-        assertThat(e.getCause()).hasMessageThat().isEqualTo(
-                String.format("Package %s is not currently archived.", PACKAGE));
+        assertThat(mArchiveManager.getArchivedAppIcon(PACKAGE, UserHandle.CURRENT)).isNull();
     }
 
     @Test
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageHelperTestBase.kt b/services/tests/mockingservicestests/src/com/android/server/pm/PackageHelperTestBase.kt
index a6ba5d4..7b80aea 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageHelperTestBase.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageHelperTestBase.kt
@@ -36,6 +36,7 @@
 open class PackageHelperTestBase {
 
     companion object {
+        const val PLATFORM_PACKAGE_NAME = "android"
         const val TEST_PACKAGE_1 = "com.android.test.package1"
         const val TEST_PACKAGE_2 = "com.android.test.package2"
         const val DEVICE_OWNER_PACKAGE = "com.android.test.owner"
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt
index e685c3f..944b1aa 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt
@@ -21,17 +21,17 @@
 import android.content.pm.SharedLibraryInfo
 import android.content.pm.VersionedPackage
 import android.os.Build
-import android.os.storage.StorageManager
 import android.os.UserHandle
+import android.os.storage.StorageManager
 import android.util.ArrayMap
 import android.util.PackageUtils
+import com.android.internal.pm.parsing.pkg.PackageImpl
 import com.android.internal.pm.parsing.pkg.ParsedPackage
 import com.android.server.SystemConfig.SharedLibraryEntry
 import com.android.server.compat.PlatformCompat
 import com.android.server.extendedtestutils.wheneverStatic
 import com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME
 import com.android.server.pm.pkg.AndroidPackage
-import com.android.server.pm.parsing.pkg.PackageImpl
 import com.android.server.testutils.any
 import com.android.server.testutils.eq
 import com.android.server.testutils.mock
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt
index 7b381ce..ae53e70 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt
@@ -16,12 +16,14 @@
 
 package com.android.server.pm
 
+import android.app.AppOpsManager
 import android.content.Intent
 import android.content.pm.SuspendDialogInfo
 import android.os.Binder
 import android.os.PersistableBundle
 import com.android.server.testutils.any
 import com.android.server.testutils.eq
+import com.android.server.testutils.whenever
 import com.google.common.truth.Truth.assertThat
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -32,6 +34,12 @@
 
 @RunWith(JUnit4::class)
 class SuspendPackageHelperTest : PackageHelperTestBase() {
+    override fun setup() {
+        super.setup()
+        whenever(rule.mocks().appOpsManager.checkOpNoThrow(
+                eq(AppOpsManager.OP_SYSTEM_EXEMPT_FROM_SUSPENSION), any(), any()))
+                .thenReturn(AppOpsManager.MODE_DEFAULT)
+    }
 
     @Test
     fun setPackagesSuspended() {
@@ -275,6 +283,72 @@
     }
 
     @Test
+    fun getSuspendingPackagePrecedence() {
+        val launcherExtras = PersistableBundle()
+        launcherExtras.putString(TEST_PACKAGE_2, TEST_PACKAGE_2)
+        val targetPackages = arrayOf(TEST_PACKAGE_2)
+        // Suspend.
+        var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
+                targetPackages, true /* suspended */, null /* appExtras */, launcherExtras,
+                null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid,
+                false /* quarantined */)
+        assertThat(failedNames).isEmpty()
+        testHandler.flush()
+
+        assertThat(suspendPackageHelper.getSuspendingPackage(pms.snapshotComputer(),
+                TEST_PACKAGE_2, TEST_USER_ID, deviceOwnerUid)).isEqualTo(DEVICE_OWNER_PACKAGE)
+
+        // Suspend by system.
+        failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
+                targetPackages, true /* suspended */, null /* appExtras */, launcherExtras,
+                null /* dialogInfo */, PLATFORM_PACKAGE_NAME, TEST_USER_ID, deviceOwnerUid,
+                false /* quarantined */)
+        assertThat(failedNames).isEmpty()
+        testHandler.flush()
+
+        assertThat(suspendPackageHelper.getSuspendingPackage(pms.snapshotComputer(),
+                TEST_PACKAGE_2, TEST_USER_ID, deviceOwnerUid)).isEqualTo(PLATFORM_PACKAGE_NAME)
+
+        // QAS by package1.
+        failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
+                targetPackages, true /* suspended */, null /* appExtras */, launcherExtras,
+                null /* dialogInfo */, TEST_PACKAGE_1, TEST_USER_ID, deviceOwnerUid,
+                true /* quarantined */)
+        assertThat(failedNames).isEmpty()
+        testHandler.flush()
+
+        assertThat(suspendPackageHelper.getSuspendingPackage(pms.snapshotComputer(),
+                TEST_PACKAGE_2, TEST_USER_ID, deviceOwnerUid)).isEqualTo(TEST_PACKAGE_1)
+
+        // Un-QAS by package1.
+        suspendPackageHelper.removeSuspensionsBySuspendingPackage(pms.snapshotComputer(),
+                targetPackages, { suspendingPackage -> suspendingPackage == TEST_PACKAGE_1 },
+                TEST_USER_ID)
+        testHandler.flush()
+
+        assertThat(suspendPackageHelper.getSuspendingPackage(pms.snapshotComputer(),
+                TEST_PACKAGE_2, TEST_USER_ID, deviceOwnerUid)).isEqualTo(PLATFORM_PACKAGE_NAME)
+
+        // Un-suspend by system.
+        suspendPackageHelper.removeSuspensionsBySuspendingPackage(pms.snapshotComputer(),
+                targetPackages, { suspendingPackage -> suspendingPackage == PLATFORM_PACKAGE_NAME },
+                TEST_USER_ID)
+        testHandler.flush()
+
+        assertThat(suspendPackageHelper.getSuspendingPackage(pms.snapshotComputer(),
+                TEST_PACKAGE_2, TEST_USER_ID, deviceOwnerUid)).isEqualTo(DEVICE_OWNER_PACKAGE)
+
+        // Unsuspend.
+        suspendPackageHelper.removeSuspensionsBySuspendingPackage(pms.snapshotComputer(),
+                targetPackages, { suspendingPackage -> suspendingPackage == DEVICE_OWNER_PACKAGE },
+                TEST_USER_ID)
+        testHandler.flush()
+
+        assertThat(suspendPackageHelper.getSuspendingPackage(pms.snapshotComputer(),
+                TEST_PACKAGE_2, TEST_USER_ID, deviceOwnerUid)).isNull()
+    }
+
+    @Test
     fun getSuspendedDialogInfo() {
         val dialogInfo = SuspendDialogInfo.Builder()
             .setTitle(TEST_PACKAGE_1).build()
diff --git a/services/tests/powerstatstests/Android.bp b/services/tests/powerstatstests/Android.bp
index f02e5a5..05e0e8f 100644
--- a/services/tests/powerstatstests/Android.bp
+++ b/services/tests/powerstatstests/Android.bp
@@ -3,6 +3,20 @@
     default_applicable_licenses: ["frameworks_base_license"],
 }
 
+filegroup {
+    name: "power_stats_ravenwood_tests",
+    srcs: [
+        "src/com/android/server/power/stats/AggregatedPowerStatsProcessorTest.java",
+        "src/com/android/server/power/stats/AggregatedPowerStatsTest.java",
+        "src/com/android/server/power/stats/MultiStateStatsTest.java",
+        "src/com/android/server/power/stats/PowerStatsAggregatorTest.java",
+        "src/com/android/server/power/stats/PowerStatsCollectorTest.java",
+        "src/com/android/server/power/stats/PowerStatsSchedulerTest.java",
+        "src/com/android/server/power/stats/PowerStatsStoreTest.java",
+        "src/com/android/server/power/stats/PowerStatsUidResolverTest.java",
+    ],
+}
+
 android_test {
     name: "PowerStatsTests",
 
@@ -12,7 +26,7 @@
     ],
 
     exclude_srcs: [
-        "src/com/android/server/power/stats/PowerStatsStoreTest.java",
+        ":power_stats_ravenwood_tests",
     ],
 
     static_libs: [
@@ -62,13 +76,14 @@
     static_libs: [
         "services.core",
         "modules-utils-binary-xml",
-
         "androidx.annotation_annotation",
         "androidx.test.rules",
+        "truth",
+        "mockito_ravenwood",
     ],
     srcs: [
-        "src/com/android/server/power/stats/PowerStatsStoreTest.java",
+        ":power_stats_ravenwood_tests",
+        "src/com/android/server/power/stats/MockClock.java",
     ],
-    sdk_version: "test_current",
     auto_gen_config: true,
 }
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/AggregatePowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/AggregatedPowerStatsProcessorTest.java
similarity index 98%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/AggregatePowerStatsProcessorTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/AggregatedPowerStatsProcessorTest.java
index 48e2dd7..af83be0 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/AggregatePowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/AggregatedPowerStatsProcessorTest.java
@@ -26,8 +26,6 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.internal.os.MultiStateStats;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -37,7 +35,7 @@
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
-public class AggregatePowerStatsProcessorTest {
+public class AggregatedPowerStatsProcessorTest {
 
     @Test
     public void createPowerEstimationPlan_allDeviceStatesPresentInUidStates() {
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsHistoryIteratorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsHistoryIteratorTest.java
index abb3be7..bf5bf36 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsHistoryIteratorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsHistoryIteratorTest.java
@@ -26,6 +26,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.os.BatteryStatsHistoryIterator;
+import com.android.internal.os.MonotonicClock;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -76,7 +77,8 @@
     public void unconstrainedIteration() {
         prepareHistory();
 
-        final BatteryStatsHistoryIterator iterator = mBatteryStats.iterateBatteryStatsHistory(0, 0);
+        final BatteryStatsHistoryIterator iterator =
+                mBatteryStats.iterateBatteryStatsHistory(0, MonotonicClock.UNDEFINED);
 
         BatteryStats.HistoryItem item;
 
@@ -114,9 +116,10 @@
         prepareHistory();
 
         // Initial time is 1000_000
-        assertIncludedEvents(mBatteryStats.iterateBatteryStatsHistory(0, 0),
+        assertIncludedEvents(mBatteryStats.iterateBatteryStatsHistory(0, MonotonicClock.UNDEFINED),
                 1000_000L, 1000_000L, 2000_000L, 3000_000L, 3001_000L);
-        assertIncludedEvents(mBatteryStats.iterateBatteryStatsHistory(2000_000, 0),
+        assertIncludedEvents(
+                mBatteryStats.iterateBatteryStatsHistory(2000_000, MonotonicClock.UNDEFINED),
                 2000_000L, 3000_000L, 3001_000L);
         assertIncludedEvents(mBatteryStats.iterateBatteryStatsHistory(0, 3000_000L),
                 1000_000L, 1000_000L, 2000_000L);
@@ -177,7 +180,8 @@
                     mMockClock.realtime, mMockClock.uptime);
         }
 
-        final BatteryStatsHistoryIterator iterator = mBatteryStats.iterateBatteryStatsHistory(0, 0);
+        final BatteryStatsHistoryIterator iterator =
+                mBatteryStats.iterateBatteryStatsHistory(0, MonotonicClock.UNDEFINED);
 
         BatteryStats.HistoryItem item;
         assertThat(item = iterator.next()).isNotNull();
@@ -244,7 +248,8 @@
 
         mExternalStatsSync.updateCpuStats(300, 7_100_000, 4_100_000);
 
-        final BatteryStatsHistoryIterator iterator = mBatteryStats.iterateBatteryStatsHistory(0, 0);
+        final BatteryStatsHistoryIterator iterator =
+                mBatteryStats.iterateBatteryStatsHistory(0, MonotonicClock.UNDEFINED);
 
         BatteryStats.HistoryItem item;
         assertThat(item = iterator.next()).isNotNull();
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java
index 1dd499c..bb70080 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java
@@ -277,7 +277,7 @@
         mReadFiles.clear();
 
         // Prepare history for iteration
-        mHistory.iterate(0, 0);
+        mHistory.iterate(0, MonotonicClock.UNDEFINED);
 
         Parcel parcel = mHistory.getNextParcel(0, Long.MAX_VALUE);
         assertThat(parcel).isNotNull();
@@ -399,7 +399,7 @@
 
         mHistory.recordPowerStats(200, 200, powerStats);
 
-        BatteryStatsHistoryIterator iterator = mHistory.iterate(0, 0);
+        BatteryStatsHistoryIterator iterator = mHistory.iterate(0, MonotonicClock.UNDEFINED);
         BatteryStats.HistoryItem item;
         assertThat(item = iterator.next()).isNotNull(); // First item contains current time only
 
@@ -429,7 +429,7 @@
         mHistory.recordNrStateChangeEvent(500, 500,
                 NetworkRegistrationInfo.NR_STATE_NONE);
 
-        BatteryStatsHistoryIterator iterator = mHistory.iterate(0, 0);
+        BatteryStatsHistoryIterator iterator = mHistory.iterate(0, MonotonicClock.UNDEFINED);
         BatteryStats.HistoryItem item = new BatteryStats.HistoryItem();
         assertThat(item = iterator.next()).isNotNull(); // First item contains current time only
 
@@ -470,7 +470,7 @@
         mHistory.recordNrStateChangeEvent(500, 500,
                 NetworkRegistrationInfo.NR_STATE_NONE);
 
-        BatteryStatsHistoryIterator iterator = mHistory.iterate(0, 0);
+        BatteryStatsHistoryIterator iterator = mHistory.iterate(0, MonotonicClock.UNDEFINED);
         BatteryStats.HistoryItem item = new BatteryStats.HistoryItem();
         assertThat(item = iterator.next()).isNotNull(); // First item contains current time only
 
@@ -552,7 +552,8 @@
         int wakelockTagsUnpooled = 0;
         int wakeReasonTagsPooled = 0;
         int wakeReasonTagsUnpooled = 0;
-        for (BatteryStatsHistoryIterator iterator = mHistory.iterate(0, 0); iterator.hasNext(); ) {
+        for (BatteryStatsHistoryIterator iterator =
+                mHistory.iterate(0, MonotonicClock.UNDEFINED); iterator.hasNext(); ) {
             HistoryItem item = iterator.next();
             if (item.cmd != HistoryItem.CMD_UPDATE) {
                 continue;
@@ -608,7 +609,7 @@
                 UserHandle.getUid(777, Process.LAST_ISOLATED_UID),
                 BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE);
 
-        BatteryStatsHistoryIterator iterator = mHistory.iterate(0, 0);
+        BatteryStatsHistoryIterator iterator = mHistory.iterate(0, MonotonicClock.UNDEFINED);
         BatteryStats.HistoryItem item;
         assertThat(item = iterator.next()).isNotNull(); // First item contains current time only
 
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsNoteTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsNoteTest.java
index 24c67f8..eea2875 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsNoteTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsNoteTest.java
@@ -58,6 +58,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.os.BatteryStatsHistoryIterator;
+import com.android.internal.os.MonotonicClock;
 import com.android.internal.os.PowerProfile;
 import com.android.internal.power.EnergyConsumerStats;
 import com.android.server.power.stats.BatteryStatsImpl.DualTimer;
@@ -270,7 +271,8 @@
         clocks.realtime = clocks.uptime = 220;
         bi.noteLongPartialWakelockFinish(name, historyName, ISOLATED_UID);
 
-        final BatteryStatsHistoryIterator iterator =  bi.iterateBatteryStatsHistory(0, 0);
+        final BatteryStatsHistoryIterator iterator =
+                bi.iterateBatteryStatsHistory(0, MonotonicClock.UNDEFINED);
 
         BatteryStats.HistoryItem item;
 
@@ -327,7 +329,8 @@
         clocks.realtime = clocks.uptime = 220;
         bi.noteLongPartialWakelockFinish(name, historyName, ISOLATED_UID);
 
-        final BatteryStatsHistoryIterator iterator = bi.iterateBatteryStatsHistory(0, 0);
+        final BatteryStatsHistoryIterator iterator =
+                bi.iterateBatteryStatsHistory(0, MonotonicClock.UNDEFINED);
 
         BatteryStats.HistoryItem item;
 
@@ -941,7 +944,8 @@
         clocks.realtime = clocks.uptime = 5000;
         bi.noteAlarmFinishLocked("foo", null, UID);
 
-        BatteryStatsHistoryIterator iterator = bi.iterateBatteryStatsHistory(0, 0);
+        BatteryStatsHistoryIterator iterator =
+                bi.iterateBatteryStatsHistory(0, MonotonicClock.UNDEFINED);
         HistoryItem item;
 
         assertThat(item = iterator.next()).isNotNull();
@@ -980,7 +984,8 @@
         clocks.realtime = clocks.uptime = 5000;
         bi.noteAlarmFinishLocked("foo", ws, UID);
 
-        BatteryStatsHistoryIterator iterator = bi.iterateBatteryStatsHistory(0, 0);
+        BatteryStatsHistoryIterator iterator =
+                bi.iterateBatteryStatsHistory(0, MonotonicClock.UNDEFINED);
         HistoryItem item;
 
         assertThat(item = iterator.next()).isNotNull();
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/CpuAggregatedPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/CpuAggregatedPowerStatsProcessorTest.java
index 8ca4ff6..993d834 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/CpuAggregatedPowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/CpuAggregatedPowerStatsProcessorTest.java
@@ -38,7 +38,6 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.internal.os.MultiStateStats;
 import com.android.internal.os.PowerProfile;
 import com.android.internal.os.PowerStats;
 
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/MultiStateStatsTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/MultiStateStatsTest.java
index eb03a6c..1b045c5 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/MultiStateStatsTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/MultiStateStatsTest.java
@@ -26,8 +26,6 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.internal.os.MultiStateStats;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -38,7 +36,6 @@
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class MultiStateStatsTest {
-
     public static final int DIMENSION_COUNT = 2;
 
     @Test
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsAggregatorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsAggregatorTest.java
index 6704987..22a7351 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsAggregatorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsAggregatorTest.java
@@ -24,7 +24,6 @@
 import android.os.BatteryConsumer;
 import android.os.BatteryStats;
 import android.os.PersistableBundle;
-import android.text.format.DateFormat;
 
 import androidx.annotation.NonNull;
 import androidx.test.filters.SmallTest;
@@ -39,7 +38,8 @@
 import org.junit.runner.RunWith;
 
 import java.text.ParseException;
-import java.util.Calendar;
+import java.text.SimpleDateFormat;
+import java.util.Date;
 import java.util.List;
 import java.util.TimeZone;
 
@@ -60,7 +60,7 @@
     public void setup() throws ParseException {
         mHistory = new BatteryStatsHistory(32, 1024,
                 mock(BatteryStatsHistory.HistoryStepDetailsCalculator.class), mClock,
-                mMonotonicClock);
+                mMonotonicClock, mock(BatteryStatsHistory.TraceDelegate.class));
 
         AggregatedPowerStatsConfig config = new AggregatedPowerStatsConfig();
         config.trackPowerComponent(TEST_POWER_COMPONENT)
@@ -120,7 +120,7 @@
         powerStats.uidStats.put(TEST_UID, new long[]{4444});
         mHistory.recordPowerStats(mClock.realtime, mClock.uptime, powerStats);
 
-        mAggregator.aggregatePowerStats(0, 0, stats -> {
+        mAggregator.aggregatePowerStats(0, MonotonicClock.UNDEFINED, stats -> {
             assertThat(mAggregatedStatsCount++).isEqualTo(0);
             assertThat(stats.getStartTime()).isEqualTo(START_TIME);
 
@@ -179,9 +179,9 @@
 
     @NonNull
     private static CharSequence formatDateTime(long timeInMillis) {
-        Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
-        cal.setTimeInMillis(timeInMillis);
-        return DateFormat.format("yyyy-MM-dd hh:mm:ss", cal);
+        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
+        format.getCalendar().setTimeZone(TimeZone.getTimeZone("GMT"));
+        return format.format(new Date(timeInMillis));
     }
 
     @Test
@@ -220,7 +220,7 @@
 
         mHistory.recordBatteryState(mClock.realtime, mClock.uptime, 50, /* plugged */ true);
 
-        mAggregator.aggregatePowerStats(0, 0, stats -> {
+        mAggregator.aggregatePowerStats(0, MonotonicClock.UNDEFINED, stats -> {
             long[] values = new long[1];
 
             PowerComponentAggregatedPowerStats powerComponentStats =
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsCollectorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsCollectorTest.java
index 330f698..17a7d3e 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsCollectorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsCollectorTest.java
@@ -22,6 +22,7 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.PersistableBundle;
+import android.platform.test.ravenwood.RavenwoodRule;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
@@ -29,12 +30,18 @@
 import com.android.internal.os.PowerStats;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class PowerStatsCollectorTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder()
+            .setProvideMainThread(true)
+            .build();
+
     private final MockClock mMockClock = new MockClock();
     private final HandlerThread mHandlerThread = new HandlerThread("test");
     private Handler mHandler;
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsSchedulerTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsSchedulerTest.java
index 7257a94..beec661 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsSchedulerTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsSchedulerTest.java
@@ -24,26 +24,26 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
 
-import android.content.Context;
 import android.os.ConditionVariable;
 import android.os.Handler;
 import android.os.HandlerThread;
+import android.platform.test.ravenwood.RavenwoodRule;
 
-import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.os.MonotonicClock;
-import com.android.internal.os.PowerProfile;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
 import java.time.Duration;
 import java.time.Instant;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.TimeZone;
 import java.util.concurrent.TimeUnit;
@@ -51,39 +51,46 @@
 
 @RunWith(AndroidJUnit4.class)
 public class PowerStatsSchedulerTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder()
+            .setProvideMainThread(true)
+            .build();
+
     private PowerStatsStore mPowerStatsStore;
     private Handler mHandler;
     private MockClock mClock = new MockClock();
     private MonotonicClock mMonotonicClock = new MonotonicClock(0, mClock);
-    private MockBatteryStatsImpl mBatteryStats;
     private PowerStatsScheduler mPowerStatsScheduler;
-    private PowerProfile mPowerProfile;
     private PowerStatsAggregator mPowerStatsAggregator;
     private AggregatedPowerStatsConfig mAggregatedPowerStatsConfig;
+    private List<Long> mScheduledAlarms = new ArrayList<>();
+    private boolean mPowerStatsCollectionOccurred;
+
+    private static final int START_REALTIME = 7654321;
 
     @Before
     @SuppressWarnings("GuardedBy")
-    public void setup() {
-        final Context context = InstrumentationRegistry.getContext();
-
+    public void setup() throws IOException {
         TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
 
         mClock.currentTime = Instant.parse("2023-01-02T03:04:05.00Z").toEpochMilli();
-        mClock.realtime = 7654321;
+        mClock.realtime = START_REALTIME;
 
         HandlerThread bgThread = new HandlerThread("bg thread");
         bgThread.start();
-        File systemDir = context.getCacheDir();
         mHandler = new Handler(bgThread.getLooper());
         mAggregatedPowerStatsConfig = new AggregatedPowerStatsConfig();
-        mPowerStatsStore = new PowerStatsStore(systemDir, mHandler, mAggregatedPowerStatsConfig);
-        mPowerProfile = mock(PowerProfile.class);
-        when(mPowerProfile.getAveragePower(PowerProfile.POWER_FLASHLIGHT)).thenReturn(1000000.0);
-        mBatteryStats = new MockBatteryStatsImpl(mClock).setPowerProfile(mPowerProfile);
+        mPowerStatsStore = new PowerStatsStore(
+                Files.createTempDirectory("PowerStatsSchedulerTest").toFile(),
+                mHandler, mAggregatedPowerStatsConfig);
         mPowerStatsAggregator = mock(PowerStatsAggregator.class);
-        mPowerStatsScheduler = new PowerStatsScheduler(context, mPowerStatsAggregator,
-                TimeUnit.MINUTES.toMillis(30), TimeUnit.HOURS.toMillis(1), mPowerStatsStore, mClock,
-                mMonotonicClock, mHandler, mBatteryStats);
+        mPowerStatsScheduler = new PowerStatsScheduler(
+                () -> mPowerStatsCollectionOccurred = true,
+                mPowerStatsAggregator, TimeUnit.MINUTES.toMillis(30), TimeUnit.HOURS.toMillis(1),
+                mPowerStatsStore,
+                ((triggerAtMillis, tag, onAlarmListener, handler) ->
+                        mScheduledAlarms.add(triggerAtMillis)),
+                mClock, mMonotonicClock, () -> 12345L, mHandler);
     }
 
     @Test
@@ -113,7 +120,7 @@
             long endTimeWallClock =
                     mClock.currentTime - (mMonotonicClock.monotonicTime() - endTime);
 
-            assertThat(startTime).isEqualTo(7654321 + 123);
+            assertThat(startTime).isEqualTo(START_REALTIME + 123);
             assertThat(endTime - startTime).isAtLeast(TimeUnit.MINUTES.toMillis(30));
             assertThat(Instant.ofEpochMilli(endTimeWallClock))
                     .isEqualTo(Instant.parse("2023-01-02T04:00:00Z"));
@@ -142,11 +149,15 @@
         }).when(mPowerStatsAggregator).aggregatePowerStats(anyLong(), anyLong(),
                 any(Consumer.class));
 
-        mPowerStatsScheduler.schedulePowerStatsAggregation();
+        mPowerStatsScheduler.start(/*enabled*/ true);
         ConditionVariable done = new ConditionVariable();
         mHandler.post(done::open);
         done.block();
 
+        assertThat(mPowerStatsCollectionOccurred).isTrue();
+        assertThat(mScheduledAlarms).containsExactly(
+                START_REALTIME + TimeUnit.MINUTES.toMillis(90) + TimeUnit.HOURS.toMillis(1));
+
         verify(mPowerStatsAggregator, times(2))
                 .aggregatePowerStats(anyLong(), anyLong(), any(Consumer.class));
 
@@ -155,7 +166,7 @@
         // Skip the first entry, which was placed in the store at the beginning of this test
         PowerStatsSpan.TimeFrame timeFrame1 = contents.get(1).getTimeFrames().get(0);
         PowerStatsSpan.TimeFrame timeFrame2 = contents.get(2).getTimeFrames().get(0);
-        assertThat(timeFrame1.startMonotonicTime).isEqualTo(7654321 + 123);
+        assertThat(timeFrame1.startMonotonicTime).isEqualTo(START_REALTIME + 123);
         assertThat(timeFrame2.startMonotonicTime)
                 .isEqualTo(timeFrame1.startMonotonicTime + timeFrame1.duration);
         assertThat(Instant.ofEpochMilli(timeFrame2.startTime))
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 2ece8c7..9b84190 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -79,6 +79,7 @@
         "coretests-aidl",
         "securebox",
         "flag-junit",
+        "ravenwood-junit",
     ],
 
     libs: [
@@ -140,6 +141,23 @@
     resource_zips: [":FrameworksServicesTests_apks_as_resources"],
 }
 
+android_ravenwood_test {
+    name: "FrameworksServicesTestsRavenwood",
+    libs: [
+        "android.test.mock",
+    ],
+    static_libs: [
+        "androidx.annotation_annotation",
+        "androidx.test.rules",
+        "mockito_ravenwood",
+        "services.core",
+    ],
+    srcs: [
+        "src/com/android/server/uri/**/*.java",
+    ],
+    auto_gen_config: true,
+}
+
 java_library {
     name: "servicestests-core-utils",
     srcs: [
diff --git a/services/tests/servicestests/res/xml/usertypes_test_profile.xml b/services/tests/servicestests/res/xml/usertypes_test_profile.xml
index e89199d..6537d47 100644
--- a/services/tests/servicestests/res/xml/usertypes_test_profile.xml
+++ b/services/tests/servicestests/res/xml/usertypes_test_profile.xml
@@ -40,11 +40,13 @@
             mediaSharedWithParent='true'
             credentialShareableWithParent='false'
             authAlwaysRequiredToDisableQuietMode='true'
+            allowStoppingUserWithDelayedLocking='true'
             showInSettings='23'
             hideInSettingsInQuietMode='true'
             inheritDevicePolicy='450'
             deleteAppWithParent='false'
             alwaysVisible='true'
+            crossProfileContentSharingStrategy='0'
         />
     </profile-type>
     <profile-type name='custom.test.1' max-allowed-per-parent='14' />
diff --git a/services/tests/servicestests/src/com/android/server/BootReceiverTest.java b/services/tests/servicestests/src/com/android/server/BootReceiverTest.java
new file mode 100644
index 0000000..523c5c0
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/BootReceiverTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.test.AndroidTestCase;
+
+import com.android.server.os.TombstoneProtos;
+import com.android.server.os.TombstoneProtos.Tombstone;
+
+public class BootReceiverTest extends AndroidTestCase {
+    private static final String TAG = "BootReceiverTest";
+
+    public void testRemoveMemoryFromTombstone() {
+        Tombstone tombstoneBase = Tombstone.newBuilder()
+                .setBuildFingerprint("build_fingerprint")
+                .setRevision("revision")
+                .setPid(123)
+                .setTid(23)
+                .setUid(34)
+                .setSelinuxLabel("selinux_label")
+                .addCommandLine("cmd1")
+                .addCommandLine("cmd2")
+                .addCommandLine("cmd3")
+                .setProcessUptime(300)
+                .setAbortMessage("abort")
+                .addCauses(TombstoneProtos.Cause.newBuilder()
+                        .setHumanReadable("cause1")
+                        .setMemoryError(TombstoneProtos.MemoryError.newBuilder()
+                                .setTool(TombstoneProtos.MemoryError.Tool.SCUDO)
+                                .setType(TombstoneProtos.MemoryError.Type.DOUBLE_FREE)))
+                .addLogBuffers(TombstoneProtos.LogBuffer.newBuilder().setName("name").addLogs(
+                        TombstoneProtos.LogMessage.newBuilder()
+                                .setTimestamp("123")
+                                .setMessage("message")))
+                .addOpenFds(TombstoneProtos.FD.newBuilder().setFd(1).setPath("path"))
+                .build();
+
+        Tombstone tombstoneWithoutMemory = tombstoneBase.toBuilder()
+                .putThreads(1, TombstoneProtos.Thread.newBuilder()
+                        .setId(1)
+                        .setName("thread1")
+                        .addRegisters(TombstoneProtos.Register.newBuilder().setName("r1").setU64(1))
+                        .addRegisters(TombstoneProtos.Register.newBuilder().setName("r2").setU64(2))
+                        .addBacktraceNote("backtracenote1")
+                        .addUnreadableElfFiles("files1")
+                        .setTaggedAddrCtrl(1)
+                        .setPacEnabledKeys(10)
+                        .build())
+                .build();
+
+        Tombstone tombstoneWithMemory = tombstoneBase.toBuilder()
+                .addMemoryMappings(TombstoneProtos.MemoryMapping.newBuilder()
+                        .setBeginAddress(1)
+                        .setEndAddress(100)
+                        .setOffset(10)
+                        .setRead(true)
+                        .setWrite(true)
+                        .setExecute(false)
+                        .setMappingName("mapping")
+                        .setBuildId("build")
+                        .setLoadBias(70))
+                .putThreads(1, TombstoneProtos.Thread.newBuilder()
+                        .setId(1)
+                        .setName("thread1")
+                        .addRegisters(TombstoneProtos.Register.newBuilder().setName("r1").setU64(1))
+                        .addRegisters(TombstoneProtos.Register.newBuilder().setName("r2").setU64(2))
+                        .addBacktraceNote("backtracenote1")
+                        .addUnreadableElfFiles("files1")
+                        .addMemoryDump(TombstoneProtos.MemoryDump.newBuilder()
+                                .setRegisterName("register1")
+                                .setMappingName("mapping")
+                                .setBeginAddress(10))
+                        .setTaggedAddrCtrl(1)
+                        .setPacEnabledKeys(10)
+                        .build())
+                .build();
+
+        assertThat(BootReceiver.removeMemoryFromTombstone(tombstoneWithMemory))
+                .isEqualTo(tombstoneWithoutMemory);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
index 9114027..71d64cf 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
@@ -532,12 +532,11 @@
 
     @Test
     @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE)
-    public void testTwoFingerTripleTap_StateIsIdle_shouldInActivated() {
+    public void testTwoFingerDoubleTap_StateIsIdle_shouldInActivated() {
         goFromStateIdleTo(STATE_IDLE);
 
         twoFingerTap();
         twoFingerTap();
-        twoFingerTap();
 
         assertIn(STATE_ACTIVATED);
         verify(mMockMagnificationLogger, never()).logMagnificationTripleTap(anyBoolean());
@@ -546,13 +545,12 @@
 
     @Test
     @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE)
-    public void testTwoFingerTripleTap_StateIsActivated_shouldInIdle() {
+    public void testTwoFingerDoubleTap_StateIsActivated_shouldInIdle() {
         goFromStateIdleTo(STATE_ACTIVATED);
         reset(mMockMagnificationLogger);
 
         twoFingerTap();
         twoFingerTap();
-        twoFingerTap();
 
         assertIn(STATE_IDLE);
         verify(mMockMagnificationLogger, never()).logMagnificationTripleTap(anyBoolean());
@@ -561,11 +559,10 @@
 
     @Test
     @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE)
-    public void testTwoFingerTripleTapAndHold_StateIsIdle_shouldZoomsImmediately() {
+    public void testTwoFingerDoubleTapAndHold_StateIsIdle_shouldZoomsImmediately() {
         goFromStateIdleTo(STATE_IDLE);
 
         twoFingerTap();
-        twoFingerTap();
         twoFingerTapAndHold();
 
         assertIn(STATE_NON_ACTIVATED_ZOOMED_TMP);
@@ -575,11 +572,10 @@
 
     @Test
     @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE)
-    public void testTwoFingerTripleSwipeAndHold_StateIsIdle_shouldZoomsImmediately() {
+    public void testTwoFingerDoubleSwipeAndHold_StateIsIdle_shouldZoomsImmediately() {
         goFromStateIdleTo(STATE_IDLE);
 
         twoFingerTap();
-        twoFingerTap();
         twoFingerSwipeAndHold();
 
         assertIn(STATE_NON_ACTIVATED_ZOOMED_TMP);
@@ -717,6 +713,45 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE)
+    public void testSecondFingerSwipe_twoPointerDownAndActivatedState_shouldInPanningState() {
+        goFromStateIdleTo(STATE_ACTIVATED);
+        PointF pointer1 = DEFAULT_POINT;
+        PointF pointer2 = new PointF(DEFAULT_X * 1.5f, DEFAULT_Y);
+
+        send(downEvent());
+        send(pointerEvent(ACTION_POINTER_DOWN, new PointF[] {pointer1, pointer2}, 1));
+        //The minimum movement to transit to panningState.
+        final float sWipeMinDistance = ViewConfiguration.get(mContext).getScaledTouchSlop();
+        pointer2.offset(sWipeMinDistance + 1, 0);
+        send(pointerEvent(ACTION_MOVE, new PointF[] {pointer1, pointer2}, 1));
+        fastForward(ViewConfiguration.getTapTimeout());
+        assertIn(STATE_PANNING);
+
+        returnToNormalFrom(STATE_PANNING);
+    }
+
+    @Test
+    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE)
+    public void testTowFingerSwipe_twoPointerDownAndShortcutTriggeredState_shouldInPanningState() {
+        goFromStateIdleTo(STATE_SHORTCUT_TRIGGERED);
+        PointF pointer1 = DEFAULT_POINT;
+        PointF pointer2 = new PointF(DEFAULT_X * 1.5f, DEFAULT_Y);
+
+        send(downEvent());
+        send(pointerEvent(ACTION_POINTER_DOWN, new PointF[] {pointer1, pointer2}, 1));
+        //The minimum movement to transit to panningState.
+        final float sWipeMinDistance = ViewConfiguration.get(mContext).getScaledTouchSlop();
+        pointer2.offset(sWipeMinDistance + 1, 0);
+        send(pointerEvent(ACTION_MOVE, new PointF[] {pointer1, pointer2}, 1));
+        fastForward(ViewConfiguration.getTapTimeout());
+        assertIn(STATE_PANNING);
+
+        returnToNormalFrom(STATE_PANNING);
+    }
+
+    @Test
+    @RequiresFlagsDisabled(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE)
     public void testSecondFingerSwipe_twoPointerDownAndActivatedState_panningState() {
         goFromStateIdleTo(STATE_ACTIVATED);
         PointF pointer1 = DEFAULT_POINT;
@@ -734,6 +769,7 @@
     }
 
     @Test
+    @RequiresFlagsDisabled(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE)
     public void testSecondFingerSwipe_twoPointerDownAndShortcutTriggeredState_panningState() {
         goFromStateIdleTo(STATE_SHORTCUT_TRIGGERED);
         PointF pointer1 = DEFAULT_POINT;
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationConnectionManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationConnectionManagerTest.java
index a7cf361..009bfb7 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationConnectionManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationConnectionManagerTest.java
@@ -52,8 +52,8 @@
 import android.test.mock.MockContentResolver;
 import android.view.InputDevice;
 import android.view.MotionEvent;
+import android.view.accessibility.IMagnificationConnectionCallback;
 import android.view.accessibility.IRemoteMagnificationAnimationCallback;
-import android.view.accessibility.IWindowMagnificationConnectionCallback;
 import android.view.accessibility.MagnificationAnimationCallback;
 
 import androidx.test.core.app.ApplicationProvider;
@@ -146,7 +146,7 @@
         assertTrue(mMagnificationConnectionManager.isConnected());
         verify(mMockConnection.asBinder()).linkToDeath(any(IBinder.DeathRecipient.class), eq(0));
         verify(mMockConnection.getConnection()).setConnectionCallback(
-                any(IWindowMagnificationConnectionCallback.class));
+                any(IMagnificationConnectionCallback.class));
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationConnectionWrapperTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationConnectionWrapperTest.java
index 8fdd884..07f3036 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationConnectionWrapperTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationConnectionWrapperTest.java
@@ -25,8 +25,8 @@
 import android.provider.Settings;
 import android.view.Display;
 import android.view.accessibility.IMagnificationConnection;
+import android.view.accessibility.IMagnificationConnectionCallback;
 import android.view.accessibility.IRemoteMagnificationAnimationCallback;
-import android.view.accessibility.IWindowMagnificationConnectionCallback;
 import android.view.accessibility.MagnificationAnimationCallback;
 
 import com.android.server.accessibility.AccessibilityTraceManager;
@@ -49,7 +49,7 @@
     @Mock
     private AccessibilityTraceManager mTrace;
     @Mock
-    private IWindowMagnificationConnectionCallback mCallback;
+    private IMagnificationConnectionCallback mCallback;
     @Mock
     private MagnificationAnimationCallback mAnimationCallback;
 
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MockMagnificationConnection.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MockMagnificationConnection.java
index 3d3d0b7..35b6c90 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MockMagnificationConnection.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MockMagnificationConnection.java
@@ -32,8 +32,8 @@
 import android.os.RemoteException;
 import android.view.Display;
 import android.view.accessibility.IMagnificationConnection;
+import android.view.accessibility.IMagnificationConnectionCallback;
 import android.view.accessibility.IRemoteMagnificationAnimationCallback;
-import android.view.accessibility.IWindowMagnificationConnectionCallback;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -53,7 +53,7 @@
     private boolean mHasPendingCallback = false;
     private boolean mWindowMagnificationEnabled = false;
     private IBinder.DeathRecipient mDeathRecipient;
-    private IWindowMagnificationConnectionCallback mIMirrorWindowCallback;
+    private IMagnificationConnectionCallback mIMagnificationCallback;
 
     private Rect mMirrorWindowFrame = new Rect(0, 0, 500, 500);
     private float mScale = 2.0f;
@@ -74,10 +74,10 @@
         mBinder = mock(Binder.class);
         when(mConnection.asBinder()).thenReturn(mBinder);
         doAnswer((invocation) -> {
-            mIMirrorWindowCallback = invocation.getArgument(0);
+            mIMagnificationCallback = invocation.getArgument(0);
             return null;
         }).when(mConnection).setConnectionCallback(
-                any(IWindowMagnificationConnectionCallback.class));
+                any(IMagnificationConnectionCallback.class));
 
         doAnswer((invocation) -> {
             mDeathRecipient = invocation.getArgument(0);
@@ -166,8 +166,8 @@
         return mDeathRecipient;
     }
 
-    IWindowMagnificationConnectionCallback getConnectionCallback() {
-        return mIMirrorWindowCallback;
+    IMagnificationConnectionCallback getConnectionCallback() {
+        return mIMagnificationCallback;
     }
 
     Rect getMirrorWindowFrame() {
@@ -185,10 +185,10 @@
         if (!mHasPendingCallback) {
             throw new IllegalStateException("There is no any pending callbacks");
         }
-        if (mWindowMagnificationEnabled && mIMirrorWindowCallback != null) {
-            mIMirrorWindowCallback.onWindowMagnifierBoundsChanged(TEST_DISPLAY,
+        if (mWindowMagnificationEnabled && mIMagnificationCallback != null) {
+            mIMagnificationCallback.onWindowMagnifierBoundsChanged(TEST_DISPLAY,
                     mMirrorWindowFrame);
-            mIMirrorWindowCallback.onSourceBoundsChanged(TEST_DISPLAY,
+            mIMagnificationCallback.onSourceBoundsChanged(TEST_DISPLAY,
                     mSourceBounds);
         }
         sendAnimationEndCallbackIfNeeded(success);
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/TwoFingersDownOrSwipeTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/TwoFingersDownOrSwipeTest.java
index 162d2a9..d94faec 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/TwoFingersDownOrSwipeTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/TwoFingersDownOrSwipeTest.java
@@ -20,6 +20,7 @@
 import static com.android.server.accessibility.utils.TouchEventGenerator.twoPointersDownEvents;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.after;
 import static org.mockito.Mockito.timeout;
@@ -27,6 +28,10 @@
 
 import android.content.Context;
 import android.graphics.PointF;
+import android.platform.test.annotations.RequiresFlagsDisabled;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 import android.view.Display;
 import android.view.MotionEvent;
 import android.view.ViewConfiguration;
@@ -37,6 +42,7 @@
 
 import org.junit.Before;
 import org.junit.BeforeClass;
+import org.junit.Rule;
 import org.junit.Test;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
@@ -48,6 +54,9 @@
  */
 public class TwoFingersDownOrSwipeTest {
 
+    @Rule
+    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
     private static final float DEFAULT_X = 100f;
     private static final float DEFAULT_Y = 100f;
 
@@ -85,7 +94,8 @@
     }
 
     @Test
-    public void sendTwoFingerDownEvent_onGestureCompleted() {
+    @RequiresFlagsDisabled(android.view.accessibility.Flags.FLAG_COPY_EVENTS_FOR_GESTURE_DETECTION)
+    public void sendTwoFingerDownEvent_onGestureCompleted_withoutCopiedEvents() {
         final List<MotionEvent> downEvents = twoPointersDownEvents(Display.DEFAULT_DISPLAY,
                 new PointF(DEFAULT_X, DEFAULT_Y), new PointF(DEFAULT_X + 10, DEFAULT_Y + 10));
 
@@ -99,6 +109,23 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(android.view.accessibility.Flags.FLAG_COPY_EVENTS_FOR_GESTURE_DETECTION)
+    public void sendTwoFingerDownEvent_onGestureCompleted() {
+        final List<MotionEvent> downEvents = twoPointersDownEvents(Display.DEFAULT_DISPLAY,
+                new PointF(DEFAULT_X, DEFAULT_Y), new PointF(DEFAULT_X + 10, DEFAULT_Y + 10));
+
+        for (MotionEvent event : downEvents) {
+            mGesturesObserver.onMotionEvent(event, event, 0);
+        }
+
+        verify(mListener, timeout(sTimeoutMillis)).onGestureCompleted(
+                eq(MagnificationGestureMatcher.GESTURE_TWO_FINGERS_DOWN_OR_SWIPE),
+                argThat(argument -> downEvents.get(1).getId() == argument.getId()),
+                argThat(argument -> downEvents.get(1).getId() == argument.getId()),
+                eq(0));
+    }
+
+    @Test
     public void sendSingleTapEvent_onGestureCancelled() {
         final MotionEvent downEvent = TouchEventGenerator.downEvent(Display.DEFAULT_DISPLAY,
                 DEFAULT_X, DEFAULT_Y);
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java
index a3b67ae..c99e040 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java
@@ -72,15 +72,15 @@
     public static final int STATE_SHOW_MAGNIFIER_TRIPLE_TAP = 4;
     public static final int STATE_NOT_ENABLED_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD = 5;
     public static final int STATE_ENABLED_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD = 6;
-    public static final int STATE_SHOW_MAGNIFIER_TWO_FINGER_TRIPLE_TAP = 7;
-    public static final int STATE_NOT_ENABLED_SHOW_MAGNIFIER_TWO_FINGER_TRIPLE_TAP_AND_HOLD = 8;
-    public static final int STATE_ENABLED_SHOW_MAGNIFIER_TWO_FINGER_TRIPLE_TAP_AND_HOLD = 9;
+    public static final int STATE_SHOW_MAGNIFIER_TWO_FINGER_DOUBLE_TAP = 7;
+    public static final int STATE_NOT_ENABLED_SHOW_MAGNIFIER_TWO_FINGER_DOUBLE_TAP_AND_HOLD = 8;
+    public static final int STATE_ENABLED_SHOW_MAGNIFIER_TWO_FINGER_DOUBLE_TAP_AND_HOLD = 9;
     //TODO: Test it after can injecting Handler to GestureMatcher is available.
 
     public static final int FIRST_STATE = STATE_IDLE;
     public static final int LAST_STATE = STATE_ENABLED_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD;
     public static final int LAST_STATE_WITH_MULTI_FINGER =
-            STATE_ENABLED_SHOW_MAGNIFIER_TWO_FINGER_TRIPLE_TAP_AND_HOLD;
+            STATE_ENABLED_SHOW_MAGNIFIER_TWO_FINGER_DOUBLE_TAP_AND_HOLD;
 
     // Co-prime x and y, to potentially catch x-y-swapped errors
     public static final float DEFAULT_TAP_X = 301;
@@ -257,15 +257,15 @@
             break;
             case STATE_SHOW_MAGNIFIER_SHORTCUT:
             case STATE_SHOW_MAGNIFIER_TRIPLE_TAP:
-            case STATE_SHOW_MAGNIFIER_TWO_FINGER_TRIPLE_TAP:
+            case STATE_SHOW_MAGNIFIER_TWO_FINGER_DOUBLE_TAP:
                 check(isWindowMagnifierEnabled(DISPLAY_0), state);
                 check(mWindowMagnificationGestureHandler.mCurrentState
                         == mWindowMagnificationGestureHandler.mDetectingState, state);
                 break;
             case STATE_NOT_ENABLED_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD:
             case STATE_ENABLED_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD:
-            case STATE_NOT_ENABLED_SHOW_MAGNIFIER_TWO_FINGER_TRIPLE_TAP_AND_HOLD:
-            case STATE_ENABLED_SHOW_MAGNIFIER_TWO_FINGER_TRIPLE_TAP_AND_HOLD: {
+            case STATE_NOT_ENABLED_SHOW_MAGNIFIER_TWO_FINGER_DOUBLE_TAP_AND_HOLD:
+            case STATE_ENABLED_SHOW_MAGNIFIER_TWO_FINGER_DOUBLE_TAP_AND_HOLD: {
                 check(isWindowMagnifierEnabled(DISPLAY_0), state);
                 check(mWindowMagnificationGestureHandler.mCurrentState
                         == mWindowMagnificationGestureHandler.mViewportDraggingState, state);
@@ -337,8 +337,7 @@
                     tapAndHold();
                 }
                 break;
-                case STATE_SHOW_MAGNIFIER_TWO_FINGER_TRIPLE_TAP: {
-                    twoFingerTap();
+                case STATE_SHOW_MAGNIFIER_TWO_FINGER_DOUBLE_TAP: {
                     twoFingerTap();
                     twoFingerTap();
                     // Wait for two-finger tap gesture completed.
@@ -346,17 +345,15 @@
                     InstrumentationRegistry.getInstrumentation().waitForIdleSync();
                 }
                 break;
-                case STATE_NOT_ENABLED_SHOW_MAGNIFIER_TWO_FINGER_TRIPLE_TAP_AND_HOLD: {
-                    twoFingerTap();
+                case STATE_NOT_ENABLED_SHOW_MAGNIFIER_TWO_FINGER_DOUBLE_TAP_AND_HOLD: {
                     twoFingerTap();
                     twoFingerTapAndHold();
                 }
                 break;
-                case STATE_ENABLED_SHOW_MAGNIFIER_TWO_FINGER_TRIPLE_TAP_AND_HOLD: {
+                case STATE_ENABLED_SHOW_MAGNIFIER_TWO_FINGER_DOUBLE_TAP_AND_HOLD: {
                     // enabled then perform two finger triple tap and hold gesture
                     goFromStateIdleTo(STATE_SHOW_MAGNIFIER_SHORTCUT);
                     twoFingerTap();
-                    twoFingerTap();
                     twoFingerTapAndHold();
                 }
                 break;
@@ -394,16 +391,15 @@
             }
             break;
             case STATE_NOT_ENABLED_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD:
-            case STATE_NOT_ENABLED_SHOW_MAGNIFIER_TWO_FINGER_TRIPLE_TAP_AND_HOLD:
+            case STATE_NOT_ENABLED_SHOW_MAGNIFIER_TWO_FINGER_DOUBLE_TAP_AND_HOLD:
                 send(upEvent(DEFAULT_TAP_X, DEFAULT_TAP_Y));
                 break;
             case STATE_ENABLED_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD:
-            case STATE_ENABLED_SHOW_MAGNIFIER_TWO_FINGER_TRIPLE_TAP_AND_HOLD:
+            case STATE_ENABLED_SHOW_MAGNIFIER_TWO_FINGER_DOUBLE_TAP_AND_HOLD:
                 send(upEvent(DEFAULT_TAP_X, DEFAULT_TAP_Y));
                 returnToNormalFrom(STATE_SHOW_MAGNIFIER_SHORTCUT);
                 break;
-            case STATE_SHOW_MAGNIFIER_TWO_FINGER_TRIPLE_TAP: {
-                twoFingerTap();
+            case STATE_SHOW_MAGNIFIER_TWO_FINGER_DOUBLE_TAP: {
                 twoFingerTap();
                 twoFingerTap();
                 // Wait for two-finger tap gesture completed.
diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
index d26d671..77b1455 100644
--- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
@@ -92,6 +92,7 @@
 import android.os.UserManager;
 import android.os.storage.IStorageManager;
 import android.platform.test.annotations.Presubmit;
+import android.platform.test.flag.junit.SetFlagsRule;
 import android.util.Log;
 import android.view.Display;
 
@@ -104,11 +105,14 @@
 import com.android.server.pm.UserJourneyLogger;
 import com.android.server.pm.UserManagerInternal;
 import com.android.server.pm.UserManagerService;
+import com.android.server.pm.UserTypeDetails;
+import com.android.server.pm.UserTypeFactory;
 import com.android.server.wm.ActivityTaskManagerInternal;
 import com.android.server.wm.WindowManagerService;
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
 
@@ -175,6 +179,9 @@
             USER_START_MSG,
             REPORT_LOCKED_BOOT_COMPLETE_MSG);
 
+    @Rule
+    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
     @Before
     public void setUp() throws Exception {
         runWithDexmakerShareClassLoader(() -> {
@@ -789,30 +796,101 @@
     }
 
     @Test
-    public void testStartProfile() throws Exception {
-        setUpAndStartProfileInBackground(TEST_USER_ID1);
+    public void testStartManagedProfile() throws Exception {
+        setUpAndStartProfileInBackground(TEST_USER_ID1, UserManager.USER_TYPE_PROFILE_MANAGED);
 
         startBackgroundUserAssertions();
         verifyUserAssignedToDisplay(TEST_USER_ID1, Display.DEFAULT_DISPLAY);
     }
 
     @Test
-    public void testStartProfile_whenUsersOnSecondaryDisplaysIsEnabled() throws Exception {
+    public void testStartManagedProfile_whenUsersOnSecondaryDisplaysIsEnabled() throws Exception {
         mockIsUsersOnSecondaryDisplaysEnabled(true);
 
-        setUpAndStartProfileInBackground(TEST_USER_ID1);
+        setUpAndStartProfileInBackground(TEST_USER_ID1, UserManager.USER_TYPE_PROFILE_MANAGED);
 
         startBackgroundUserAssertions();
         verifyUserAssignedToDisplay(TEST_USER_ID1, Display.DEFAULT_DISPLAY);
     }
 
     @Test
-    public void testStopProfile() throws Exception {
-        setUpAndStartProfileInBackground(TEST_USER_ID1);
+    public void testStopManagedProfile() throws Exception {
+        setUpAndStartProfileInBackground(TEST_USER_ID1, UserManager.USER_TYPE_PROFILE_MANAGED);
         assertProfileLockedOrUnlockedAfterStopping(TEST_USER_ID1, /* expectLocking= */ true);
         verifyUserUnassignedFromDisplay(TEST_USER_ID1);
     }
 
+    @Test
+    public void testStopPrivateProfile() throws Exception {
+        mUserController.setInitialConfig(/* mUserSwitchUiEnabled */ true,
+                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false);
+        mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_BIOMETRICS_TO_UNLOCK_PRIVATE_SPACE);
+        setUpAndStartProfileInBackground(TEST_USER_ID1, UserManager.USER_TYPE_PROFILE_PRIVATE);
+        assertProfileLockedOrUnlockedAfterStopping(TEST_USER_ID1, /* expectLocking= */ true);
+        verifyUserUnassignedFromDisplay(TEST_USER_ID1);
+
+        mSetFlagsRule.disableFlags(
+                android.multiuser.Flags.FLAG_ENABLE_BIOMETRICS_TO_UNLOCK_PRIVATE_SPACE);
+        setUpAndStartProfileInBackground(TEST_USER_ID2, UserManager.USER_TYPE_PROFILE_PRIVATE);
+        assertProfileLockedOrUnlockedAfterStopping(TEST_USER_ID2, /* expectLocking= */ true);
+        verifyUserUnassignedFromDisplay(TEST_USER_ID2);
+    }
+
+    @Test
+    public void testStopPrivateProfileWithDelayedLocking() throws Exception {
+        mUserController.setInitialConfig(/* mUserSwitchUiEnabled */ true,
+                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false);
+        mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_BIOMETRICS_TO_UNLOCK_PRIVATE_SPACE);
+        setUpAndStartProfileInBackground(TEST_USER_ID1, UserManager.USER_TYPE_PROFILE_PRIVATE);
+        assertUserLockedOrUnlockedAfterStopping(TEST_USER_ID1, /* delayedLocking= */ true,
+                /* keyEvictedCallback */ null, /* expectLocking= */ false);
+    }
+
+    @Test
+    public void testStopPrivateProfileWithDelayedLocking_flagDisabled() throws Exception {
+        mUserController.setInitialConfig(/* mUserSwitchUiEnabled */ true,
+                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false);
+        mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        mSetFlagsRule.disableFlags(
+                android.multiuser.Flags.FLAG_ENABLE_BIOMETRICS_TO_UNLOCK_PRIVATE_SPACE);
+        setUpAndStartProfileInBackground(TEST_USER_ID1, UserManager.USER_TYPE_PROFILE_PRIVATE);
+        assertUserLockedOrUnlockedAfterStopping(TEST_USER_ID1, /* delayedLocking= */ true,
+                /* keyEvictedCallback */ null, /* expectLocking= */ true);
+
+        mSetFlagsRule.disableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        mSetFlagsRule.enableFlags(
+                android.multiuser.Flags.FLAG_ENABLE_BIOMETRICS_TO_UNLOCK_PRIVATE_SPACE);
+        setUpAndStartProfileInBackground(TEST_USER_ID2, UserManager.USER_TYPE_PROFILE_PRIVATE);
+        assertUserLockedOrUnlockedAfterStopping(TEST_USER_ID2, /* delayedLocking= */ true,
+                /* keyEvictedCallback */ null, /* expectLocking= */ true);
+    }
+
+    @Test
+    public void testStopPrivateProfileWithDelayedLocking_maxRunningUsersBreached()
+            throws Exception {
+        mUserController.setInitialConfig(/* mUserSwitchUiEnabled */ true,
+                /* maxRunningUsers= */ 1, /* delayUserDataLocking= */ false);
+        mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_BIOMETRICS_TO_UNLOCK_PRIVATE_SPACE);
+        setUpAndStartProfileInBackground(TEST_USER_ID1, UserManager.USER_TYPE_PROFILE_PRIVATE);
+        setUpAndStartProfileInBackground(TEST_USER_ID2, UserManager.USER_TYPE_PROFILE_MANAGED);
+        assertUserLockedOrUnlockedAfterStopping(TEST_USER_ID1, /* delayedLocking= */ true,
+                /* keyEvictedCallback */ null, /* expectLocking= */ true);
+    }
+
+    @Test
+    public void testStopManagedProfileWithDelayedLocking() throws Exception {
+        mUserController.setInitialConfig(/* mUserSwitchUiEnabled */ true,
+                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false);
+        mSetFlagsRule.enableFlags(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
+                android.multiuser.Flags.FLAG_ENABLE_BIOMETRICS_TO_UNLOCK_PRIVATE_SPACE);
+        setUpAndStartProfileInBackground(TEST_USER_ID1, UserManager.USER_TYPE_PROFILE_MANAGED);
+        assertUserLockedOrUnlockedAfterStopping(TEST_USER_ID1, /* delayedLocking= */ true,
+                /* keyEvictedCallback */ null, /* expectLocking= */ true);
+    }
+
     /** Tests handleIncomingUser() for a variety of permissions and situations. */
     @Test
     public void testHandleIncomingUser() throws Exception {
@@ -1001,8 +1079,8 @@
         mUserStates.put(userId, mUserController.getStartedUserState(userId));
     }
 
-    private void setUpAndStartProfileInBackground(int userId) throws Exception {
-        setUpUser(userId, UserInfo.FLAG_PROFILE, false, UserManager.USER_TYPE_PROFILE_MANAGED);
+    private void setUpAndStartProfileInBackground(int userId, String userType) throws Exception {
+        setUpUser(userId, UserInfo.FLAG_PROFILE, false, userType);
         assertThat(mUserController.startProfile(userId, /* evenWhenDisabled=*/ false,
                 /* unlockListener= */ null)).isTrue();
 
@@ -1070,6 +1148,11 @@
         userInfo.preCreated = preCreated;
         when(mInjector.mUserManagerMock.getUserInfo(eq(userId))).thenReturn(userInfo);
         when(mInjector.mUserManagerMock.isPreCreated(userId)).thenReturn(preCreated);
+
+        UserTypeDetails userTypeDetails = UserTypeFactory.getUserTypes().get(userType);
+        assertThat(userTypeDetails).isNotNull();
+        when(mInjector.mUserManagerInternalMock.getUserProperties(eq(userId)))
+                .thenReturn(userTypeDetails.getDefaultUserPropertiesReference());
     }
 
     private static List<String> getActions(List<Intent> intents) {
diff --git a/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java b/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java
index cc3c880..f1c1dc3 100644
--- a/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java
+++ b/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java
@@ -266,18 +266,22 @@
                     .adoptShellPermissionIdentity(Manifest.permission.BLUETOOTH_PRIVILEGED);
 
             // no metadata set
-            assertTrue(mFakeBtDevice.setMetadata(BluetoothDevice.METADATA_DEVICE_TYPE,
-                    DEVICE_TYPE_DEFAULT.getBytes()));
-            assertFalse(
-                    mAudioDeviceBroker.isBluetoothAudioDeviceCategoryFixed(
-                            mFakeBtDevice.getAddress()));
+            if (mFakeBtDevice.setMetadata(BluetoothDevice.METADATA_DEVICE_TYPE,
+                    DEVICE_TYPE_DEFAULT.getBytes())) {
+                assertFalse(mAudioDeviceBroker.isBluetoothAudioDeviceCategoryFixed(
+                        mFakeBtDevice.getAddress()));
+            }
 
             // metadata set
-            assertTrue(mFakeBtDevice.setMetadata(BluetoothDevice.METADATA_DEVICE_TYPE,
-                    DEVICE_TYPE_HEADSET.getBytes()));
-            assertTrue(mAudioDeviceBroker.isBluetoothAudioDeviceCategoryFixed(
-                    mFakeBtDevice.getAddress()));
+            if (mFakeBtDevice.setMetadata(BluetoothDevice.METADATA_DEVICE_TYPE,
+                    DEVICE_TYPE_HEADSET.getBytes())) {
+                assertTrue(mAudioDeviceBroker.isBluetoothAudioDeviceCategoryFixed(
+                        mFakeBtDevice.getAddress()));
+            }
         } finally {
+            // reset the metadata device type
+            mFakeBtDevice.setMetadata(BluetoothDevice.METADATA_DEVICE_TYPE,
+                    DEVICE_TYPE_DEFAULT.getBytes());
             InstrumentationRegistry.getInstrumentation().getUiAutomation()
                     .dropShellPermissionIdentity();
         }
@@ -304,25 +308,30 @@
                     .adoptShellPermissionIdentity(Manifest.permission.BLUETOOTH_PRIVILEGED);
 
             // no metadata set
-            assertTrue(mFakeBtDevice.setMetadata(BluetoothDevice.METADATA_DEVICE_TYPE,
-                    DEVICE_TYPE_DEFAULT.getBytes()));
-            assertEquals(AudioManager.AUDIO_DEVICE_CATEGORY_SPEAKER,
-                    mAudioDeviceBroker.getAndUpdateBtAdiDeviceStateCategoryForAddress(
-                            mFakeBtDevice.getAddress()));
-            verify(mMockAudioService,
-                    timeout(MAX_MESSAGE_HANDLING_DELAY_MS).times(0)).onUpdatedAdiDeviceState(
-                    eq(devState));
+            if (mFakeBtDevice.setMetadata(BluetoothDevice.METADATA_DEVICE_TYPE,
+                    DEVICE_TYPE_DEFAULT.getBytes())) {
+                assertEquals(AudioManager.AUDIO_DEVICE_CATEGORY_SPEAKER,
+                        mAudioDeviceBroker.getAndUpdateBtAdiDeviceStateCategoryForAddress(
+                                mFakeBtDevice.getAddress()));
+                verify(mMockAudioService,
+                        timeout(MAX_MESSAGE_HANDLING_DELAY_MS).times(0)).onUpdatedAdiDeviceState(
+                        eq(devState));
+            }
 
             // metadata set
-            assertTrue(mFakeBtDevice.setMetadata(BluetoothDevice.METADATA_DEVICE_TYPE,
-                    DEVICE_TYPE_HEADSET.getBytes()));
-            assertEquals(AudioManager.AUDIO_DEVICE_CATEGORY_HEADPHONES,
-                    mAudioDeviceBroker.getAndUpdateBtAdiDeviceStateCategoryForAddress(
-                            mFakeBtDevice.getAddress()));
-            verify(mMockAudioService,
-                    timeout(MAX_MESSAGE_HANDLING_DELAY_MS)).onUpdatedAdiDeviceState(
-                    any());
+            if (mFakeBtDevice.setMetadata(BluetoothDevice.METADATA_DEVICE_TYPE,
+                    DEVICE_TYPE_HEADSET.getBytes())) {
+                assertEquals(AudioManager.AUDIO_DEVICE_CATEGORY_HEADPHONES,
+                        mAudioDeviceBroker.getAndUpdateBtAdiDeviceStateCategoryForAddress(
+                                mFakeBtDevice.getAddress()));
+                verify(mMockAudioService,
+                        timeout(MAX_MESSAGE_HANDLING_DELAY_MS)).onUpdatedAdiDeviceState(
+                        any());
+            }
         } finally {
+            // reset the metadata device type
+            mFakeBtDevice.setMetadata(BluetoothDevice.METADATA_DEVICE_TYPE,
+                    DEVICE_TYPE_DEFAULT.getBytes());
             InstrumentationRegistry.getInstrumentation().getUiAutomation()
                     .dropShellPermissionIdentity();
         }
diff --git a/services/tests/servicestests/src/com/android/server/audio/MusicFxHelperTest.java b/services/tests/servicestests/src/com/android/server/audio/MusicFxHelperTest.java
new file mode 100644
index 0000000..472a82c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/audio/MusicFxHelperTest.java
@@ -0,0 +1,642 @@
+/*
+ * 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 com.android.server.audio;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyObject;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.media.audiofx.AudioEffect;
+import android.os.Message;
+import android.util.Log;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class MusicFxHelperTest {
+    private static final String TAG = "MusicFxHelperTest";
+
+    @Mock private AudioService mMockAudioService;
+    @Mock private Context mMockContext;
+    @Mock private PackageManager mMockPackageManager;
+
+    private ResolveInfo mResolveInfo1 = new ResolveInfo();
+    private ResolveInfo mResolveInfo2 = new ResolveInfo();
+    private final String mTestPkg1 = "testPkg1", mTestPkg2 = "testPkg2", mTestPkg3 = "testPkg3";
+    private final String mMusicFxPkgName = "com.android.musicfx";
+    private final int mTestUid1 = 1, mTestUid2 = 2, mTestUid3 = 3, mMusicFxUid = 78;
+    private final int mTestSession1 = 11, mTestSession2 = 22, mTestSession3 = 33;
+
+    private List<ResolveInfo> mEmptyList = new ArrayList<>();
+    private List<ResolveInfo> mSingleList = new ArrayList<>();
+    private List<ResolveInfo> mDoubleList = new ArrayList<>();
+
+    // the class being unit-tested here
+    @InjectMocks private MusicFxHelper mMusicFxHelper;
+
+    @Before
+    @SuppressWarnings("DirectInvocationOnMock")
+    public void setUp() throws Exception {
+        mMockAudioService = mock(AudioService.class);
+        mMusicFxHelper = mMockAudioService.getMusicFxHelper();
+        MockitoAnnotations.initMocks(this);
+
+        mResolveInfo1.activityInfo = new ActivityInfo();
+        mResolveInfo1.activityInfo.packageName = mTestPkg1;
+        mResolveInfo2.activityInfo = new ActivityInfo();
+        mResolveInfo2.activityInfo.packageName = mTestPkg2;
+
+        mSingleList.add(mResolveInfo1);
+        mDoubleList.add(mResolveInfo1);
+        mDoubleList.add(mResolveInfo2);
+
+        Assert.assertNotNull(mMusicFxHelper);
+    }
+
+    private Intent newIntent(String action, String packageName, int sessionId) {
+        Intent intent = new Intent(action);
+        if (packageName != null) {
+            intent.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, packageName);
+        }
+        intent.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, sessionId);
+        return intent;
+    }
+
+    /**
+     * Helper function to send ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION intent with verification.
+     *
+     * @throws NameNotFoundException if no such package is available to the caller.
+     */
+    private void openSessionWithResList(
+            List<ResolveInfo> list, int bind, int broadcast, String packageName, int audioSession,
+            int uid) {
+        doReturn(mMockPackageManager).when(mMockContext).getPackageManager();
+        doReturn(list).when(mMockPackageManager).queryBroadcastReceivers(anyObject(), anyInt());
+        if (list != null && list.size() != 0) {
+            try {
+                doReturn(uid).when(mMockPackageManager)
+                        .getPackageUidAsUser(eq(packageName), anyObject(), anyInt());
+                doReturn(mMusicFxUid).when(mMockPackageManager)
+                        .getPackageUidAsUser(eq(mMusicFxPkgName), anyObject(), anyInt());
+            } catch (PackageManager.NameNotFoundException e) {
+                Log.e(TAG, "NameNotFoundException: " + e);
+            }
+        }
+
+        Intent intent = newIntent(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION,
+                packageName, audioSession);
+        mMusicFxHelper.handleAudioEffectBroadcast(mMockContext, intent);
+        verify(mMockContext, times(bind))
+                .bindServiceAsUser(anyObject(), anyObject(), anyInt(), anyObject());
+        verify(mMockContext, times(broadcast)).sendBroadcastAsUser(anyObject(), anyObject());
+    }
+
+    /**
+     * Helper function to send ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION intent with verification.
+     *
+     * @throws NameNotFoundException if no such package is available to the caller.
+     */
+    private void closeSessionWithResList(
+                List<ResolveInfo> list, int unBind, int broadcast, String packageName,
+                int audioSession, int uid) {
+        doReturn(mMockPackageManager).when(mMockContext).getPackageManager();
+        doReturn(list).when(mMockPackageManager).queryBroadcastReceivers(anyObject(), anyInt());
+        if (list != null && list.size() != 0) {
+            try {
+                doReturn(uid).when(mMockPackageManager)
+                        .getPackageUidAsUser(eq(packageName), anyObject(), anyInt());
+                doReturn(mMusicFxUid).when(mMockPackageManager)
+                        .getPackageUidAsUser(eq(mMusicFxPkgName), anyObject(), anyInt());
+            } catch (PackageManager.NameNotFoundException e) {
+                Log.e(TAG, "NameNotFoundException: " + e);
+            }
+        }
+
+        Intent intent = newIntent(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION,
+                                packageName, audioSession);
+        mMusicFxHelper.handleAudioEffectBroadcast(mMockContext, intent);
+        verify(mMockContext, times(unBind)).unbindService(anyObject());
+        verify(mMockContext, times(broadcast)).sendBroadcastAsUser(anyObject(), anyObject());
+    }
+
+    /**
+     * Helper function to send MSG_EFFECT_CLIENT_GONE message with verification.
+     */
+    private void sendMessage(int msgId, int uid, int unBinds, int broadcasts) {
+        mMusicFxHelper.handleMessage(Message.obtain(null, msgId, uid /* arg1 */, 0 /* arg2 */));
+        verify(mMockContext, times(broadcasts)).sendBroadcastAsUser(anyObject(), anyObject());
+        verify(mMockContext, times(unBinds)).unbindService(anyObject());
+    }
+
+    /**
+     * Send invalid message to MusicFxHelper.
+     */
+    @Test
+    public void testInvalidMessage() {
+        Log.i(TAG, "running testInvalidMessage");
+
+        sendMessage(MusicFxHelper.MSG_EFFECT_CLIENT_GONE - 1, 0, 0, 0);
+        sendMessage(MusicFxHelper.MSG_EFFECT_CLIENT_GONE + 1, 0, 0, 0);
+    }
+
+    /**
+     * Send client gone message to MusicFxHelper when no client exist.
+     */
+    @Test
+    public void testGoneMessageWhenNoClient() {
+        Log.i(TAG, "running testGoneMessageWhenNoClient");
+
+        sendMessage(MusicFxHelper.MSG_EFFECT_CLIENT_GONE, 0, 0, 0);
+    }
+
+    /**
+     * Send ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION intent to MusicFxHelper when no session exist.
+     */
+    @Test
+    public void testCloseBroadcastIntent() {
+        Log.i(TAG, "running testCloseBroadcastIntent");
+
+        closeSessionWithResList(null, 0, 0, null, mTestSession1, mTestUid1);
+    }
+
+    /**
+     * OPEN/CLOSE AUDIO_EFFECT_CONTROL_SESSION intent when target application package was set.
+     * When the target application package was set for an intent, it means this intent is limited
+     * to a specific target application, as a result MusicFxHelper will not handle this intent.
+     */
+    @Test
+    public void testBroadcastIntentWithPackage() {
+        Log.i(TAG, "running testBroadcastIntentWithPackage");
+
+        Intent intent = newIntent(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION, null, 1);
+        intent.setPackage(mTestPkg1);
+        mMusicFxHelper.handleAudioEffectBroadcast(mMockContext, intent);
+        verify(mMockContext, times(0))
+                .bindServiceAsUser(anyObject(), anyObject(), anyInt(), anyObject());
+        verify(mMockContext, times(0)).sendBroadcastAsUser(anyObject(), anyObject());
+
+        intent = newIntent(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION, null, 1);
+        intent.setPackage(mTestPkg2);
+        mMusicFxHelper.handleAudioEffectBroadcast(mMockContext, intent);
+        verify(mMockContext, times(0))
+                .bindServiceAsUser(anyObject(), anyObject(), anyInt(), anyObject());
+        verify(mMockContext, times(0)).sendBroadcastAsUser(anyObject(), anyObject());
+    }
+
+    /**
+     * OPEN/CLOSE AUDIO_EFFECT_CONTROL_SESSION with no broadcast receiver.
+     */
+    @Test
+    public void testBroadcastIntentWithNoPackageAndNoBroadcastReceiver() {
+        Log.i(TAG, "running testBroadcastIntentWithNoPackageAndNoBroadcastReceiver");
+
+        openSessionWithResList(mEmptyList, 0, 0, null, mTestSession1, mTestUid1);
+        closeSessionWithResList(mEmptyList, 0, 0, null, mTestSession1, mTestUid1);
+    }
+
+    /**
+     * OPEN/CLOSE AUDIO_EFFECT_CONTROL_SESSION with one broadcast receiver.
+     */
+    @Test
+    public void testBroadcastIntentWithNoPackageAndOneBroadcastReceiver() {
+        Log.i(TAG, "running testBroadcastIntentWithNoPackageAndOneBroadcastReceiver");
+
+        int broadcasts = 1, bind = 1, unbind = 1;
+        openSessionWithResList(mSingleList, bind, broadcasts, null, mTestSession1, mTestUid1);
+        broadcasts = broadcasts + 1;
+        closeSessionWithResList(mSingleList, unbind, broadcasts, null, mTestSession1, mTestUid1);
+
+        // repeat with different session ID
+        broadcasts = broadcasts + 1;
+        bind = bind + 1;
+        unbind = unbind + 1;
+        openSessionWithResList(mSingleList, bind, broadcasts, null, mTestSession2, mTestUid1);
+        broadcasts = broadcasts + 1;
+        closeSessionWithResList(mSingleList, unbind, broadcasts, null, mTestSession2, mTestUid1);
+
+        // repeat with different UID
+        broadcasts = broadcasts + 1;
+        bind = bind + 1;
+        unbind = unbind + 1;
+        openSessionWithResList(mSingleList, bind, broadcasts, null, mTestSession1, mTestUid2);
+        broadcasts = broadcasts + 1;
+        closeSessionWithResList(mSingleList, unbind, broadcasts, null, mTestSession1, mTestUid2);
+    }
+
+    /**
+     * OPEN/CLOSE AUDIO_EFFECT_CONTROL_SESSION with two broadcast receivers.
+     */
+    @Test
+    public void testBroadcastIntentWithNoPackageAndTwoBroadcastReceivers() {
+        Log.i(TAG, "running testBroadcastIntentWithNoPackageAndTwoBroadcastReceivers");
+
+        openSessionWithResList(mDoubleList, 1, 1, null, mTestSession1, mTestUid1);
+        closeSessionWithResList(mDoubleList, 1, 2, null, mTestSession1, mTestUid1);
+    }
+
+    /**
+     * Open/close session UID not matching.
+     * No broadcast for mismatching sessionID/UID/packageName.
+     */
+    @Test
+    public void testBroadcastBadIntents() {
+        Log.i(TAG, "running testBroadcastBadIntents");
+
+        int broadcasts = 1;
+        openSessionWithResList(mSingleList, 1, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+        // mismatch UID
+        closeSessionWithResList(mSingleList, 0, broadcasts, mTestPkg1, mTestSession1, mTestUid2);
+        // mismatch AudioSession
+        closeSessionWithResList(mSingleList, 0, broadcasts, mTestPkg1, mTestSession2, mTestUid1);
+        // mismatch packageName
+        closeSessionWithResList(mSingleList, 0, broadcasts, mTestPkg2, mTestSession1, mTestUid1);
+
+        // cleanup with correct UID and session ID
+        broadcasts = broadcasts + 1;
+        closeSessionWithResList(mSingleList, 1, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+    }
+
+    /**
+     * Open/close sessions with one UID, some with correct intents some with illegal intents.
+     * No broadcast for mismatching sessionID/UID/packageName.
+     */
+    @Test
+    public void testBroadcastGoodAndBadIntents() {
+        Log.i(TAG, "running testBroadcastGoodAndBadIntents");
+
+        int broadcasts = 1, bind = 1, unbind = 0;
+        openSessionWithResList(mSingleList, bind, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+        // mismatch packageName, session ID and UID
+        closeSessionWithResList(mSingleList, unbind, broadcasts, mTestPkg2, mTestSession2,
+                                mTestUid2);
+        // mismatch session ID and mismatch UID
+        closeSessionWithResList(mSingleList, unbind, broadcasts, mTestPkg1, mTestSession2,
+                                mTestUid2);
+        // mismatch packageName and mismatch UID
+        closeSessionWithResList(mSingleList, unbind, broadcasts, mTestPkg2, mTestSession1,
+                                mTestUid2);
+        // mismatch packageName and sessionID
+        closeSessionWithResList(mSingleList, unbind, broadcasts, mTestPkg2, mTestSession2,
+                                mTestUid1);
+        // inconsistency package name for same UID
+        openSessionWithResList(mSingleList, bind, broadcasts, mTestPkg2, mTestSession2, mTestUid1);
+        // open session2 with good intent
+        broadcasts = broadcasts + 1;
+        openSessionWithResList(mSingleList, bind, broadcasts, mTestPkg1, mTestSession2, mTestUid1);
+
+        // cleanup with correct UID and session ID
+        broadcasts = broadcasts + 1;
+        closeSessionWithResList(mSingleList, unbind, broadcasts, mTestPkg1, mTestSession1,
+                                mTestUid1);
+        broadcasts = broadcasts + 1;
+        unbind = unbind + 1;
+        closeSessionWithResList(mSingleList, unbind, broadcasts, mTestPkg1, mTestSession2,
+                                mTestUid1);
+    }
+
+    /**
+     * Send ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION when there is no listener.
+     */
+    @Test
+    public void testBroadcastOpenSessionWithValidPackageNameAndNoListener() {
+        Log.i(TAG, "running testBroadcastOpenSessionWithValidPackageNameAndNoListener");
+
+        // null listener list should not trigger any action
+        openSessionWithResList(null, 0, 0, mTestPkg1, mTestSession1, mTestUid1);
+        // empty listener list should not trigger any action
+        openSessionWithResList(mEmptyList, 0, 0, mTestPkg1, mTestSession1, mTestUid1);
+    }
+
+    /**
+     * One MusicFx client, open session and close.
+     */
+    @Test
+    public void testOpenCloseAudioSession() {
+        Log.i(TAG, "running testOpenCloseAudioSession");
+
+        int broadcasts = 1;
+        openSessionWithResList(mDoubleList, 1, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+        broadcasts = broadcasts + 1;
+        closeSessionWithResList(mDoubleList, 1, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+    }
+
+    /**
+     * One MusicFx client, open session and close, then gone.
+     */
+    @Test
+    public void testOpenCloseAudioSessionAndGone() {
+        Log.i(TAG, "running testOpenCloseAudioSessionAndGone");
+
+        int broadcasts = 1;
+        openSessionWithResList(mDoubleList, 1, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+        broadcasts = broadcasts + 1;
+        openSessionWithResList(mDoubleList, 1, broadcasts, mTestPkg1, mTestSession2, mTestUid1);
+        broadcasts = broadcasts + 1;
+        closeSessionWithResList(mDoubleList, 0, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+
+        broadcasts = broadcasts + 1; // 1 open session left
+        sendMessage(MusicFxHelper.MSG_EFFECT_CLIENT_GONE, mTestUid1, 1, broadcasts);
+    }
+
+    /**
+     * One MusicFx client, open session, then UID gone without close.
+     */
+    @Test
+    public void testOpenOneSessionAndGo() {
+        Log.i(TAG, "running testOpenOneSessionAndGo");
+
+        int broadcasts = 1;
+        openSessionWithResList(mDoubleList, 1, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+
+        broadcasts = broadcasts + 1;
+        sendMessage(MusicFxHelper.MSG_EFFECT_CLIENT_GONE, mTestUid1, 1, broadcasts);
+    }
+
+    /**
+     * Two MusicFx clients open and close sessions.
+     */
+    @Test
+    public void testOpenTwoSessionsAndClose() {
+        Log.i(TAG, "running testOpenTwoSessionsAndClose");
+
+        int broadcasts = 1, bind = 1, unbind = 0;
+        openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+        broadcasts = broadcasts + 1;
+        openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg2, mTestSession2, mTestUid2);
+
+        broadcasts = broadcasts + 1;
+        closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg2, mTestSession2,
+                mTestUid2);
+        broadcasts = broadcasts + 1;
+        unbind = unbind + 1;
+        closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg1, mTestSession1,
+                mTestUid1);
+
+        broadcasts = broadcasts + 1;
+        bind = bind + 1;
+        openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg2, mTestSession2, mTestUid2);
+        broadcasts = broadcasts + 1;
+        openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+
+        broadcasts = broadcasts + 1;
+        closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg1, mTestSession1,
+                mTestUid1);
+        broadcasts = broadcasts + 1;
+        unbind = unbind + 1;
+        closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg2, mTestSession2,
+                mTestUid2);
+    }
+
+    /**
+     * Two MusicFx clients open sessions, then both UID gone without close.
+     */
+    @Test
+    public void testOpenTwoSessionsAndGo() {
+        Log.i(TAG, "running testOpenTwoSessionsAndGo");
+
+        int broadcasts = 1, bind = 1, unbind = 0;
+        openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+        broadcasts = broadcasts + 1;
+        openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg2, mTestSession2, mTestUid2);
+
+        broadcasts = broadcasts + 1;
+        sendMessage(MusicFxHelper.MSG_EFFECT_CLIENT_GONE, mTestUid1, unbind, broadcasts);
+
+        broadcasts = broadcasts + 1;
+        unbind = unbind + 1;
+        sendMessage(MusicFxHelper.MSG_EFFECT_CLIENT_GONE, mTestUid2, unbind, broadcasts);
+    }
+
+    /**
+     * Two MusicFx clients open sessions, one close but not gone, the other one gone without close.
+     */
+    @Test
+    public void testTwoSessionsOpenOneCloseOneGo() {
+        Log.i(TAG, "running testTwoSessionsOpneAndOneCloseOneGo");
+
+        int broadcasts = 1, bind = 1, unbind = 0;
+        openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+        broadcasts = broadcasts + 1;
+        openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg2, mTestSession2, mTestUid2);
+
+        broadcasts = broadcasts + 1;
+        closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg1, mTestSession1,
+                                mTestUid1);
+
+        broadcasts = broadcasts + 1;
+        unbind = unbind + 1;
+        sendMessage(MusicFxHelper.MSG_EFFECT_CLIENT_GONE, mTestUid2, unbind, broadcasts);
+    }
+
+    /**
+     * One MusicFx client, open multiple audio sessions, and close all sessions.
+     */
+    @Test
+    public void testTwoSessionsInSameUidOpenClose() {
+        Log.i(TAG, "running testTwoSessionsOpneAndOneCloseOneGo");
+
+        int broadcasts = 1, bind = 1, unbind = 0;
+        openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+        broadcasts = broadcasts + 1;
+        openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg1, mTestSession2, mTestUid1);
+
+        broadcasts = broadcasts + 1;
+        closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg1, mTestSession1,
+                                mTestUid1);
+        broadcasts = broadcasts + 1;
+        unbind = unbind + 1;
+        closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg1, mTestSession2,
+                                mTestUid1);
+    }
+
+    /**
+     * Three MusicFx clients, each with multiple audio sessions, and close all sessions.
+     */
+    @Test
+    public void testThreeSessionsInThreeUidOpenClose() {
+        Log.i(TAG, "running testThreeSessionsInThreeUidOpenClose");
+
+        int broadcasts = 1, bind = 1, unbind = 0;
+        //client1
+        openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+        broadcasts = broadcasts + 1;
+        openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg1, mTestSession2, mTestUid1);
+        // client2
+        broadcasts = broadcasts + 1;
+        openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg2, mTestSession3, mTestUid2);
+        broadcasts = broadcasts + 1;
+        openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg2, mTestSession2, mTestUid2);
+        // client3
+        broadcasts = broadcasts + 1;
+        openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg3, mTestSession1, mTestUid3);
+        broadcasts = broadcasts + 1;
+        openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg3, mTestSession3, mTestUid3);
+
+        broadcasts = broadcasts + 1;
+        closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg1, mTestSession1,
+                                mTestUid1);
+        broadcasts = broadcasts + 1;
+        closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg3, mTestSession3,
+                                mTestUid3);
+        broadcasts = broadcasts + 1;
+        closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg2, mTestSession2,
+                                mTestUid2);
+        // all sessions of client1 closed
+        broadcasts = broadcasts + 1;
+        closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg1, mTestSession2,
+                                mTestUid1);
+        // all sessions of client3 closed
+        broadcasts = broadcasts + 1;
+        closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg3, mTestSession1,
+                                mTestUid3);
+        // all sessions of client2 closed
+        broadcasts = broadcasts + 1;
+        // now expect unbind to happen
+        unbind = unbind + 1;
+        closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg2, mTestSession3,
+                                mTestUid2);
+    }
+
+    /**
+     * Two MusicFx clients, with multiple audio sessions, one close all sessions, and other gone.
+     */
+    @Test
+    public void testTwoUidOneCloseOneGo() {
+        Log.i(TAG, "running testTwoUidOneCloseOneGo");
+
+        int broadcasts = 1, bind = 1, unbind = 0;
+        //client1
+        openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+        broadcasts = broadcasts + 1;
+        openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg1, mTestSession2, mTestUid1);
+        // client2
+        broadcasts = broadcasts + 1;
+        openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg2, mTestSession1, mTestUid2);
+        broadcasts = broadcasts + 1;
+        openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg2, mTestSession2, mTestUid2);
+
+        broadcasts = broadcasts + 1;
+        closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg1, mTestSession1,
+                                mTestUid1);
+        // client2 gone
+        broadcasts = broadcasts + 2;
+        sendMessage(MusicFxHelper.MSG_EFFECT_CLIENT_GONE, mTestUid2, unbind, broadcasts);
+        // client 1 close all sessions
+        broadcasts = broadcasts + 1;
+        unbind = unbind + 1;
+        closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg1, mTestSession2,
+                                mTestUid1);
+    }
+
+    /**
+     * Three MusicFx clients, with multiple audio sessions, all UID gone.
+     */
+    @Test
+    public void testThreeUidAllGo() {
+        Log.i(TAG, "running testThreeUidAllGo");
+
+        int broadcasts = 1, bind = 1, unbind = 0;
+        //client1
+        openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+        broadcasts = broadcasts + 1;
+        openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg1, mTestSession2, mTestUid1);
+        // client2
+        broadcasts = broadcasts + 1;
+        openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg2, mTestSession2, mTestUid2);
+        broadcasts = broadcasts + 1;
+        openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg2, mTestSession3, mTestUid2);
+        // client3
+        broadcasts = broadcasts + 1;
+        openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg3, mTestSession3, mTestUid3);
+        broadcasts = broadcasts + 1;
+        openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg3, mTestSession1, mTestUid3);
+
+        // client2 gone
+        broadcasts = broadcasts + 2;
+        sendMessage(MusicFxHelper.MSG_EFFECT_CLIENT_GONE, mTestUid2, unbind, broadcasts);
+        // client3 gone
+        broadcasts = broadcasts + 2;
+        sendMessage(MusicFxHelper.MSG_EFFECT_CLIENT_GONE, mTestUid3, unbind, broadcasts);
+        // client 1 gone
+        broadcasts = broadcasts + 2;
+        // now expect unbindService to happen
+        unbind = unbind + 1;
+        sendMessage(MusicFxHelper.MSG_EFFECT_CLIENT_GONE, mTestUid1, unbind, broadcasts);
+    }
+
+    /**
+     * Three MusicFx clients, multiple audio sessions, open and UID gone in difference sequence.
+     */
+    @Test
+    public void testThreeUidDiffSequence() {
+        Log.i(TAG, "running testThreeUidDiffSequence");
+
+        int broadcasts = 1, bind = 1, unbind = 0;
+        //client1
+        openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg1, mTestSession1, mTestUid1);
+        broadcasts = broadcasts + 1;
+        openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg1, mTestSession2, mTestUid1);
+        // client2
+        broadcasts = broadcasts + 1;
+        openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg2, mTestSession2, mTestUid2);
+        // client1 close one session
+        broadcasts = broadcasts + 1;
+        closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg1, mTestSession1,
+                                mTestUid1);
+        // client2 open another session
+        broadcasts = broadcasts + 1;
+        openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg2, mTestSession3, mTestUid2);
+        // client3 open one session
+        broadcasts = broadcasts + 1;
+        openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg3, mTestSession3, mTestUid3);
+        // client2 gone
+        broadcasts = broadcasts + 2;
+        sendMessage(MusicFxHelper.MSG_EFFECT_CLIENT_GONE, mTestUid2, unbind, broadcasts);
+        // client3 open another session
+        broadcasts = broadcasts + 1;
+        openSessionWithResList(mDoubleList, bind, broadcasts, mTestPkg3, mTestSession1, mTestUid3);
+        // client1 close another session, and gone
+        broadcasts = broadcasts + 1;
+        closeSessionWithResList(mDoubleList, unbind, broadcasts, mTestPkg1, mTestSession2,
+                                mTestUid1);
+        // last UID client3 gone, unbind
+        broadcasts = broadcasts + 2;
+        unbind = unbind + 1;
+        sendMessage(MusicFxHelper.MSG_EFFECT_CLIENT_GONE, mTestUid3, unbind, broadcasts);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java
index a78f2dc..3b5cae3 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java
@@ -23,6 +23,8 @@
 import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_CANCELED;
 import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_SUCCESS;
 
+import static com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR;
+
 import static junit.framework.Assert.assertEquals;
 
 import static org.junit.Assert.assertThrows;
@@ -41,6 +43,7 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
+import android.hardware.biometrics.AuthenticationStateListener;
 import android.hardware.biometrics.BiometricManager;
 import android.hardware.biometrics.Flags;
 import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
@@ -108,6 +111,7 @@
     @Mock
     IFaceService mFaceService;
     @Mock
+
     AppOpsManager mAppOpsManager;
     @Mock
     private VirtualDeviceManagerInternal mVdmInternal;
@@ -404,6 +408,23 @@
                 eq(TEST_OP_PACKAGE_NAME));
     }
 
+    @Test
+    public void testRegisterAuthenticationStateListener_callsFingerprintService()
+            throws Exception {
+        mSetFlagsRule.enableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR);
+        setInternalAndTestBiometricPermissions(mContext, true /* hasPermission */);
+
+        mAuthService = new AuthService(mContext, mInjector);
+        mAuthService.onStart();
+
+        final AuthenticationStateListener listener = mock(AuthenticationStateListener.class);
+
+        mAuthService.mImpl.registerAuthenticationStateListener(listener);
+
+        waitForIdle();
+        verify(mFingerprintService).registerAuthenticationStateListener(
+                eq(listener));
+    }
 
     @Test
     public void testRegisterKeyguardCallback_callsBiometricServiceRegisterKeyguardCallback()
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/SensorOverlaysTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/SensorOverlaysTest.java
index 5012335..94cb860 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/SensorOverlaysTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/SensorOverlaysTest.java
@@ -16,6 +16,8 @@
 
 package com.android.server.biometrics.sensors;
 
+import static com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
@@ -23,10 +25,11 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.hardware.biometrics.BiometricOverlayConstants;
+import android.hardware.biometrics.BiometricRequestConstants;
 import android.hardware.fingerprint.ISidefpsController;
 import android.hardware.fingerprint.IUdfpsOverlayController;
 import android.platform.test.annotations.Presubmit;
+import android.platform.test.annotations.RequiresFlagsDisabled;
 
 import androidx.test.filters.SmallTest;
 
@@ -40,6 +43,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
+@RequiresFlagsDisabled(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
 @Presubmit
 @SmallTest
 public class SensorOverlaysTest {
@@ -97,7 +101,7 @@
     private void testShow(IUdfpsOverlayController udfps, ISidefpsController sidefps)
             throws Exception {
         final SensorOverlays sensorOverlays = new SensorOverlays(udfps, sidefps);
-        final int reason = BiometricOverlayConstants.REASON_UNKNOWN;
+        final int reason = BiometricRequestConstants.REASON_UNKNOWN;
         sensorOverlays.show(SENSOR_ID, reason, mAcquisitionClient);
 
         if (udfps != null) {
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
index 79a528c..c24227f 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
@@ -18,6 +18,8 @@
 
 import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_CANCELED;
 
+import static com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -56,6 +58,7 @@
 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.testing.TestableContext;
 
 import androidx.test.filters.SmallTest;
@@ -68,6 +71,7 @@
 import com.android.server.biometrics.log.OperationContextExt;
 import com.android.server.biometrics.log.Probe;
 import com.android.server.biometrics.sensors.AuthSessionCoordinator;
+import com.android.server.biometrics.sensors.AuthenticationStateListeners;
 import com.android.server.biometrics.sensors.ClientMonitorCallback;
 import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
 import com.android.server.biometrics.sensors.LockoutTracker;
@@ -91,6 +95,8 @@
 @SmallTest
 public class FingerprintAuthenticationClientTest {
 
+    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
     private static final int SENSOR_ID = 4;
     private static final int USER_ID = 8;
     private static final long OP_ID = 7;
@@ -128,6 +134,8 @@
     @Mock
     private ISidefpsController mSideFpsController;
     @Mock
+    private AuthenticationStateListeners mAuthenticationStateListeners;
+    @Mock
     private FingerprintSensorPropertiesInternal mSensorProps;
     @Mock
     private ClientMonitorCallback mCallback;
@@ -384,6 +392,7 @@
 
     private void showHideOverlay(Consumer<FingerprintAuthenticationClient> block)
             throws RemoteException {
+        mSetFlagsRule.disableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR);
         final FingerprintAuthenticationClient client = createClient();
 
         client.start(mCallback);
@@ -398,6 +407,49 @@
     }
 
     @Test
+    public void showHideOverlay_cancel_sidefpsControllerRemovalRefactor() throws RemoteException {
+        showHideOverlay_sidefpsControllerRemovalRefactor(c -> c.cancel());
+    }
+
+    @Test
+    public void showHideOverlay_stop_sidefpsControllerRemovalRefactor() throws RemoteException {
+        showHideOverlay_sidefpsControllerRemovalRefactor(c -> c.stopHalOperation());
+    }
+
+    @Test
+    public void showHideOverlay_error_sidefpsControllerRemovalRefactor() throws RemoteException {
+        showHideOverlay_sidefpsControllerRemovalRefactor(c -> c.onError(0, 0));
+        verify(mCallback).onClientFinished(any(), eq(false));
+    }
+
+    @Test
+    public void showHideOverlay_lockout_sidefpsControllerRemovalRefactor() throws RemoteException {
+        showHideOverlay_sidefpsControllerRemovalRefactor(c -> c.onLockoutTimed(5000));
+    }
+
+    @Test
+    public void showHideOverlay_lockoutPerm_sidefpsControllerRemovalRefactor()
+            throws RemoteException {
+        showHideOverlay_sidefpsControllerRemovalRefactor(c -> c.onLockoutPermanent());
+    }
+
+    private void showHideOverlay_sidefpsControllerRemovalRefactor(
+            Consumer<FingerprintAuthenticationClient> block) throws RemoteException {
+        mSetFlagsRule.enableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR);
+        final FingerprintAuthenticationClient client = createClient();
+
+        client.start(mCallback);
+
+        verify(mUdfpsOverlayController).showUdfpsOverlay(eq(REQUEST_ID), anyInt(), anyInt(), any());
+        verify(mAuthenticationStateListeners).onAuthenticationStarted(anyInt());
+
+        block.accept(client);
+
+        verify(mUdfpsOverlayController).hideUdfpsOverlay(anyInt());
+        verify(mAuthenticationStateListeners).onAuthenticationStopped();
+    }
+
+    @Test
     public void cancelsAuthWhenNotInForeground() throws Exception {
         final ActivityManager.RunningTaskInfo topTask = new ActivityManager.RunningTaskInfo();
         topTask.topActivity = new ComponentName("other", "thing");
@@ -502,7 +554,8 @@
                 mBiometricLogger, mBiometricContext,
                 true /* isStrongBiometric */,
                 null /* taskStackListener */,
-                mUdfpsOverlayController, mSideFpsController, allowBackgroundAuthentication,
+                mUdfpsOverlayController, mSideFpsController, mAuthenticationStateListeners,
+                allowBackgroundAuthentication,
                 mSensorProps,
                 new Handler(mLooper.getLooper()), 0 /* biometricStrength */, mClock,
                 lockoutTracker) {
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java
index c7eb1db..e7d4a2e 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java
@@ -16,6 +16,8 @@
 
 package com.android.server.biometrics.sensors.fingerprint.aidl;
 
+import static com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR;
+
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyFloat;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -38,6 +40,7 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
+import android.platform.test.flag.junit.SetFlagsRule;
 import android.testing.TestableContext;
 
 import androidx.test.filters.SmallTest;
@@ -48,6 +51,7 @@
 import com.android.server.biometrics.log.CallbackWithProbe;
 import com.android.server.biometrics.log.OperationContextExt;
 import com.android.server.biometrics.log.Probe;
+import com.android.server.biometrics.sensors.AuthenticationStateListeners;
 import com.android.server.biometrics.sensors.BiometricUtils;
 import com.android.server.biometrics.sensors.ClientMonitorCallback;
 import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
@@ -68,6 +72,8 @@
 @SmallTest
 public class FingerprintEnrollClientTest {
 
+    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
     private static final byte[] HAT = new byte[69];
     private static final int USER_ID = 8;
     private static final long REQUEST_ID = 9;
@@ -98,6 +104,8 @@
     @Mock
     private ISidefpsController mSideFpsController;
     @Mock
+    private AuthenticationStateListeners mAuthenticationStateListeners;
+    @Mock
     private FingerprintSensorPropertiesInternal mSensorProps;
     @Mock
     private ClientMonitorCallback mCallback;
@@ -271,6 +279,7 @@
 
     private void showHideOverlay(Consumer<FingerprintEnrollClient> block)
             throws RemoteException {
+        mSetFlagsRule.disableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR);
         final FingerprintEnrollClient client = createClient();
 
         client.start(mCallback);
@@ -284,6 +293,44 @@
         verify(mSideFpsController).hide(anyInt());
     }
 
+    @Test
+    public void showHideOverlay_cancel_sidefpsControllerRemovalRefactor() throws RemoteException {
+        showHideOverlay_sidefpsControllerRemovalRefactor(c -> c.cancel());
+    }
+
+    @Test
+    public void showHideOverlay_stop_sidefpsControllerRemovalRefactor() throws RemoteException {
+        showHideOverlay_sidefpsControllerRemovalRefactor(c -> c.stopHalOperation());
+    }
+
+    @Test
+    public void showHideOverlay_error_sidefpsControllerRemovalRefactor() throws RemoteException {
+        showHideOverlay_sidefpsControllerRemovalRefactor(c -> c.onError(0, 0));
+        verify(mCallback).onClientFinished(any(), eq(false));
+    }
+
+    @Test
+    public void showHideOverlay_result_sidefpsControllerRemovalRefactor() throws RemoteException {
+        showHideOverlay_sidefpsControllerRemovalRefactor(
+                c -> c.onEnrollResult(new Fingerprint("", 1, 1), 0));
+    }
+
+    private void showHideOverlay_sidefpsControllerRemovalRefactor(
+            Consumer<FingerprintEnrollClient> block) throws RemoteException {
+        mSetFlagsRule.enableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR);
+        final FingerprintEnrollClient client = createClient();
+
+        client.start(mCallback);
+
+        verify(mUdfpsOverlayController).showUdfpsOverlay(eq(REQUEST_ID), anyInt(), anyInt(), any());
+        verify(mAuthenticationStateListeners).onAuthenticationStarted(anyInt());
+
+        block.accept(client);
+
+        verify(mUdfpsOverlayController).hideUdfpsOverlay(anyInt());
+        verify(mAuthenticationStateListeners).onAuthenticationStopped();
+    }
+
     private FingerprintEnrollClient createClient() throws RemoteException {
         return createClient(500);
     }
@@ -296,6 +343,7 @@
         mClientMonitorCallbackConverter, 0 /* userId */,
         HAT, "owner", mBiometricUtils, 8 /* sensorId */,
         mBiometricLogger, mBiometricContext, mSensorProps, mUdfpsOverlayController,
-        mSideFpsController, 6 /* maxTemplatesPerUser */, FingerprintManager.ENROLL_ENROLL);
+        mSideFpsController, mAuthenticationStateListeners, 6 /* maxTemplatesPerUser */,
+        FingerprintManager.ENROLL_ENROLL);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java
index 8f6efff..4cfb83f 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java
@@ -43,6 +43,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.sensors.AuthenticationStateListeners;
 import com.android.server.biometrics.sensors.BaseClientMonitor;
 import com.android.server.biometrics.sensors.BiometricScheduler;
 import com.android.server.biometrics.sensors.BiometricStateCallback;
@@ -74,6 +75,8 @@
     @Mock
     private GestureAvailabilityDispatcher mGestureAvailabilityDispatcher;
     @Mock
+    private AuthenticationStateListeners mAuthenticationStateListeners;
+    @Mock
     private BiometricStateCallback mBiometricStateCallback;
     @Mock
     private BiometricContext mBiometricContext;
@@ -110,8 +113,9 @@
         mLockoutResetDispatcher = new LockoutResetDispatcher(mContext);
 
         mFingerprintProvider = new FingerprintProvider(mContext,
-                mBiometricStateCallback, mSensorProps, TAG, mLockoutResetDispatcher,
-                mGestureAvailabilityDispatcher, mBiometricContext, mDaemon);
+                mBiometricStateCallback, mAuthenticationStateListeners, mSensorProps, TAG,
+                mLockoutResetDispatcher, mGestureAvailabilityDispatcher, mBiometricContext,
+                mDaemon);
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java
index b32b89a..0d3f192 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java
@@ -40,6 +40,7 @@
 
 import com.android.internal.R;
 import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.sensors.AuthenticationStateListeners;
 import com.android.server.biometrics.sensors.BiometricScheduler;
 import com.android.server.biometrics.sensors.BiometricStateCallback;
 import com.android.server.biometrics.sensors.LockoutResetDispatcher;
@@ -70,6 +71,8 @@
     @Mock
     private BiometricScheduler mScheduler;
     @Mock
+    private AuthenticationStateListeners mAuthenticationStateListeners;
+    @Mock
     private BiometricStateCallback mBiometricStateCallback;
     @Mock
     private BiometricContext mBiometricContext;
@@ -102,9 +105,10 @@
                         componentInfo, FingerprintSensorProperties.TYPE_UNKNOWN,
                         resetLockoutRequiresHardwareAuthToken);
 
-        mFingerprint21 = new TestableFingerprint21(mContext, mBiometricStateCallback, sensorProps,
-                mScheduler, new Handler(Looper.getMainLooper()), mLockoutResetDispatcher,
-                mHalResultController, mBiometricContext);
+        mFingerprint21 = new TestableFingerprint21(mContext, mBiometricStateCallback,
+                mAuthenticationStateListeners, sensorProps, mScheduler,
+                new Handler(Looper.getMainLooper()), mLockoutResetDispatcher, mHalResultController,
+                mBiometricContext);
     }
 
     @Test
@@ -126,13 +130,14 @@
 
         TestableFingerprint21(@NonNull Context context,
                 @NonNull BiometricStateCallback biometricStateCallback,
+                @NonNull AuthenticationStateListeners authenticationStateListeners,
                 @NonNull FingerprintSensorPropertiesInternal sensorProps,
                 @NonNull BiometricScheduler scheduler, @NonNull Handler handler,
                 @NonNull LockoutResetDispatcher lockoutResetDispatcher,
                 @NonNull HalResultController controller,
                 @NonNull BiometricContext biometricContext) {
-            super(context, biometricStateCallback, sensorProps, scheduler, handler,
-                    lockoutResetDispatcher, controller, biometricContext);
+            super(context, biometricStateCallback, authenticationStateListeners, sensorProps,
+                    scheduler, handler, lockoutResetDispatcher, controller, biometricContext);
         }
 
         @Override
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/GenericWindowPolicyControllerTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/GenericWindowPolicyControllerTest.java
index 3355910..18e6f0a 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/GenericWindowPolicyControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/GenericWindowPolicyControllerTest.java
@@ -151,6 +151,19 @@
     }
 
     @Test
+    public void userNotAllowlisted_launchIsBlocked() {
+        GenericWindowPolicyController gwpc = createGwpcWithNoAllowedUsers();
+        gwpc.setDisplayId(DISPLAY_ID, /* isMirrorDisplay= */ false);
+
+        ActivityInfo activityInfo = getActivityInfo(
+                NONBLOCKED_APP_PACKAGE_NAME,
+                NONBLOCKED_APP_PACKAGE_NAME,
+                /* displayOnRemoteDevices */ true,
+                /* targetDisplayCategory */ null);
+        assertActivityIsBlocked(gwpc, activityInfo);
+    }
+
+    @Test
     public void openNonBlockedAppOnVirtualDisplay_isNotBlocked() {
         GenericWindowPolicyController gwpc = createGwpc();
         gwpc.setDisplayId(DISPLAY_ID, /* isMirrorDisplay= */ false);
@@ -702,6 +715,26 @@
                 /* customHomeComponent= */ null);
     }
 
+    private GenericWindowPolicyController createGwpcWithNoAllowedUsers() {
+        return new GenericWindowPolicyController(
+                0,
+                0,
+                /* allowedUsers= */ new ArraySet<>(),
+                /* activityLaunchAllowedByDefault= */ true,
+                /* activityPolicyExemptions= */ new ArraySet<>(),
+                /* crossTaskNavigationAllowedByDefault= */ true,
+                /* crossTaskNavigationExemptions= */ new ArraySet<>(),
+                /* permissionDialogComponent= */ null,
+                /* activityListener= */ mActivityListener,
+                /* pipBlockedCallback= */ mPipBlockedCallback,
+                /* activityBlockedCallback= */ mActivityBlockedCallback,
+                /* secureWindowCallback= */ mSecureWindowCallback,
+                /* intentListenerCallback= */ mIntentListenerCallback,
+                /* displayCategories= */ new ArraySet<>(),
+                /* showTasksInHostDeviceRecents= */ true,
+                /* customHomeComponent= */ null);
+    }
+
     private GenericWindowPolicyController createGwpcWithCustomHomeComponent(
             ComponentName homeComponent) {
         return new GenericWindowPolicyController(
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
index 9213601a..995d1f4 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
@@ -444,18 +444,27 @@
     }
 
     @Test
+    public void isDeviceIdValid_invalidDeviceId_returnsFalse() {
+        assertThat(mVdm.isValidVirtualDeviceId(DEVICE_ID_INVALID)).isFalse();
+        assertThat(mLocalService.isValidVirtualDeviceId(DEVICE_ID_INVALID)).isFalse();
+    }
+
+    @Test
     public void isDeviceIdValid_defaultDeviceId_returnsFalse() {
         assertThat(mVdm.isValidVirtualDeviceId(DEVICE_ID_DEFAULT)).isFalse();
+        assertThat(mLocalService.isValidVirtualDeviceId(DEVICE_ID_DEFAULT)).isFalse();
     }
 
     @Test
     public void isDeviceIdValid_validVirtualDeviceId_returnsTrue() {
         assertThat(mVdm.isValidVirtualDeviceId(mDeviceImpl.getDeviceId())).isTrue();
+        assertThat(mLocalService.isValidVirtualDeviceId(mDeviceImpl.getDeviceId())).isTrue();
     }
 
     @Test
     public void isDeviceIdValid_nonExistentDeviceId_returnsFalse() {
         assertThat(mVdm.isValidVirtualDeviceId(mDeviceImpl.getDeviceId() + 1)).isFalse();
+        assertThat(mLocalService.isValidVirtualDeviceId(mDeviceImpl.getDeviceId() + 1)).isFalse();
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/devicestate/OverrideRequestControllerTest.java b/services/tests/servicestests/src/com/android/server/devicestate/OverrideRequestControllerTest.java
index fe37f42..b3d25f2 100644
--- a/services/tests/servicestests/src/com/android/server/devicestate/OverrideRequestControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicestate/OverrideRequestControllerTest.java
@@ -47,6 +47,10 @@
 @Presubmit
 @RunWith(AndroidJUnit4.class)
 public final class OverrideRequestControllerTest {
+
+    private static final DeviceState TEST_DEVICE_STATE_ZERO = new DeviceState(0, "TEST_STATE", 0);
+    private static final DeviceState TEST_DEVICE_STATE_ONE = new DeviceState(1, "TEST_STATE", 0);
+
     private TestStatusChangeListener mStatusListener;
     private OverrideRequestController mController;
 
@@ -59,7 +63,7 @@
     @Test
     public void addRequest() {
         OverrideRequest request = new OverrideRequest(new Binder(), 0 /* pid */, 0 /* uid */,
-                0 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
+                TEST_DEVICE_STATE_ZERO, 0 /* flags */, OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
         assertNull(mStatusListener.getLastStatus(request));
 
         mController.addRequest(request);
@@ -69,14 +73,14 @@
     @Test
     public void addRequest_cancelExistingRequestThroughNewRequest() {
         OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */, 0 /* uid */,
-                0 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
+                TEST_DEVICE_STATE_ZERO, 0 /* flags */, OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
         assertNull(mStatusListener.getLastStatus(firstRequest));
 
         mController.addRequest(firstRequest);
         assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
 
         OverrideRequest secondRequest = new OverrideRequest(new Binder(), 0 /* pid */, 0 /* uid */,
-                1 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
+                TEST_DEVICE_STATE_ONE, 0 /* flags */, OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
         assertNull(mStatusListener.getLastStatus(secondRequest));
 
         mController.addRequest(secondRequest);
@@ -87,7 +91,7 @@
     @Test
     public void addRequest_cancelActiveRequest() {
         OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */, 0 /* uid */,
-                0 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
+                TEST_DEVICE_STATE_ZERO, 0 /* flags */, OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
 
         mController.addRequest(firstRequest);
 
@@ -101,7 +105,7 @@
     @Test
     public void addBaseStateRequest() {
         OverrideRequest request = new OverrideRequest(new Binder(), 0 /* pid */, 0 /* uid */,
-                0 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_BASE_STATE);
+                TEST_DEVICE_STATE_ZERO, 0 /* flags */, OVERRIDE_REQUEST_TYPE_BASE_STATE);
         assertNull(mStatusListener.getLastStatus(request));
 
         mController.addBaseStateRequest(request);
@@ -111,14 +115,14 @@
     @Test
     public void addBaseStateRequest_cancelExistingBaseStateRequestThroughNewRequest() {
         OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */, 0 /* uid */,
-                0 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_BASE_STATE);
+                TEST_DEVICE_STATE_ZERO, 0 /* flags */, OVERRIDE_REQUEST_TYPE_BASE_STATE);
         assertNull(mStatusListener.getLastStatus(firstRequest));
 
         mController.addBaseStateRequest(firstRequest);
         assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
 
         OverrideRequest secondRequest = new OverrideRequest(new Binder(), 0 /* pid */, 0 /* uid */,
-                1 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_BASE_STATE);
+                TEST_DEVICE_STATE_ONE, 0 /* flags */, OVERRIDE_REQUEST_TYPE_BASE_STATE);
         assertNull(mStatusListener.getLastStatus(secondRequest));
 
         mController.addBaseStateRequest(secondRequest);
@@ -129,7 +133,7 @@
     @Test
     public void addBaseStateRequest_cancelActiveBaseStateRequest() {
         OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */, 0 /* uid */,
-                0 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_BASE_STATE);
+                TEST_DEVICE_STATE_ZERO, 0 /* flags */, OVERRIDE_REQUEST_TYPE_BASE_STATE);
 
         mController.addBaseStateRequest(firstRequest);
 
@@ -143,13 +147,13 @@
     @Test
     public void handleBaseStateChanged() {
         OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */, 0 /* uid */,
-                0 /* requestedState */,
+                TEST_DEVICE_STATE_ZERO,
                 DeviceStateRequest.FLAG_CANCEL_WHEN_BASE_CHANGES /* flags */,
                 OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
 
         OverrideRequest baseStateRequest = new OverrideRequest(new Binder(), 0 /* pid */,
                 0 /* uid */,
-                0 /* requestedState */,
+                TEST_DEVICE_STATE_ZERO,
                 0 /* flags */, OVERRIDE_REQUEST_TYPE_BASE_STATE);
 
         mController.addRequest(firstRequest);
@@ -169,11 +173,11 @@
     @Test
     public void handleProcessDied() {
         OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */, 0 /* uid */,
-                0 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
+                TEST_DEVICE_STATE_ZERO, 0 /* flags */, OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
 
         OverrideRequest baseStateRequest = new OverrideRequest(new Binder(), 0 /* pid */,
                 0 /* uid */,
-                1 /* requestedState */,
+                TEST_DEVICE_STATE_ONE,
                 0 /* flags */, OVERRIDE_REQUEST_TYPE_BASE_STATE);
 
         mController.addRequest(firstRequest);
@@ -192,11 +196,11 @@
         mController.setStickyRequestsAllowed(true);
 
         OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */, 0 /* uid */,
-                0 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
+                TEST_DEVICE_STATE_ZERO, 0 /* flags */, OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
 
         OverrideRequest baseStateRequest = new OverrideRequest(new Binder(), 0 /* pid */,
                 0 /* uid */,
-                1 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_BASE_STATE);
+                TEST_DEVICE_STATE_ONE, 0 /* flags */, OVERRIDE_REQUEST_TYPE_BASE_STATE);
 
         mController.addRequest(firstRequest);
         assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
@@ -215,11 +219,11 @@
     @Test
     public void handleNewSupportedStates() {
         OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */, 0 /* uid */,
-                1 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
+                TEST_DEVICE_STATE_ONE, 0 /* flags */, OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
 
         OverrideRequest baseStateRequest = new OverrideRequest(new Binder(), 0 /* pid */,
                 0 /* uid */,
-                1 /* requestedState */,
+                TEST_DEVICE_STATE_ONE,
                 0 /* flags */, OVERRIDE_REQUEST_TYPE_BASE_STATE);
 
         mController.addRequest(firstRequest);
@@ -242,7 +246,7 @@
     @Test
     public void cancelOverrideRequestsTest() {
         OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */, 0 /* uid */,
-                1 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
+                TEST_DEVICE_STATE_ONE, 0 /* flags */, OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
 
         mController.addRequest(firstRequest);
         assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
index 5acbe65..0973d46 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
@@ -23,6 +23,7 @@
 import static com.android.server.hdmi.Constants.ADDR_PLAYBACK_2;
 import static com.android.server.hdmi.Constants.ADDR_RECORDER_1;
 import static com.android.server.hdmi.Constants.ADDR_TV;
+import static com.android.server.hdmi.HdmiCecLocalDevice.ActiveSource;
 import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -1712,28 +1713,89 @@
                 HdmiCecMessageBuilder.buildRequestActiveSource(ADDR_TV);
         HdmiCecMessage activeSourceFromTv =
                 HdmiCecMessageBuilder.buildActiveSource(ADDR_TV, 0x0000);
-
         mHdmiControlService.getHdmiCecNetwork().clearLocalDevices();
         mNativeWrapper.setPollAddressResponse(ADDR_PLAYBACK_1, SendMessageResult.SUCCESS);
         mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
         mTestLooper.dispatchAll();
 
         assertThat(mNativeWrapper.getResultMessages()).contains(requestActiveSource);
+        assertThat(mHdmiControlService.getLocalActiveSource()).isEqualTo(
+                new ActiveSource(Constants.ADDR_INVALID, Constants.INVALID_PHYSICAL_ADDRESS));
         mNativeWrapper.clearResultMessages();
         mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
         mTestLooper.dispatchAll();
+        assertThat(mNativeWrapper.getResultMessages()).doesNotContain(activeSourceFromTv);
 
+        // Skip the retry.
+        mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
+        mTestLooper.dispatchAll();
         assertThat(mNativeWrapper.getResultMessages()).contains(activeSourceFromTv);
+        assertThat(mHdmiControlService.getLocalActiveSource()).isEqualTo(
+                new ActiveSource(mTvLogicalAddress, mTvPhysicalAddress));
     }
 
     @Test
+    public void requestActiveSourceActionComplete_validLocalActiveSource_doNotSendActiveSource() {
+        HdmiCecMessage requestActiveSource =
+                HdmiCecMessageBuilder.buildRequestActiveSource(ADDR_TV);
+        HdmiCecMessage activeSourceFromTv =
+                HdmiCecMessageBuilder.buildActiveSource(ADDR_TV, 0x0000);
+        mHdmiControlService.getHdmiCecNetwork().clearLocalDevices();
+        mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
+        mTestLooper.dispatchAll();
+
+        assertThat(mNativeWrapper.getResultMessages()).contains(requestActiveSource);
+        mHdmiControlService.setActiveSource(mTvLogicalAddress, mTvPhysicalAddress,
+                "HdmiCecLocalDeviceTvTest");
+        mNativeWrapper.clearResultMessages();
+        mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS * 2);
+        mTestLooper.dispatchAll();
+
+        assertThat(mNativeWrapper.getResultMessages()).doesNotContain(activeSourceFromTv);
+    }
+
+    @Test
+    public void onAddressAllocated_startRequestActiveSourceAction_cancelOnDeviceSelect() {
+        HdmiCecMessage requestActiveSource =
+                HdmiCecMessageBuilder.buildRequestActiveSource(ADDR_TV);
+        HdmiCecMessage activeSourceFromTv =
+                HdmiCecMessageBuilder.buildActiveSource(ADDR_TV, 0x0000);
+        mHdmiControlService.getHdmiCecNetwork().clearLocalDevices();
+        mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
+        HdmiDeviceInfo playbackDevice = HdmiDeviceInfo.cecDeviceBuilder()
+                .setLogicalAddress(ADDR_PLAYBACK_1)
+                .setPhysicalAddress(0x1000)
+                .setPortId(PORT_1)
+                .setDeviceType(HdmiDeviceInfo.DEVICE_PLAYBACK)
+                .setVendorId(0x1234)
+                .setDisplayName("Playback 1")
+                .setDevicePowerStatus(HdmiControlManager.POWER_STATUS_ON)
+                .setCecVersion(HdmiControlManager.HDMI_CEC_VERSION_1_4_B)
+                .build();
+        mHdmiControlService.getHdmiCecNetwork().addCecDevice(playbackDevice);
+        mTestLooper.dispatchAll();
+
+        assertThat(mNativeWrapper.getResultMessages()).contains(requestActiveSource);
+        mNativeWrapper.clearResultMessages();
+        mHdmiCecLocalDeviceTv.deviceSelect(playbackDevice.getId(), null);
+        mTestLooper.dispatchAll();
+
+        mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS * 2);
+        mTestLooper.dispatchAll();
+
+        // RequestActiveSourceAction should be cancelled and TV will not broadcast <Active Source>.
+        assertThat(mNativeWrapper.getResultMessages()).doesNotContain(activeSourceFromTv);
+    }
+
+
+    @Test
     public void newDeviceConnectedIfOnlyOneGiveOsdNameSent() {
         mHdmiControlService.getHdmiCecNetwork().clearDeviceList();
         assertThat(mHdmiControlService.getHdmiCecNetwork().getDeviceInfoList(false))
                 .isEmpty();
         HdmiCecMessage reportPhysicalAddress =
                 HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
-                ADDR_PLAYBACK_2, 0x1000, HdmiDeviceInfo.DEVICE_PLAYBACK);
+                        ADDR_PLAYBACK_2, 0x1000, HdmiDeviceInfo.DEVICE_PLAYBACK);
         HdmiCecMessage giveOsdName = HdmiCecMessageBuilder.buildGiveOsdNameCommand(
                 ADDR_TV, ADDR_PLAYBACK_2);
         mNativeWrapper.onCecMessage(reportPhysicalAddress);
diff --git a/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodUtilsTest.java b/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodUtilsTest.java
index 37a1a41..0d25faf 100644
--- a/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodUtilsTest.java
@@ -60,6 +60,8 @@
 
 import com.android.internal.inputmethod.StartInputFlags;
 
+import com.google.common.truth.Truth;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -1234,7 +1236,7 @@
         // Init InputMethodSettings for the owner user (userId=0), verify calls can get the
         // corresponding user's context, contentResolver and the resources configuration.
         InputMethodUtils.InputMethodSettings settings = new InputMethodUtils.InputMethodSettings(
-                ownerUserContext, methodMap, 0 /* userId */, true);
+                methodMap, 0 /* userId */, true);
         assertEquals(0, settings.getCurrentUserId());
 
         settings.isShowImeWithHardKeyboardEnabled();
@@ -1336,6 +1338,54 @@
         }
     }
 
+    private static void verifySplitEnabledImeStr(@NonNull String enabledImeStr,
+            @NonNull String... expected) {
+        final ArrayList<String> actual = new ArrayList<>();
+        InputMethodUtils.splitEnabledImeStr(enabledImeStr, actual::add);
+        if (expected.length == 0) {
+            Truth.assertThat(actual).isEmpty();
+        } else {
+            Truth.assertThat(actual).containsExactlyElementsIn(expected);
+        }
+    }
+
+    @Test
+    public void testSplitEnabledImeStr() {
+        verifySplitEnabledImeStr("");
+        verifySplitEnabledImeStr("com.android/.ime1", "com.android/.ime1");
+        verifySplitEnabledImeStr("com.android/.ime1;1;2;3", "com.android/.ime1");
+        verifySplitEnabledImeStr("com.android/.ime1;1;2;3:com.android/.ime2",
+                "com.android/.ime1", "com.android/.ime2");
+        verifySplitEnabledImeStr("com.android/.ime1:com.android/.ime2",
+                "com.android/.ime1", "com.android/.ime2");
+        verifySplitEnabledImeStr("com.android/.ime1:com.android/.ime2:com.android/.ime3",
+                "com.android/.ime1", "com.android/.ime2", "com.android/.ime3");
+        verifySplitEnabledImeStr("com.android/.ime1;1:com.android/.ime2;1:com.android/.ime3;1",
+                "com.android/.ime1", "com.android/.ime2", "com.android/.ime3");
+    }
+
+    @Test
+    public void testConcatEnabledImeIds() {
+        Truth.assertThat(InputMethodUtils.concatEnabledImeIds("")).isEmpty();
+        Truth.assertThat(InputMethodUtils.concatEnabledImeIds("", "com.android/.ime1"))
+                .isEqualTo("com.android/.ime1");
+        Truth.assertThat(InputMethodUtils.concatEnabledImeIds(
+                        "com.android/.ime1", "com.android/.ime1"))
+                .isEqualTo("com.android/.ime1");
+        Truth.assertThat(InputMethodUtils.concatEnabledImeIds(
+                        "com.android/.ime1", "com.android/.ime2"))
+                .isEqualTo("com.android/.ime1:com.android/.ime2");
+        Truth.assertThat(InputMethodUtils.concatEnabledImeIds(
+                        "com.android/.ime1", "com.android/.ime2", "com.android/.ime3"))
+                .isEqualTo("com.android/.ime1:com.android/.ime2:com.android/.ime3");
+        Truth.assertThat(InputMethodUtils.concatEnabledImeIds(
+                        "com.android/.ime1:com.android/.ime2", "com.android/.ime1"))
+                .isEqualTo("com.android/.ime1:com.android/.ime2");
+        Truth.assertThat(InputMethodUtils.concatEnabledImeIds(
+                        "com.android/.ime1:com.android/.ime2", "com.android/.ime3"))
+                .isEqualTo("com.android/.ime1:com.android/.ime2:com.android/.ime3");
+    }
+
     @Test
     public void updateEnabledImeStringTest() {
         // No change cases
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
index 18961c0..ee076c6 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
@@ -140,9 +140,9 @@
         }
 
         @Override
-        public ManagedProfilePasswordCache getManagedProfilePasswordCache(
+        public UnifiedProfilePasswordCache getUnifiedProfilePasswordCache(
                 java.security.KeyStore ks) {
-            return mock(ManagedProfilePasswordCache.class);
+            return mock(UnifiedProfilePasswordCache.class);
         }
 
         @Override
diff --git a/services/tests/servicestests/src/com/android/server/pm/SELinuxMMACTest.java b/services/tests/servicestests/src/com/android/server/pm/SELinuxMMACTest.java
index dd687fd..86a1358 100644
--- a/services/tests/servicestests/src/com/android/server/pm/SELinuxMMACTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/SELinuxMMACTest.java
@@ -27,9 +27,9 @@
 import android.os.Build;
 import android.platform.test.annotations.Presubmit;
 
+import com.android.internal.pm.parsing.pkg.PackageImpl;
 import com.android.internal.pm.parsing.pkg.ParsedPackage;
 import com.android.server.compat.PlatformCompat;
-import com.android.server.pm.parsing.pkg.PackageImpl;
 import com.android.server.pm.pkg.PackageState;
 
 import org.junit.Test;
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserPropertiesTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserPropertiesTest.java
index d70a4fd..d7ed7c2 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserPropertiesTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserPropertiesTest.java
@@ -69,8 +69,10 @@
                 .setMediaSharedWithParent(false)
                 .setCredentialShareableWithParent(true)
                 .setAuthAlwaysRequiredToDisableQuietMode(false)
+                .setAllowStoppingUserWithDelayedLocking(false)
                 .setDeleteAppWithParent(false)
                 .setAlwaysVisible(false)
+                .setCrossProfileContentSharingStrategy(0)
                 .build();
         final UserProperties actualProps = new UserProperties(defaultProps);
         actualProps.setShowInLauncher(14);
@@ -84,8 +86,10 @@
         actualProps.setMediaSharedWithParent(true);
         actualProps.setCredentialShareableWithParent(false);
         actualProps.setAuthAlwaysRequiredToDisableQuietMode(true);
+        actualProps.setAllowStoppingUserWithDelayedLocking(true);
         actualProps.setDeleteAppWithParent(true);
         actualProps.setAlwaysVisible(true);
+        actualProps.setCrossProfileContentSharingStrategy(1);
 
         // Write the properties to xml.
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -128,6 +132,7 @@
                 .setMediaSharedWithParent(true)
                 .setDeleteAppWithParent(true)
                 .setAuthAlwaysRequiredToDisableQuietMode(false)
+                .setAllowStoppingUserWithDelayedLocking(false)
                 .setAlwaysVisible(true)
                 .build();
         final UserProperties orig = new UserProperties(defaultProps);
@@ -137,6 +142,7 @@
         orig.setInheritDevicePolicy(9456);
         orig.setDeleteAppWithParent(false);
         orig.setAuthAlwaysRequiredToDisableQuietMode(true);
+        orig.setAllowStoppingUserWithDelayedLocking(true);
         orig.setAlwaysVisible(false);
 
         // Test every permission level. (Currently, it's linear so it's easy.)
@@ -182,6 +188,8 @@
         assertEqualGetterOrThrows(orig::getDeleteAppWithParent,
                 copy::getDeleteAppWithParent, exposeAll);
         assertEqualGetterOrThrows(orig::getAlwaysVisible, copy::getAlwaysVisible, exposeAll);
+        assertEqualGetterOrThrows(orig::getAllowStoppingUserWithDelayedLocking,
+                copy::getAllowStoppingUserWithDelayedLocking, exposeAll);
 
         // Items requiring hasManagePermission - put them here using hasManagePermission.
         assertEqualGetterOrThrows(orig::getShowInSettings, copy::getShowInSettings,
@@ -199,6 +207,8 @@
                 copy::isMediaSharedWithParent, true);
         assertEqualGetterOrThrows(orig::isCredentialShareableWithParent,
                 copy::isCredentialShareableWithParent, true);
+        assertEqualGetterOrThrows(orig::getCrossProfileContentSharingStrategy,
+                copy::getCrossProfileContentSharingStrategy, true);
     }
 
     /**
@@ -254,7 +264,11 @@
                 .isEqualTo(actual.isCredentialShareableWithParent());
         assertThat(expected.isAuthAlwaysRequiredToDisableQuietMode())
                 .isEqualTo(actual.isAuthAlwaysRequiredToDisableQuietMode());
+        assertThat(expected.getAllowStoppingUserWithDelayedLocking())
+                .isEqualTo(actual.getAllowStoppingUserWithDelayedLocking());
         assertThat(expected.getDeleteAppWithParent()).isEqualTo(actual.getDeleteAppWithParent());
         assertThat(expected.getAlwaysVisible()).isEqualTo(actual.getAlwaysVisible());
+        assertThat(expected.getCrossProfileContentSharingStrategy())
+                .isEqualTo(actual.getCrossProfileContentSharingStrategy());
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java
index 77f6939..7083706 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java
@@ -29,7 +29,6 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertTrue;
@@ -91,12 +90,14 @@
                 .setMediaSharedWithParent(true)
                 .setCredentialShareableWithParent(false)
                 .setAuthAlwaysRequiredToDisableQuietMode(true)
+                .setAllowStoppingUserWithDelayedLocking(true)
                 .setShowInSettings(900)
                 .setShowInSharingSurfaces(20)
                 .setShowInQuietMode(30)
                 .setInheritDevicePolicy(340)
                 .setDeleteAppWithParent(true)
-                .setAlwaysVisible(true);
+                .setAlwaysVisible(true)
+                .setCrossProfileContentSharingStrategy(1);
 
         final UserTypeDetails type = new UserTypeDetails.Builder()
                 .setName("a.name")
@@ -167,6 +168,8 @@
         assertFalse(type.getDefaultUserPropertiesReference().isCredentialShareableWithParent());
         assertTrue(type.getDefaultUserPropertiesReference()
                 .isAuthAlwaysRequiredToDisableQuietMode());
+        assertTrue(type.getDefaultUserPropertiesReference()
+                .getAllowStoppingUserWithDelayedLocking());
         assertEquals(900, type.getDefaultUserPropertiesReference().getShowInSettings());
         assertEquals(20, type.getDefaultUserPropertiesReference().getShowInSharingSurfaces());
         assertEquals(30,
@@ -175,6 +178,8 @@
                 .getInheritDevicePolicy());
         assertTrue(type.getDefaultUserPropertiesReference().getDeleteAppWithParent());
         assertTrue(type.getDefaultUserPropertiesReference().getAlwaysVisible());
+        assertEquals(1, type.getDefaultUserPropertiesReference()
+                .getCrossProfileContentSharingStrategy());
 
         assertEquals(23, type.getBadgeLabel(0));
         assertEquals(24, type.getBadgeLabel(1));
@@ -231,6 +236,8 @@
         assertEquals(UserProperties.SHOW_IN_LAUNCHER_SEPARATE, props.getShowInSharingSurfaces());
         assertEquals(UserProperties.SHOW_IN_QUIET_MODE_PAUSED,
                 props.getShowInQuietMode());
+        assertEquals(UserProperties.CROSS_PROFILE_CONTENT_SHARING_NO_DELEGATION,
+                props.getCrossProfileContentSharingStrategy());
 
         assertFalse(type.hasBadge());
     }
@@ -318,12 +325,14 @@
                 .setMediaSharedWithParent(false)
                 .setCredentialShareableWithParent(true)
                 .setAuthAlwaysRequiredToDisableQuietMode(false)
+                .setAllowStoppingUserWithDelayedLocking(false)
                 .setShowInSettings(20)
                 .setInheritDevicePolicy(21)
                 .setShowInSharingSurfaces(22)
                 .setShowInQuietMode(24)
                 .setDeleteAppWithParent(true)
-                .setAlwaysVisible(false);
+                .setAlwaysVisible(false)
+                .setCrossProfileContentSharingStrategy(1);
 
         final ArrayMap<String, UserTypeDetails.Builder> builders = new ArrayMap<>();
         builders.put(userTypeAosp1, new UserTypeDetails.Builder()
@@ -362,6 +371,8 @@
                 .isCredentialShareableWithParent());
         assertFalse(aospType.getDefaultUserPropertiesReference()
                 .isAuthAlwaysRequiredToDisableQuietMode());
+        assertFalse(aospType.getDefaultUserPropertiesReference()
+                .getAllowStoppingUserWithDelayedLocking());
         assertEquals(20, aospType.getDefaultUserPropertiesReference().getShowInSettings());
         assertEquals(21, aospType.getDefaultUserPropertiesReference()
                 .getInheritDevicePolicy());
@@ -370,6 +381,8 @@
                 aospType.getDefaultUserPropertiesReference().getShowInQuietMode());
         assertTrue(aospType.getDefaultUserPropertiesReference().getDeleteAppWithParent());
         assertFalse(aospType.getDefaultUserPropertiesReference().getAlwaysVisible());
+        assertEquals(1, aospType.getDefaultUserPropertiesReference()
+                .getCrossProfileContentSharingStrategy());
 
         // userTypeAosp2 should be modified.
         aospType = builders.get(userTypeAosp2).createUserTypeDetails();
@@ -413,6 +426,8 @@
                 .isCredentialShareableWithParent());
         assertTrue(aospType.getDefaultUserPropertiesReference()
                 .isAuthAlwaysRequiredToDisableQuietMode());
+        assertTrue(aospType.getDefaultUserPropertiesReference()
+                .getAllowStoppingUserWithDelayedLocking());
         assertEquals(23, aospType.getDefaultUserPropertiesReference().getShowInSettings());
         assertEquals(22,
                 aospType.getDefaultUserPropertiesReference().getShowInSharingSurfaces());
@@ -422,6 +437,8 @@
                 .getInheritDevicePolicy());
         assertFalse(aospType.getDefaultUserPropertiesReference().getDeleteAppWithParent());
         assertTrue(aospType.getDefaultUserPropertiesReference().getAlwaysVisible());
+        assertEquals(0, aospType.getDefaultUserPropertiesReference()
+                .getCrossProfileContentSharingStrategy());
 
         // userTypeOem1 should be created.
         UserTypeDetails.Builder customType = builders.get(userTypeOem1);
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index 8933c6c..a743fff 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -23,7 +23,6 @@
 import static org.junit.Assume.assumeTrue;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertThrows;
-import static org.testng.Assert.assertTrue;
 
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
@@ -219,6 +218,8 @@
                 .isEqualTo(cloneUserProperties.isMediaSharedWithParent());
         assertThat(typeProps.isCredentialShareableWithParent())
                 .isEqualTo(cloneUserProperties.isCredentialShareableWithParent());
+        assertThat(typeProps.getCrossProfileContentSharingStrategy())
+                .isEqualTo(cloneUserProperties.getCrossProfileContentSharingStrategy());
         assertThrows(SecurityException.class, cloneUserProperties::getDeleteAppWithParent);
         assertThrows(SecurityException.class, cloneUserProperties::getAlwaysVisible);
         compareDrawables(mUserManager.getUserBadge(),
@@ -338,9 +339,15 @@
         assertThat(typeProps.isAuthAlwaysRequiredToDisableQuietMode())
                 .isEqualTo(privateProfileUserProperties
                         .isAuthAlwaysRequiredToDisableQuietMode());
+        assertThat(typeProps.getCrossProfileContentSharingStrategy())
+                .isEqualTo(privateProfileUserProperties.getCrossProfileContentSharingStrategy());
         assertThrows(SecurityException.class, privateProfileUserProperties::getDeleteAppWithParent);
+        assertThrows(SecurityException.class,
+                privateProfileUserProperties::getAllowStoppingUserWithDelayedLocking);
+
         compareDrawables(mUserManager.getUserBadge(),
                 Resources.getSystem().getDrawable(userTypeDetails.getBadgePlain()));
+
         // Verify private profile parent
         assertThat(mUserManager.getProfileParent(mainUserId)).isNull();
         UserInfo parentProfileInfo = mUserManager.getProfileParent(userInfo.id);
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java
index 8464969..ee93bc1 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java
@@ -53,10 +53,10 @@
 import androidx.test.runner.AndroidJUnit4;
 import androidx.test.uiautomator.UiDevice;
 
+import com.android.internal.pm.parsing.pkg.PackageImpl;
 import com.android.internal.pm.parsing.pkg.ParsedPackage;
 import com.android.server.LocalServices;
 import com.android.server.SystemConfig;
-import com.android.server.pm.parsing.pkg.PackageImpl;
 import com.android.server.pm.pkg.AndroidPackage;
 
 import org.junit.After;
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
index 0f87202..587f5fa 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
@@ -29,9 +29,9 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.internal.pm.parsing.pkg.PackageImpl;
 import com.android.internal.pm.parsing.pkg.ParsedPackage;
 import com.android.internal.pm.pkg.parsing.ParsingPackage;
-import com.android.server.pm.parsing.pkg.PackageImpl;
 import com.android.server.pm.pkg.AndroidPackage;
 
 import dalvik.system.DelegateLastClassLoader;
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingValidationTest.kt b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingValidationTest.kt
index ee23a00..9b4ca2a 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingValidationTest.kt
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingValidationTest.kt
@@ -21,17 +21,17 @@
 import android.os.SystemProperties.PROP_VALUE_MAX
 import android.platform.test.annotations.Postsubmit
 import com.android.internal.R
+import com.android.internal.pm.pkg.parsing.ParsingPackageUtils
 import com.android.server.pm.PackageManagerService
-import com.android.server.pm.pkg.parsing.ParsingPackageUtils
 import com.google.common.truth.Truth.assertThat
+import java.io.ByteArrayInputStream
+import java.io.File
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertThrows
 import org.junit.Assert.fail
 import org.junit.Test
 import org.xmlpull.v1.XmlPullParser
 import org.xmlpull.v1.XmlPullParserFactory
-import java.io.ByteArrayInputStream
-import java.io.File
 
 @Postsubmit
 class AndroidPackageParsingValidationTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/TestPackageParser2.kt b/services/tests/servicestests/src/com/android/server/pm/parsing/TestPackageParser2.kt
index 2332817..c44f583 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/TestPackageParser2.kt
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/TestPackageParser2.kt
@@ -17,6 +17,7 @@
 package com.android.server.pm.parsing
 
 import android.content.pm.ApplicationInfo
+import android.util.ArraySet
 import java.io.File
 
 class TestPackageParser2(var cacheDir: File? = null) : PackageParser2(
@@ -33,4 +34,7 @@
         // behavior.
         return false
     }
+
+    override fun getHiddenApiWhitelistedApps() = ArraySet<String>()
+    override fun getInstallConstraintsAllowlist() = ArraySet<String>()
 })
diff --git a/services/tests/servicestests/src/com/android/server/rollback/RollbackUnitTest.java b/services/tests/servicestests/src/com/android/server/rollback/RollbackUnitTest.java
index 5ba4851..759b204 100644
--- a/services/tests/servicestests/src/com/android/server/rollback/RollbackUnitTest.java
+++ b/services/tests/servicestests/src/com/android/server/rollback/RollbackUnitTest.java
@@ -32,8 +32,9 @@
 import android.util.SparseArray;
 import android.util.SparseIntArray;
 
+import com.android.internal.pm.parsing.pkg.PackageImpl;
 import com.android.server.pm.PackageList;
-import com.android.server.pm.parsing.pkg.PackageImpl;
+
 import com.google.common.collect.Range;
 
 import org.junit.Before;
@@ -415,7 +416,7 @@
 
     private void addPkgWithMinExtVersions(String pkg, int[][] minExtVersions) {
         mPackages.add(pkg);
-        PackageImpl pkgImpl = new PackageImpl(pkg, "baseCodePath", "codePath", null, false);
+        PackageImpl pkgImpl = new PackageImpl(pkg, "baseCodePath", "codePath", null, false, null);
         pkgImpl.setMinExtensionVersions(sparseArrayFrom(minExtVersions));
 
         when(mMockPmi.getPackage(pkg)).thenReturn(pkgImpl);
diff --git a/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java
index e418d2f..769ec5f 100644
--- a/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java
@@ -57,17 +57,22 @@
 import android.net.Uri;
 import android.os.Process;
 import android.os.UserHandle;
+import android.platform.test.ravenwood.RavenwoodRule;
 import android.util.ArraySet;
 
 import androidx.test.InstrumentationRegistry;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 
 import java.util.Arrays;
 import java.util.Set;
 
 public class UriGrantsManagerServiceTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     private UriGrantsMockContext mContext;
     private UriGrantsManagerInternal mService;
 
@@ -79,7 +84,7 @@
 
     @Before
     public void setUp() throws Exception {
-        mContext = new UriGrantsMockContext(InstrumentationRegistry.getContext());
+        mContext = new UriGrantsMockContext();
         mService = UriGrantsManagerService.createForTest(mContext.getFilesDir()).getLocalService();
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/uri/UriGrantsMockContext.java b/services/tests/servicestests/src/com/android/server/uri/UriGrantsMockContext.java
index 7eb6c97..4c11de09 100644
--- a/services/tests/servicestests/src/com/android/server/uri/UriGrantsMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/uri/UriGrantsMockContext.java
@@ -21,11 +21,7 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
-import android.annotation.NonNull;
 import android.app.ActivityManagerInternal;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.ContextWrapper;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
@@ -33,18 +29,19 @@
 import android.content.pm.PathPermission;
 import android.content.pm.ProviderInfo;
 import android.net.Uri;
-import android.os.FileUtils;
 import android.os.PatternMatcher;
 import android.os.Process;
 import android.os.UserHandle;
-import android.test.mock.MockContentResolver;
+import android.test.mock.MockContext;
 import android.test.mock.MockPackageManager;
 
 import com.android.server.LocalServices;
 
 import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
 
-public class UriGrantsMockContext extends ContextWrapper {
+public class UriGrantsMockContext extends MockContext {
     static final String TAG = "UriGrants";
 
     static final int FLAG_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
@@ -98,19 +95,14 @@
     private final File mDir;
 
     private final MockPackageManager mPackage;
-    private final MockContentResolver mResolver;
 
     final ActivityManagerInternal mAmInternal;
     final PackageManagerInternal mPmInternal;
 
-    public UriGrantsMockContext(@NonNull Context base) {
-        super(base);
-        mDir = new File(base.getFilesDir(), TAG);
-        mDir.mkdirs();
-        FileUtils.deleteContents(mDir);
+    public UriGrantsMockContext() throws IOException {
+        mDir = Files.createTempDirectory(TAG).toFile();
 
         mPackage = new MockPackageManager();
-        mResolver = new MockContentResolver(this);
 
         mAmInternal = mock(ActivityManagerInternal.class);
         LocalServices.removeServiceForTest(ActivityManagerInternal.class);
@@ -239,11 +231,6 @@
     }
 
     @Override
-    public ContentResolver getContentResolver() {
-        return mResolver;
-    }
-
-    @Override
     public File getFilesDir() {
         return mDir;
     }
diff --git a/services/tests/servicestests/src/com/android/server/uri/UriPermissionTest.java b/services/tests/servicestests/src/com/android/server/uri/UriPermissionTest.java
index 07005a9..4d4f5ed 100644
--- a/services/tests/servicestests/src/com/android/server/uri/UriPermissionTest.java
+++ b/services/tests/servicestests/src/com/android/server/uri/UriPermissionTest.java
@@ -35,12 +35,18 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
+import android.platform.test.ravenwood.RavenwoodRule;
+
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
 public class UriPermissionTest {
+    @Rule
+    public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
     @Mock
     private UriGrantsManagerInternal mService;
 
diff --git a/services/tests/servicestests/src/com/android/server/utils/AnrTimerTest.java b/services/tests/servicestests/src/com/android/server/utils/AnrTimerTest.java
index 330dbb8..861d14a 100644
--- a/services/tests/servicestests/src/com/android/server/utils/AnrTimerTest.java
+++ b/services/tests/servicestests/src/com/android/server/utils/AnrTimerTest.java
@@ -30,13 +30,19 @@
 import com.android.internal.annotations.GuardedBy;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
 
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
 @SmallTest
 @Presubmit
+@RunWith(Parameterized.class)
 public class AnrTimerTest {
 
     // The commonly used message timeout key.
@@ -106,6 +112,16 @@
     }
 
     /**
+     * Force AnrTimer to use the test parameter for the feature flag.
+     */
+    class TestInjector extends AnrTimer.Injector {
+        @Override
+        boolean anrTimerServiceEnabled() {
+            return mEnabled;
+        }
+    }
+
+    /**
      * An instrumented AnrTimer.
      */
     private static class TestAnrTimer extends AnrTimer<TestArg> {
@@ -137,6 +153,17 @@
         assertEquals(actual.what, MSG_TIMEOUT);
     }
 
+    @Parameters(name = "featureEnabled={0}")
+    public static Collection<Object[]> data() {
+        return Arrays.asList(new Object[][] { {false}, {true} });
+    }
+
+    /** True if the feature is enabled. */
+    private boolean mEnabled;
+
+    public AnrTimerTest(boolean featureEnabled) {
+        mEnabled = featureEnabled;
+    }
 
     /**
      * Verify that a simple expiration succeeds.  The timer is started for 10ms.  The test
diff --git a/services/tests/servicestests/src/com/android/server/utils/OWNERS b/services/tests/servicestests/src/com/android/server/utils/OWNERS
index 5e24828..f5b19a1 100644
--- a/services/tests/servicestests/src/com/android/server/utils/OWNERS
+++ b/services/tests/servicestests/src/com/android/server/utils/OWNERS
@@ -1,2 +1,5 @@
 per-file EventLoggerTest.java = file:/platform/frameworks/av:/media/janitors/media_solutions_OWNERS
 per-file EventLoggerTest.java = jmtrivi@google.com
+
+# Bug component : 158088 = per-file AnrTimer*.java
+per-file AnrTimer*.java = file:/PERFORMANCE_OWNERS
diff --git a/services/tests/uiservicestests/Android.bp b/services/tests/uiservicestests/Android.bp
index 8891413..4e1c72a 100644
--- a/services/tests/uiservicestests/Android.bp
+++ b/services/tests/uiservicestests/Android.bp
@@ -40,11 +40,13 @@
         "servicestests-utils",
         "testables",
         "truth",
+        "TestParameterInjector",
         // TODO: remove once Android migrates to JUnit 4.12,
         // which provides assertThrows
         "testng",
         "flag-junit",
         "notification_flags_lib",
+        "platform-test-rules",
     ],
 
     libs: [
@@ -82,4 +84,7 @@
         "libutils",
         "netd_aidl_interface-V5-cpp",
     ],
+
+    // Required for TestParameterInjector
+    javacflags: ["-parameters"],
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/DefaultDeviceEffectsApplierTest.java b/services/tests/uiservicestests/src/com/android/server/notification/DefaultDeviceEffectsApplierTest.java
index 5febd02..260ee396 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/DefaultDeviceEffectsApplierTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/DefaultDeviceEffectsApplierTest.java
@@ -16,30 +16,51 @@
 
 package com.android.server.notification;
 
+import static android.app.UiModeManager.MODE_NIGHT_CUSTOM_TYPE_BEDTIME;
+import static android.service.notification.ZenModeConfig.UPDATE_ORIGIN_APP;
+import static android.service.notification.ZenModeConfig.UPDATE_ORIGIN_USER;
+
+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.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.argThat;
 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.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
 
 import android.app.UiModeManager;
 import android.app.WallpaperManager;
+import android.content.BroadcastReceiver;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.hardware.display.ColorDisplayManager;
 import android.os.PowerManager;
 import android.platform.test.flag.junit.SetFlagsRule;
 import android.service.notification.ZenDeviceEffects;
+import android.service.notification.ZenModeConfig;
 import android.testing.TestableContext;
 
 import androidx.test.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
+
+import com.google.testing.junit.testparameterinjector.TestParameter;
+import com.google.testing.junit.testparameterinjector.TestParameterInjector;
+import com.google.testing.junit.testparameterinjector.TestParameters;
 
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-@RunWith(AndroidJUnit4.class)
+@RunWith(TestParameterInjector.class)
 public class DefaultDeviceEffectsApplierTest {
 
     @Rule
@@ -52,10 +73,31 @@
     @Mock UiModeManager mUiModeManager;
     @Mock WallpaperManager mWallpaperManager;
 
+    private enum ChangeOrigin {
+        ORIGIN_UNKNOWN(ZenModeConfig.UPDATE_ORIGIN_UNKNOWN),
+        ORIGIN_INIT(ZenModeConfig.UPDATE_ORIGIN_INIT),
+        ORIGIN_INIT_USER(ZenModeConfig.UPDATE_ORIGIN_INIT_USER),
+        ORIGIN_USER(ZenModeConfig.UPDATE_ORIGIN_USER),
+        ORIGIN_APP(ZenModeConfig.UPDATE_ORIGIN_APP),
+        ORIGIN_SYSTEM_OR_SYSTEMUI(ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI),
+        ORIGIN_RESTORE_BACKUP(ZenModeConfig.UPDATE_ORIGIN_RESTORE_BACKUP);
+
+        private final int mValue;
+
+        ChangeOrigin(@ZenModeConfig.ConfigChangeOrigin int value) {
+            mValue = value;
+        }
+
+        @ZenModeConfig.ConfigChangeOrigin
+        public int value() {
+            return mValue;
+        }
+    }
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mContext = new TestableContext(InstrumentationRegistry.getContext(), null);
+        mContext = spy(new TestableContext(InstrumentationRegistry.getContext(), null));
         mContext.addMockSystemService(PowerManager.class, mPowerManager);
         mContext.addMockSystemService(ColorDisplayManager.class, mColorDisplayManager);
         mContext.addMockSystemService(UiModeManager.class, mUiModeManager);
@@ -74,25 +116,33 @@
                 .setShouldDisplayGrayscale(true)
                 .setShouldUseNightMode(true)
                 .build();
-        mApplier.apply(effects);
+        mApplier.apply(effects, UPDATE_ORIGIN_USER);
 
         verify(mPowerManager).suppressAmbientDisplay(anyString(), eq(true));
         verify(mColorDisplayManager).setSaturationLevel(eq(0));
         verify(mWallpaperManager).setWallpaperDimAmount(eq(0.6f));
-        verifyZeroInteractions(mUiModeManager); // Coming later; adding now so test fails then. :)
+        verify(mUiModeManager).setNightModeActivatedForCustomMode(
+                eq(MODE_NIGHT_CUSTOM_TYPE_BEDTIME), eq(true));
     }
 
     @Test
-    public void apply_removesEffects() {
+    public void apply_removesPreviouslyAppliedEffects() {
         mSetFlagsRule.enableFlags(android.app.Flags.FLAG_MODES_API);
 
+        ZenDeviceEffects previousEffects = new ZenDeviceEffects.Builder()
+                .setShouldSuppressAmbientDisplay(true)
+                .setShouldDimWallpaper(true)
+                .build();
+        mApplier.apply(previousEffects, UPDATE_ORIGIN_USER);
+        verify(mPowerManager).suppressAmbientDisplay(anyString(), eq(true));
+        verify(mWallpaperManager).setWallpaperDimAmount(eq(0.6f));
+
         ZenDeviceEffects noEffects = new ZenDeviceEffects.Builder().build();
-        mApplier.apply(noEffects);
+        mApplier.apply(noEffects, UPDATE_ORIGIN_USER);
 
         verify(mPowerManager).suppressAmbientDisplay(anyString(), eq(false));
-        verify(mColorDisplayManager).setSaturationLevel(eq(100));
         verify(mWallpaperManager).setWallpaperDimAmount(eq(0.0f));
-        verifyZeroInteractions(mUiModeManager);
+        verifyZeroInteractions(mColorDisplayManager, mUiModeManager);
     }
 
     @Test
@@ -107,9 +157,125 @@
                 .setShouldDisplayGrayscale(true)
                 .setShouldUseNightMode(true)
                 .build();
-        mApplier.apply(effects);
+        mApplier.apply(effects, UPDATE_ORIGIN_USER);
 
         verify(mPowerManager).suppressAmbientDisplay(anyString(), eq(true));
         // (And no crash from missing services).
     }
+
+    @Test
+    public void apply_someEffects_onlyThoseEffectsApplied() {
+        mSetFlagsRule.enableFlags(android.app.Flags.FLAG_MODES_API);
+
+        ZenDeviceEffects effects = new ZenDeviceEffects.Builder()
+                .setShouldDimWallpaper(true)
+                .setShouldDisplayGrayscale(true)
+                .build();
+        mApplier.apply(effects, UPDATE_ORIGIN_USER);
+
+        verify(mColorDisplayManager).setSaturationLevel(eq(0));
+        verify(mWallpaperManager).setWallpaperDimAmount(eq(0.6f));
+
+        verify(mPowerManager, never()).suppressAmbientDisplay(anyString(), anyBoolean());
+        verify(mUiModeManager, never()).setNightModeActivatedForCustomMode(anyInt(), anyBoolean());
+    }
+
+    @Test
+    public void apply_onlyEffectDeltaApplied() {
+        mSetFlagsRule.enableFlags(android.app.Flags.FLAG_MODES_API);
+
+        mApplier.apply(new ZenDeviceEffects.Builder().setShouldDimWallpaper(true).build(),
+                UPDATE_ORIGIN_USER);
+        verify(mWallpaperManager).setWallpaperDimAmount(eq(0.6f));
+
+        // Apply a second effect and remove the first one.
+        mApplier.apply(new ZenDeviceEffects.Builder().setShouldDisplayGrayscale(true).build(),
+                UPDATE_ORIGIN_USER);
+
+        // Wallpaper dimming was undone, Grayscale was applied, nothing else was touched.
+        verify(mWallpaperManager).setWallpaperDimAmount(eq(0.0f));
+        verify(mColorDisplayManager).setSaturationLevel(eq(0));
+        verifyZeroInteractions(mPowerManager);
+        verifyZeroInteractions(mUiModeManager);
+    }
+
+    @Test
+    public void apply_nightModeFromApp_appliedOnScreenOff() {
+        mSetFlagsRule.enableFlags(android.app.Flags.FLAG_MODES_API);
+        ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
+                ArgumentCaptor.forClass(BroadcastReceiver.class);
+        ArgumentCaptor<IntentFilter> intentFilterCaptor =
+                ArgumentCaptor.forClass(IntentFilter.class);
+
+        when(mPowerManager.isInteractive()).thenReturn(true);
+
+        mApplier.apply(new ZenDeviceEffects.Builder().setShouldUseNightMode(true).build(),
+                UPDATE_ORIGIN_APP);
+
+        // Effect was not yet applied, but a broadcast receiver was registered.
+        verifyZeroInteractions(mUiModeManager);
+        verify(mContext).registerReceiver(broadcastReceiverCaptor.capture(),
+                intentFilterCaptor.capture(), anyInt());
+        assertThat(intentFilterCaptor.getValue().getAction(0)).isEqualTo(Intent.ACTION_SCREEN_OFF);
+        BroadcastReceiver screenOffReceiver = broadcastReceiverCaptor.getValue();
+
+        // Now the "screen off" event comes.
+        screenOffReceiver.onReceive(mContext, new Intent(Intent.ACTION_SCREEN_OFF));
+
+        // So the effect is applied, and we stopped listening for this event.
+        verify(mUiModeManager).setNightModeActivatedForCustomMode(
+                eq(MODE_NIGHT_CUSTOM_TYPE_BEDTIME), eq(true));
+        verify(mContext).unregisterReceiver(eq(screenOffReceiver));
+    }
+
+    @Test
+    public void apply_nightModeWithScreenOff_appliedImmediately(
+            @TestParameter ChangeOrigin origin) {
+        mSetFlagsRule.enableFlags(android.app.Flags.FLAG_MODES_API);
+
+        when(mPowerManager.isInteractive()).thenReturn(false);
+
+        mApplier.apply(new ZenDeviceEffects.Builder().setShouldUseNightMode(true).build(),
+                origin.value());
+
+        // Effect was applied, and no broadcast receiver was registered.
+        verify(mUiModeManager).setNightModeActivatedForCustomMode(
+                eq(MODE_NIGHT_CUSTOM_TYPE_BEDTIME), eq(true));
+        verify(mContext, never()).registerReceiver(any(), any(), anyInt());
+    }
+
+    @Test
+    @TestParameters({"{origin: ORIGIN_USER}", "{origin: ORIGIN_INIT}", "{origin: ORIGIN_INIT_USER}",
+            "{origin: ORIGIN_SYSTEM_OR_SYSTEMUI}"})
+    public void apply_nightModeWithScreenOn_appliedImmediatelyBasedOnOrigin(ChangeOrigin origin) {
+        mSetFlagsRule.enableFlags(android.app.Flags.FLAG_MODES_API);
+
+        when(mPowerManager.isInteractive()).thenReturn(true);
+
+        mApplier.apply(new ZenDeviceEffects.Builder().setShouldUseNightMode(true).build(),
+                origin.value());
+
+        // Effect was applied, and no broadcast receiver was registered.
+        verify(mUiModeManager).setNightModeActivatedForCustomMode(
+                eq(MODE_NIGHT_CUSTOM_TYPE_BEDTIME), eq(true));
+        verify(mContext, never()).registerReceiver(any(), any(), anyInt());
+    }
+
+    @Test
+    @TestParameters({"{origin: ORIGIN_APP}", "{origin: ORIGIN_RESTORE_BACKUP}",
+            "{origin: ORIGIN_UNKNOWN}"})
+    public void apply_nightModeWithScreenOn_willBeAppliedLaterBasedOnOrigin(ChangeOrigin origin) {
+        mSetFlagsRule.enableFlags(android.app.Flags.FLAG_MODES_API);
+
+        when(mPowerManager.isInteractive()).thenReturn(true);
+
+        mApplier.apply(new ZenDeviceEffects.Builder().setShouldUseNightMode(true).build(),
+                origin.value());
+
+        // Effect was not applied, will be on next screen-off.
+        verifyZeroInteractions(mUiModeManager);
+        verify(mContext).registerReceiver(any(),
+                argThat(filter -> Intent.ACTION_SCREEN_OFF.equals(filter.getAction(0))),
+                anyInt());
+    }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java
index ea11395..2868b7e 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java
@@ -15,7 +15,10 @@
  */
 package com.android.server.notification;
 
+import static android.Manifest.permission.RECEIVE_SENSITIVE_NOTIFICATIONS;
 import static android.content.pm.PackageManager.MATCH_ANY_USER;
+import static android.permission.PermissionManager.PERMISSION_GRANTED;
+import static android.service.notification.Flags.FLAG_REDACT_SENSITIVE_NOTIFICATIONS_FROM_UNTRUSTED_LISTENERS;
 import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ALERTING;
 import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_CONVERSATIONS;
 import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ONGOING;
@@ -47,11 +50,14 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.annotation.SuppressLint;
 import android.app.INotificationManager;
 import android.app.Notification;
 import android.app.NotificationChannel;
 import android.app.NotificationChannelGroup;
 import android.app.NotificationManager;
+import android.companion.AssociationInfo;
+import android.companion.ICompanionDeviceManager;
 import android.content.ComponentName;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
@@ -62,6 +68,10 @@
 import android.os.Parcel;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.platform.test.annotations.RequiresFlagsDisabled;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 import android.service.notification.INotificationListener;
 import android.service.notification.NotificationListenerFilter;
 import android.service.notification.NotificationListenerService;
@@ -76,10 +86,12 @@
 import com.android.modules.utils.TypedXmlPullParser;
 import com.android.modules.utils.TypedXmlSerializer;
 import com.android.server.UiServiceTestCase;
+import com.android.server.pm.pkg.PackageStateInternal;
 
 import com.google.common.collect.ImmutableList;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.mockito.ArgumentMatcher;
 import org.mockito.Mock;
@@ -90,12 +102,17 @@
 import java.io.BufferedOutputStream;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
 
+@SuppressLint("GuardedBy")
 public class NotificationListenersTest extends UiServiceTestCase {
 
+    @Rule
+    public CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
     @Mock
     private PackageManager mPm;
     @Mock
@@ -103,7 +120,8 @@
     @Mock
     private Resources mResources;
 
-    @Mock
+    // mNm is going to be a spy, so it must use doReturn.when, not when.thenReturn, as
+    // when.thenReturn will result in the real method being called
     NotificationManagerService mNm;
     @Mock
     private INotificationManager mINm;
@@ -111,6 +129,7 @@
 
     NotificationManagerService.NotificationListeners mListeners;
 
+    private int mUid1 = 98989;
     private ComponentName mCn1 = new ComponentName("pkg", "pkg.cmp");
     private ComponentName mCn2 = new ComponentName("pkg2", "pkg2.cmp2");
     private ComponentName mUninstalledComponent = new ComponentName("pkg3",
@@ -118,15 +137,26 @@
 
     @Before
     public void setUp() throws Exception {
+        mNm = spy(new NotificationManagerService(mContext));
         MockitoAnnotations.initMocks(this);
         getContext().setMockPackageManager(mPm);
         doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any());
 
-        when(mNm.isInteractionVisibleToListener(any(), anyInt())).thenReturn(true);
+        doReturn(true).when(mNm).isInteractionVisibleToListener(any(), anyInt());
 
         mListeners = spy(mNm.new NotificationListeners(
                 mContext, new Object(), mock(ManagedServices.UserProfiles.class), miPm));
         when(mNm.getBinderService()).thenReturn(mINm);
+        mNm.mPackageManager = mock(IPackageManager.class);
+        PackageStateInternal psi = mock(PackageStateInternal.class);
+        mNm.mPackageManagerInternal = mPmi;
+        when(psi.getAppId()).thenReturn(mUid1);
+        when(mNm.mPackageManagerInternal.getPackageStateInternal(any())).thenReturn(psi);
+        mNm.mCompanionManager = mock(ICompanionDeviceManager.class);
+        when(mNm.mCompanionManager.getAllAssociationsForUser(anyInt()))
+                .thenReturn(new ArrayList<>());
+        mNm.mHandler = mock(NotificationManagerService.WorkerHandler.class);
+        mNm.mAssistants = mock(NotificationManagerService.NotificationAssistants.class);
     }
 
     @Test
@@ -499,11 +529,11 @@
         // Neither user0 and user1 is in the lockdown mode
         when(r0.getUser()).thenReturn(uh0);
         when(uh0.getIdentifier()).thenReturn(0);
-        when(mNm.isInLockDownMode(0)).thenReturn(false);
+        doReturn(false).when(mNm).isInLockDownMode(0);
 
         when(r1.getUser()).thenReturn(uh1);
         when(uh1.getIdentifier()).thenReturn(1);
-        when(mNm.isInLockDownMode(1)).thenReturn(false);
+        doReturn(false).when(mNm).isInLockDownMode(1);
 
         mListeners.notifyPostedLocked(r0, old0, true);
         mListeners.notifyPostedLocked(r0, old0, false);
@@ -555,12 +585,12 @@
         // Neither user0 and user1 is in the lockdown mode
         when(r0.getUser()).thenReturn(uh0);
         when(uh0.getIdentifier()).thenReturn(0);
-        when(mNm.isInLockDownMode(0)).thenReturn(false);
+        doReturn(false).when(mNm).isInLockDownMode(0);
         when(r0.getSbn()).thenReturn(sbn);
 
         when(r1.getUser()).thenReturn(uh1);
         when(uh1.getIdentifier()).thenReturn(1);
-        when(mNm.isInLockDownMode(1)).thenReturn(false);
+        doReturn(false).when(mNm).isInLockDownMode(1);
         when(r1.getSbn()).thenReturn(sbn);
 
         mListeners.notifyRemovedLocked(r0, 0, rs0);
@@ -617,9 +647,10 @@
         List<ManagedServices.ManagedServiceInfo> services = ImmutableList.of(info);
         when(mListeners.getServices()).thenReturn(services);
 
-        when(mNm.isVisibleToListener(any(), anyInt(), any())).thenReturn(true);
-        when(mNm.makeRankingUpdateLocked(info)).thenReturn(mock(NotificationRankingUpdate.class));
-        mNm.mPackageManagerInternal = mPmi;
+        doReturn(true).when(mNm).isVisibleToListener(any(), anyInt(), any());
+        doReturn(mock(NotificationRankingUpdate.class)).when(mNm).makeRankingUpdateLocked(info);
+        doReturn(false).when(mNm).isInLockDownMode(anyInt());
+        doNothing().when(mNm).updateUriPermissions(any(), any(), any(), anyInt());
 
         mListeners.notifyPostedLocked(r, null);
 
@@ -664,6 +695,143 @@
         }, 20, 50);
     }
 
+    @Test
+    @RequiresFlagsEnabled(FLAG_REDACT_SENSITIVE_NOTIFICATIONS_FROM_UNTRUSTED_LISTENERS)
+    public void testListenerTrusted_withPermission() throws RemoteException {
+        when(mNm.mPackageManager.checkUidPermission(RECEIVE_SENSITIVE_NOTIFICATIONS, mUid1))
+                .thenReturn(PERMISSION_GRANTED);
+        ManagedServices.ManagedServiceInfo info = getMockServiceInfo();
+        mListeners.onServiceAdded(info);
+        assertTrue(mListeners.isUidTrusted(mUid1));
+    }
+
+    @Test
+    @RequiresFlagsEnabled(FLAG_REDACT_SENSITIVE_NOTIFICATIONS_FROM_UNTRUSTED_LISTENERS)
+    public void testListenerTrusted_withSystemSignature() {
+        when(mNm.mPackageManagerInternal.isPlatformSigned(mCn1.getPackageName())).thenReturn(true);
+        ManagedServices.ManagedServiceInfo info = getMockServiceInfo();
+        mListeners.onServiceAdded(info);
+        assertTrue(mListeners.isUidTrusted(mUid1));
+    }
+
+    @Test
+    @RequiresFlagsEnabled(FLAG_REDACT_SENSITIVE_NOTIFICATIONS_FROM_UNTRUSTED_LISTENERS)
+    public void testListenerTrusted_withCdmAssociation() throws Exception {
+        mNm.mCompanionManager = mock(ICompanionDeviceManager.class);
+        AssociationInfo assocInfo = mock(AssociationInfo.class);
+        when(assocInfo.isRevoked()).thenReturn(false);
+        when(assocInfo.getPackageName()).thenReturn(mCn1.getPackageName());
+        when(assocInfo.getUserId()).thenReturn(UserHandle.getUserId(mUid1));
+        ArrayList<AssociationInfo> infos = new ArrayList<>();
+        infos.add(assocInfo);
+        when(mNm.mCompanionManager.getAllAssociationsForUser(anyInt())).thenReturn(infos);
+        ManagedServices.ManagedServiceInfo info = getMockServiceInfo();
+        mListeners.onServiceAdded(info);
+        assertTrue(mListeners.isUidTrusted(mUid1));
+    }
+
+    @Test
+    @RequiresFlagsDisabled(FLAG_REDACT_SENSITIVE_NOTIFICATIONS_FROM_UNTRUSTED_LISTENERS)
+    public void testListenerTrusted_ifFlagDisabled() {
+        ManagedServices.ManagedServiceInfo info = getMockServiceInfo();
+        mListeners.onServiceAdded(info);
+        assertTrue(mListeners.isUidTrusted(mUid1));
+    }
+
+    @Test
+    @RequiresFlagsEnabled(FLAG_REDACT_SENSITIVE_NOTIFICATIONS_FROM_UNTRUSTED_LISTENERS)
+    public void testRedaction_whenPosted() {
+        ArrayList<ManagedServices.ManagedServiceInfo> infos = new ArrayList<>();
+        infos.add(getMockServiceInfo());
+        doReturn(infos).when(mListeners).getServices();
+        doReturn(mock(StatusBarNotification.class))
+                .when(mListeners).redactStatusBarNotification(any());
+        doReturn(false).when(mNm).isInLockDownMode(anyInt());
+        doReturn(true).when(mNm).isVisibleToListener(any(), anyInt(), any());
+        NotificationRecord r = mock(NotificationRecord.class);
+        when(r.getUser()).thenReturn(UserHandle.of(0));
+        StatusBarNotification sbn = getSbn(0);
+        NotificationRecord old = mock(NotificationRecord.class);
+        when(old.getUser()).thenReturn(UserHandle.of(0));
+        StatusBarNotification oldSbn = getSbn(1);
+        when(r.getSbn()).thenReturn(sbn);
+        when(r.hasSensitiveContent()).thenReturn(true);
+        when(old.getSbn()).thenReturn(oldSbn);
+        when(old.hasSensitiveContent()).thenReturn(true);
+
+        mListeners.notifyPostedLocked(r, old);
+        verify(mListeners, atLeast(1)).redactStatusBarNotification(eq(sbn));
+        verify(mListeners, never()).redactStatusBarNotification(eq(oldSbn));
+
+
+    }
+
+    @Test
+    @RequiresFlagsEnabled(FLAG_REDACT_SENSITIVE_NOTIFICATIONS_FROM_UNTRUSTED_LISTENERS)
+    public void testRedaction_whenPosted_oldRemoved() {
+        ArrayList<ManagedServices.ManagedServiceInfo> infos = new ArrayList<>();
+        infos.add(getMockServiceInfo());
+        doReturn(infos).when(mListeners).getServices();
+        doReturn(mock(StatusBarNotification.class))
+                .when(mListeners).redactStatusBarNotification(any());
+        doReturn(false).when(mNm).isInLockDownMode(anyInt());
+        doReturn(true).when(mNm).isVisibleToListener(any(), anyInt(), any());
+        NotificationRecord r = mock(NotificationRecord.class);
+        when(r.getUser()).thenReturn(UserHandle.of(0));
+        StatusBarNotification sbn = getSbn(0);
+        NotificationRecord old = mock(NotificationRecord.class);
+        when(old.getUser()).thenReturn(UserHandle.of(0));
+        StatusBarNotification oldSbn = getSbn(1);
+        when(r.getSbn()).thenReturn(sbn);
+        when(r.hasSensitiveContent()).thenReturn(true);
+        when(old.getSbn()).thenReturn(oldSbn);
+        when(old.hasSensitiveContent()).thenReturn(true);
+
+        doReturn(true).when(mNm).isVisibleToListener(eq(oldSbn), anyInt(), any());
+        doReturn(false).when(mNm).isVisibleToListener(eq(sbn), anyInt(), any());
+        mListeners.notifyPostedLocked(r, old);
+        // When the old sbn is removed, the old should be redacted
+        verify(mListeners, atLeast(1)).redactStatusBarNotification(eq(oldSbn));
+    }
+
+    @Test
+    @RequiresFlagsEnabled(FLAG_REDACT_SENSITIVE_NOTIFICATIONS_FROM_UNTRUSTED_LISTENERS)
+    public void testRedaction_whenRemoved() {
+        doReturn(mock(StatusBarNotification.class))
+                .when(mListeners).redactStatusBarNotification(any());
+        ArrayList<ManagedServices.ManagedServiceInfo> infos = new ArrayList<>();
+        infos.add(getMockServiceInfo());
+        doReturn(infos).when(mListeners).getServices();
+        doReturn(false).when(mNm).isInLockDownMode(anyInt());
+        doReturn(true).when(mNm).isVisibleToListener(any(), anyInt(), any());
+        NotificationRecord r = mock(NotificationRecord.class);
+        when(r.getUser()).thenReturn(UserHandle.of(0));
+        StatusBarNotification sbn = getSbn(0);
+        when(r.getSbn()).thenReturn(sbn);
+        when(r.hasSensitiveContent()).thenReturn(true);
+        mNm.mAssistants = mock(NotificationManagerService.NotificationAssistants.class);
+
+        mListeners.notifyRemovedLocked(r, 0, mock(NotificationStats.class));
+        verify(mListeners, atLeast(1)).redactStatusBarNotification(any());
+    }
+
+    @Test
+    @RequiresFlagsDisabled(FLAG_REDACT_SENSITIVE_NOTIFICATIONS_FROM_UNTRUSTED_LISTENERS)
+    public void testRedaction_noneIfFlagDisabled() {
+        ArrayList<ManagedServices.ManagedServiceInfo> infos = new ArrayList<>();
+        infos.add(getMockServiceInfo());
+        doReturn(infos).when(mListeners).getServices();
+        doReturn(false).when(mNm).isInLockDownMode(anyInt());
+        doReturn(true).when(mNm).isVisibleToListener(any(), anyInt(), any());
+        NotificationRecord r = mock(NotificationRecord.class);
+        when(r.getUser()).thenReturn(UserHandle.of(0));
+        StatusBarNotification sbn = getSbn(0);
+        when(r.getSbn()).thenReturn(sbn);
+        when(r.hasSensitiveContent()).thenReturn(true);
+        mListeners.notifyRemovedLocked(r, 0, mock(NotificationStats.class));
+        verify(mListeners, never()).redactStatusBarNotification(eq(sbn));
+    }
+
     /**
      * Helper method to test the thread safety of some operations.
      *
@@ -701,10 +869,8 @@
     private ManagedServices.ManagedServiceInfo getParcelingListener(
             final NotificationChannelGroup toParcel)
             throws RemoteException {
-        ManagedServices.ManagedServiceInfo i1 = mock(ManagedServices.ManagedServiceInfo.class);
-        when(i1.isSystem()).thenReturn(true);
-        INotificationListener l1 = mock(INotificationListener.class);
-        when(i1.enabledAndUserMatches(anyInt())).thenReturn(true);
+        ManagedServices.ManagedServiceInfo i1 = getMockServiceInfo();
+        INotificationListener l1 = (INotificationListener) i1.getService();
         doAnswer(invocationOnMock -> {
             try {
                 toParcel.writeToParcel(Parcel.obtain(), 0);
@@ -715,7 +881,24 @@
             }
             return null;
         }).when(l1).onNotificationChannelGroupModification(anyString(), any(), any(), anyInt());
-        when(i1.getService()).thenReturn(l1);
         return i1;
     }
+
+    private ManagedServices.ManagedServiceInfo getMockServiceInfo() {
+        ManagedServices.ManagedServiceInfo i1 = mock(ManagedServices.ManagedServiceInfo.class);
+        when(i1.isSystem()).thenReturn(true);
+        INotificationListener l1 = mock(INotificationListener.class);
+        when(i1.enabledAndUserMatches(anyInt())).thenReturn(true);
+        when(i1.getService()).thenReturn(l1);
+        i1.service = l1;
+        i1.uid = mUid1;
+        i1.component = mCn1;
+        return i1;
+    }
+
+    private StatusBarNotification getSbn(int id) {
+        return new StatusBarNotification("pkg1", "pkg1", id, "", mUid1, 0,
+                mock(Notification.class), UserHandle.of(0), "", 0);
+
+    }
 }
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 ee08fd2..48c00a8 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -24,6 +24,7 @@
 import static android.app.Notification.EXTRA_ALLOW_DURING_SETUP;
 import static android.app.Notification.EXTRA_PICTURE;
 import static android.app.Notification.EXTRA_PICTURE_ICON;
+import static android.app.Notification.EXTRA_TEXT;
 import static android.app.Notification.FLAG_AUTO_CANCEL;
 import static android.app.Notification.FLAG_BUBBLE;
 import static android.app.Notification.FLAG_CAN_COLORIZE;
@@ -77,6 +78,7 @@
 import static android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
 import static android.service.notification.Adjustment.KEY_IMPORTANCE;
 import static android.service.notification.Adjustment.KEY_USER_SENTIMENT;
+import static android.service.notification.Flags.FLAG_REDACT_SENSITIVE_NOTIFICATIONS_FROM_UNTRUSTED_LISTENERS;
 import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ALERTING;
 import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_CONVERSATIONS;
 import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ONGOING;
@@ -209,17 +211,27 @@
 import android.os.UserManager;
 import android.os.WorkSource;
 import android.permission.PermissionManager;
+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.platform.test.rule.DeniedDevices;
+import android.platform.test.rule.DeviceProduct;
+import android.platform.test.rule.LimitDevicesRule;
 import android.provider.DeviceConfig;
 import android.provider.MediaStore;
 import android.provider.Settings;
 import android.service.notification.Adjustment;
 import android.service.notification.ConversationChannelWrapper;
+import android.service.notification.DeviceEffectsApplier;
+import android.service.notification.INotificationListener;
 import android.service.notification.NotificationListenerFilter;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationRankingUpdate;
 import android.service.notification.NotificationStats;
 import android.service.notification.StatusBarNotification;
+import android.service.notification.ZenModeConfig;
 import android.service.notification.ZenPolicy;
 import android.telecom.TelecomManager;
 import android.telephony.TelephonyManager;
@@ -279,6 +291,7 @@
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TestRule;
@@ -311,6 +324,7 @@
 @RunWith(AndroidTestingRunner.class)
 @SuppressLint("GuardedBy") // It's ok for this test to access guarded methods from the service.
 @RunWithLooper
+@DeniedDevices(denied = {DeviceProduct.CF_AUTO})
 public class NotificationManagerServiceTest extends UiServiceTestCase {
     private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId";
     private static final String TEST_PACKAGE = "The.name.is.Package.Test.Package";
@@ -325,13 +339,20 @@
             NotificationManagerService.class.getSimpleName() + ".TIMEOUT";
     private static final String EXTRA_KEY = "key";
     private static final String SCHEME_TIMEOUT = "timeout";
+    private static final String REDACTED_TEXT = "redacted text";
 
     private final int mUid = Binder.getCallingUid();
     private final @UserIdInt int mUserId = UserHandle.getUserId(mUid);
 
+    @ClassRule
+    public static final LimitDevicesRule sLimitDevicesRule = new LimitDevicesRule();
+
     @Rule
     public TestRule compatChangeRule = new PlatformCompatChangeRule();
 
+    @Rule
+    public CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
     private TestableNotificationManagerService mService;
     private INotificationManager mBinderService;
     private NotificationManagerInternal mInternalService;
@@ -625,6 +646,10 @@
     }
 
     private void initNMS() throws Exception {
+        initNMS(SystemService.PHASE_BOOT_COMPLETED);
+    }
+
+    private void initNMS(int upToBootPhase) throws Exception {
         mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger,
                 mNotificationInstanceIdSequence);
 
@@ -652,13 +677,21 @@
                 mAmi, mToastRateLimiter, mPermissionHelper, mock(UsageStatsManagerInternal.class),
                 mTelecomManager, mLogger, mTestFlagResolver, mPermissionManager,
                 mPowerManager, mPostNotificationTrackerFactory);
+
         // Return first true for RoleObserver main-thread check
         when(mMainLooper.isCurrentThread()).thenReturn(true).thenReturn(false);
-        mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY, mMainLooper);
+
+        if (upToBootPhase >= SystemService.PHASE_SYSTEM_SERVICES_READY) {
+            mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY, mMainLooper);
+        }
+
         Mockito.reset(mHistoryManager);
         verify(mHistoryManager, never()).onBootPhaseAppsCanStart();
-        mService.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START, mMainLooper);
-        verify(mHistoryManager).onBootPhaseAppsCanStart();
+
+        if (upToBootPhase >= SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
+            mService.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START, mMainLooper);
+            verify(mHistoryManager).onBootPhaseAppsCanStart();
+        }
 
         // TODO b/291907312: remove feature flag
         if (Flags.refactorAttentionHelper()) {
@@ -904,7 +937,9 @@
         mTestNotificationChannel.setAllowBubbles(channelEnabled);
     }
 
-    private void setUpPrefsForHistory(int uid, boolean globalEnabled) {
+    private void setUpPrefsForHistory(int uid, boolean globalEnabled) throws Exception {
+        initNMS(SystemService.PHASE_ACTIVITY_MANAGER_READY);
+
         // Sets NOTIFICATION_HISTORY_ENABLED setting for calling process uid
         Settings.Secure.putIntForUser(mContext.getContentResolver(),
                 Settings.Secure.NOTIFICATION_HISTORY_ENABLED, globalEnabled ? 1 : 0, uid);
@@ -970,6 +1005,12 @@
         return new NotificationRecord(mContext, sbn, channel);
     }
 
+    private NotificationRecord generateNotificationRecord(NotificationChannel channel,
+            long postTime) {
+        final StatusBarNotification sbn = generateSbn(PKG, mUid, postTime, 0);
+        return new NotificationRecord(mContext, sbn, channel);
+    }
+
     private NotificationRecord generateNotificationRecord(NotificationChannel channel, int userId) {
         return generateNotificationRecord(channel, 1, userId);
     }
@@ -984,7 +1025,8 @@
                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id, "tag", mUid, 0,
                 nb.build(), new UserHandle(userId), null, 0);
-        return new NotificationRecord(mContext, sbn, channel);
+        NotificationRecord r = new NotificationRecord(mContext, sbn, channel);
+        return r;
     }
 
     private NotificationRecord generateMessageBubbleNotifRecord(NotificationChannel channel,
@@ -1007,6 +1049,16 @@
         return new NotificationRecord(mContext, sbn, channel);
     }
 
+    private StatusBarNotification generateRedactedSbn(NotificationChannel channel, int id,
+            int userId) {
+        Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
+                .setContentTitle("foo")
+                .setSmallIcon(android.R.drawable.sym_def_app_icon)
+                .setContentText(REDACTED_TEXT);
+        return new StatusBarNotification(PKG, PKG, id, "tag", mUid, 0,
+                nb.build(), new UserHandle(userId), null, 0);
+    }
+
     private Map<String, Answer> getSignalExtractorSideEffects() {
         Map<String, Answer> answers = new ArrayMap<>();
 
@@ -8929,8 +8981,8 @@
         mBinderService.addAutomaticZenRule(rule, "com.android.settings");
 
         // verify that zen mode helper gets passed in a package name of "android"
-        verify(mockZenModeHelper).addAutomaticZenRule(eq("android"), eq(rule), anyString(),
-                anyInt(), eq(ZenModeHelper.FROM_SYSTEM_OR_SYSTEMUI)); // system call
+        verify(mockZenModeHelper).addAutomaticZenRule(eq("android"), eq(rule),
+                eq(ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI), anyString(), anyInt());
     }
 
     @Test
@@ -8951,8 +9003,8 @@
         mBinderService.addAutomaticZenRule(rule, "com.android.settings");
 
         // verify that zen mode helper gets passed in a package name of "android"
-        verify(mockZenModeHelper).addAutomaticZenRule(eq("android"), eq(rule), anyString(),
-                anyInt(), eq(ZenModeHelper.FROM_SYSTEM_OR_SYSTEMUI));  // system call
+        verify(mockZenModeHelper).addAutomaticZenRule(eq("android"), eq(rule),
+                eq(ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI), anyString(), anyInt());
     }
 
     @Test
@@ -8972,8 +9024,44 @@
 
         // verify that zen mode helper gets passed in the package name from the arg, not the owner
         verify(mockZenModeHelper).addAutomaticZenRule(
-                eq("another.package"), eq(rule), anyString(), anyInt(),
-                eq(ZenModeHelper.FROM_APP));  // doesn't count as a system/systemui call
+                eq("another.package"), eq(rule), eq(ZenModeConfig.UPDATE_ORIGIN_APP),
+                anyString(), anyInt());  // doesn't count as a system/systemui call
+    }
+
+    @Test
+    @EnableFlags(android.app.Flags.FLAG_MODES_API)
+    public void testAddAutomaticZenRule_typeManagedCanBeUsedByDeviceOwners() throws Exception {
+        mService.setCallerIsNormalPackage();
+        mService.setZenHelper(mock(ZenModeHelper.class));
+        when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
+                .thenReturn(true);
+
+        AutomaticZenRule rule = new AutomaticZenRule.Builder("rule", Uri.parse("uri"))
+                .setType(AutomaticZenRule.TYPE_MANAGED)
+                .setOwner(new ComponentName("pkg", "cls"))
+                .build();
+        when(mDevicePolicyManager.isActiveDeviceOwner(anyInt())).thenReturn(true);
+
+        mBinderService.addAutomaticZenRule(rule, "pkg");
+        // No exception!
+    }
+
+    @Test
+    @EnableFlags(android.app.Flags.FLAG_MODES_API)
+    public void testAddAutomaticZenRule_typeManagedCannotBeUsedByRegularApps() throws Exception {
+        mService.setCallerIsNormalPackage();
+        mService.setZenHelper(mock(ZenModeHelper.class));
+        when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
+                .thenReturn(true);
+
+        AutomaticZenRule rule = new AutomaticZenRule.Builder("rule", Uri.parse("uri"))
+                .setType(AutomaticZenRule.TYPE_MANAGED)
+                .setOwner(new ComponentName("pkg", "cls"))
+                .build();
+        when(mDevicePolicyManager.isActiveDeviceOwner(anyInt())).thenReturn(false);
+
+        assertThrows(IllegalArgumentException.class,
+                () -> mBinderService.addAutomaticZenRule(rule, "pkg"));
     }
 
     @Test
@@ -10038,7 +10126,7 @@
     }
 
     @Test
-    public void testHandleOnPackageRemoved_ClearsHistory() throws RemoteException {
+    public void testHandleOnPackageRemoved_ClearsHistory() throws Exception {
         // Enables Notification History setting
         setUpPrefsForHistory(mUid, true /* =enabled */);
 
@@ -11447,6 +11535,67 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(FLAG_REDACT_SENSITIVE_NOTIFICATIONS_FROM_UNTRUSTED_LISTENERS)
+    public void testGetActiveNotificationsFromListener_redactNotification() throws Exception {
+        NotificationRecord r =
+                generateNotificationRecord(mTestNotificationChannel, 0, 0);
+        mService.addNotification(r);
+        when(mListeners.isUidTrusted(anyInt())).thenReturn(false);
+        when(mListeners.hasSensitiveContent(any())).thenReturn(true);
+        StatusBarNotification redacted = generateRedactedSbn(mTestNotificationChannel, 1, 1);
+        when(mListeners.redactStatusBarNotification(any())).thenReturn(redacted);
+        ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class);
+        info.userid = 0;
+        when(info.isSameUser(anyInt())).thenReturn(true);
+        when(info.enabledAndUserMatches(anyInt())).thenReturn(true);
+        when(mListeners.checkServiceTokenLocked(any())).thenReturn(info);
+        List<StatusBarNotification> notifications = mBinderService
+                .getActiveNotificationsFromListener(mock(INotificationListener.class), null, -1)
+                .getList();
+
+        boolean foundRedactedSbn = false;
+        for (StatusBarNotification sbn: notifications) {
+            String text = sbn.getNotification().extras.getCharSequence(EXTRA_TEXT).toString();
+            if (REDACTED_TEXT.equals(text)) {
+                foundRedactedSbn = true;
+                break;
+            }
+        }
+        assertTrue("expect to find a redacted notification", foundRedactedSbn);
+    }
+
+    @Test
+    @RequiresFlagsEnabled(FLAG_REDACT_SENSITIVE_NOTIFICATIONS_FROM_UNTRUSTED_LISTENERS)
+    public void testGetSnoozedNotificationsFromListener_redactNotification() throws Exception {
+        NotificationRecord r =
+                generateNotificationRecord(mTestNotificationChannel, 0, 0);
+        mService.addNotification(r);
+        mService.snoozeNotificationInt(r.getKey(), 1000, null, mListener);
+        when(mListeners.isUidTrusted(anyInt())).thenReturn(false);
+        when(mListeners.hasSensitiveContent(any())).thenReturn(true);
+        StatusBarNotification redacted = generateRedactedSbn(mTestNotificationChannel, 1, 1);
+        when(mListeners.redactStatusBarNotification(any())).thenReturn(redacted);
+        ManagedServices.ManagedServiceInfo info = mock(ManagedServices.ManagedServiceInfo.class);
+        info.userid = 0;
+        when(info.isSameUser(anyInt())).thenReturn(true);
+        when(info.enabledAndUserMatches(anyInt())).thenReturn(true);
+        when(mListeners.checkServiceTokenLocked(any())).thenReturn(info);
+        List<StatusBarNotification> notifications = mBinderService
+                .getSnoozedNotificationsFromListener(mock(INotificationListener.class), -1)
+                .getList();
+
+        boolean foundRedactedSbn = false;
+        for (StatusBarNotification sbn: notifications) {
+            String text = sbn.getNotification().extras.getCharSequence(EXTRA_TEXT).toString();
+            if (REDACTED_TEXT.equals(text)) {
+                foundRedactedSbn = true;
+                break;
+            }
+        }
+        assertTrue("expect to find a redacted notification", foundRedactedSbn);
+    }
+
+    @Test
     public void testUngroupingOngoingAutoSummary() throws Exception {
         NotificationRecord nr0 =
                 generateNotificationRecord(mTestNotificationChannel, 0);
@@ -13157,6 +13306,34 @@
     }
 
     @Test
+    @EnableFlags(android.app.Flags.FLAG_MODES_API)
+    public void setDeviceEffectsApplier_succeeds() throws Exception {
+        initNMS(SystemService.PHASE_SYSTEM_SERVICES_READY);
+
+        mInternalService.setDeviceEffectsApplier(mock(DeviceEffectsApplier.class));
+        // No exception!
+    }
+
+    @Test
+    @EnableFlags(android.app.Flags.FLAG_MODES_API)
+    public void setDeviceEffectsApplier_tooLate_throws() throws Exception {
+        initNMS(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
+
+        assertThrows(IllegalStateException.class, () ->
+                mInternalService.setDeviceEffectsApplier(mock(DeviceEffectsApplier.class)));
+    }
+
+    @Test
+    @EnableFlags(android.app.Flags.FLAG_MODES_API)
+    public void setDeviceEffectsApplier_calledTwice_throws() throws Exception {
+        initNMS(SystemService.PHASE_SYSTEM_SERVICES_READY);
+
+        mInternalService.setDeviceEffectsApplier(mock(DeviceEffectsApplier.class));
+        assertThrows(IllegalStateException.class, () ->
+                mInternalService.setDeviceEffectsApplier(mock(DeviceEffectsApplier.class)));
+    }
+
+    @Test
     @EnableCompatChanges(NotificationManagerService.MANAGE_GLOBAL_ZEN_VIA_IMPLICIT_RULES)
     public void setNotificationPolicy_mappedToImplicitRule() throws RemoteException {
         mSetFlagsRule.enableFlags(android.app.Flags.FLAG_MODES_API);
@@ -13185,7 +13362,7 @@
         NotificationManager.Policy policy = new NotificationManager.Policy(0, 0, 0);
         mBinderService.setNotificationPolicy("package", policy);
 
-        verify(zenModeHelper).setNotificationPolicy(eq(policy), anyInt(), anyBoolean());
+        verify(zenModeHelper).setNotificationPolicy(eq(policy), anyInt(), anyInt());
     }
 
     @Test
@@ -13207,7 +13384,7 @@
         NotificationManager.Policy policy = new NotificationManager.Policy(0, 0, 0);
         mBinderService.setNotificationPolicy("package", policy);
 
-        verify(zenModeHelper).setNotificationPolicy(eq(policy), anyInt(), anyBoolean());
+        verify(zenModeHelper).setNotificationPolicy(eq(policy), anyInt(), anyInt());
     }
 
     @Test
@@ -13223,7 +13400,7 @@
         NotificationManager.Policy policy = new NotificationManager.Policy(0, 0, 0);
         mBinderService.setNotificationPolicy("package", policy);
 
-        verify(zenModeHelper).setNotificationPolicy(eq(policy), anyInt(), anyBoolean());
+        verify(zenModeHelper).setNotificationPolicy(eq(policy), anyInt(), anyInt());
     }
 
     @Test
@@ -13271,7 +13448,8 @@
         mBinderService.setInterruptionFilter("package", INTERRUPTION_FILTER_PRIORITY);
 
         verify(zenModeHelper).setManualZenMode(eq(ZEN_MODE_IMPORTANT_INTERRUPTIONS), eq(null),
-                eq("package"), anyString(), anyInt(), anyBoolean());
+                eq(ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI), anyString(), eq("package"),
+                anyInt());
     }
 
     @Test
@@ -13280,6 +13458,7 @@
         mSetFlagsRule.enableFlags(android.app.Flags.FLAG_MODES_API);
         ZenModeHelper zenModeHelper = mock(ZenModeHelper.class);
         mService.mZenModeHelper = zenModeHelper;
+        mService.setCallerIsNormalPackage();
         when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
                 .thenReturn(true);
         when(mCompanionMgr.getAssociations(anyString(), anyInt()))
@@ -13292,7 +13471,7 @@
         mBinderService.setInterruptionFilter("package", INTERRUPTION_FILTER_PRIORITY);
 
         verify(zenModeHelper).setManualZenMode(eq(ZEN_MODE_IMPORTANT_INTERRUPTIONS), eq(null),
-                eq("package"), anyString(), anyInt(), anyBoolean());
+                eq(ZenModeConfig.UPDATE_ORIGIN_APP), anyString(), eq("package"), anyInt());
     }
 
     @Test
@@ -13309,6 +13488,175 @@
         assertThat(n.flags & FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY).isEqualTo(0);
     }
 
+    @Test
+    public void cancelNotificationsFromListener_rapidClear_oldNew_cancelOne()
+            throws RemoteException {
+        mSetFlagsRule.enableFlags(android.view.contentprotection.flags.Flags
+                .FLAG_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER_APP_OP_ENABLED);
+
+        // Create recent notification.
+        final NotificationRecord nr1 = generateNotificationRecord(mTestNotificationChannel,
+                System.currentTimeMillis());
+        mService.addNotification(nr1);
+
+        // Create old notification.
+        final NotificationRecord nr2 = generateNotificationRecord(mTestNotificationChannel, 0);
+        mService.addNotification(nr2);
+
+        // Cancel specific notifications via listener.
+        String[] keys = {nr1.getSbn().getKey(), nr2.getSbn().getKey()};
+        mService.getBinderService().cancelNotificationsFromListener(null, keys);
+        waitForIdle();
+
+        // Notifications should not be active anymore.
+        StatusBarNotification[] notifications = mBinderService.getActiveNotifications(PKG);
+        assertThat(notifications).isEmpty();
+        assertEquals(0, mService.getNotificationRecordCount());
+        // Ensure cancel event is logged.
+        verify(mAppOpsManager).noteOpNoThrow(
+                AppOpsManager.OP_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER, mUid, PKG, null, null);
+    }
+
+    @Test
+    public void cancelNotificationsFromListener_rapidClear_old_cancelOne() throws RemoteException {
+        mSetFlagsRule.enableFlags(android.view.contentprotection.flags.Flags
+                .FLAG_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER_APP_OP_ENABLED);
+
+        // Create old notifications.
+        final NotificationRecord nr1 = generateNotificationRecord(mTestNotificationChannel, 0);
+        mService.addNotification(nr1);
+
+        final NotificationRecord nr2 = generateNotificationRecord(mTestNotificationChannel, 0);
+        mService.addNotification(nr2);
+
+        // Cancel specific notifications via listener.
+        String[] keys = {nr1.getSbn().getKey(), nr2.getSbn().getKey()};
+        mService.getBinderService().cancelNotificationsFromListener(null, keys);
+        waitForIdle();
+
+        // Notifications should not be active anymore.
+        StatusBarNotification[] notifications = mBinderService.getActiveNotifications(PKG);
+        assertThat(notifications).isEmpty();
+        assertEquals(0, mService.getNotificationRecordCount());
+        // Ensure cancel event is not logged.
+        verify(mAppOpsManager, never()).noteOpNoThrow(
+                eq(AppOpsManager.OP_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER), anyInt(), anyString(),
+                any(), any());
+    }
+
+    @Test
+    public void cancelNotificationsFromListener_rapidClear_oldNew_cancelOne_flagDisabled()
+            throws RemoteException {
+        mSetFlagsRule.disableFlags(android.view.contentprotection.flags.Flags
+                .FLAG_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER_APP_OP_ENABLED);
+
+        // Create recent notification.
+        final NotificationRecord nr1 = generateNotificationRecord(mTestNotificationChannel,
+                System.currentTimeMillis());
+        mService.addNotification(nr1);
+
+        // Create old notification.
+        final NotificationRecord nr2 = generateNotificationRecord(mTestNotificationChannel, 0);
+        mService.addNotification(nr2);
+
+        // Cancel specific notifications via listener.
+        String[] keys = {nr1.getSbn().getKey(), nr2.getSbn().getKey()};
+        mService.getBinderService().cancelNotificationsFromListener(null, keys);
+        waitForIdle();
+
+        // Notifications should not be active anymore.
+        StatusBarNotification[] notifications = mBinderService.getActiveNotifications(PKG);
+        assertThat(notifications).isEmpty();
+        assertEquals(0, mService.getNotificationRecordCount());
+        // Ensure cancel event is not logged due to flag being disabled.
+        verify(mAppOpsManager, never()).noteOpNoThrow(
+                eq(AppOpsManager.OP_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER), anyInt(), anyString(),
+                any(), any());
+    }
+
+    @Test
+    public void cancelNotificationsFromListener_rapidClear_oldNew_cancelAll()
+            throws RemoteException {
+        mSetFlagsRule.enableFlags(android.view.contentprotection.flags.Flags
+                .FLAG_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER_APP_OP_ENABLED);
+
+        // Create recent notification.
+        final NotificationRecord nr1 = generateNotificationRecord(mTestNotificationChannel,
+                System.currentTimeMillis());
+        mService.addNotification(nr1);
+
+        // Create old notification.
+        final NotificationRecord nr2 = generateNotificationRecord(mTestNotificationChannel, 0);
+        mService.addNotification(nr2);
+
+        // Cancel all notifications via listener.
+        mService.getBinderService().cancelNotificationsFromListener(null, null);
+        waitForIdle();
+
+        // Notifications should not be active anymore.
+        StatusBarNotification[] notifications = mBinderService.getActiveNotifications(PKG);
+        assertThat(notifications).isEmpty();
+        assertEquals(0, mService.getNotificationRecordCount());
+        // Ensure cancel event is logged.
+        verify(mAppOpsManager).noteOpNoThrow(
+                AppOpsManager.OP_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER, mUid, PKG, null, null);
+    }
+
+    @Test
+    public void cancelNotificationsFromListener_rapidClear_old_cancelAll() throws RemoteException {
+        mSetFlagsRule.enableFlags(android.view.contentprotection.flags.Flags
+                .FLAG_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER_APP_OP_ENABLED);
+
+        // Create old notifications.
+        final NotificationRecord nr1 = generateNotificationRecord(mTestNotificationChannel, 0);
+        mService.addNotification(nr1);
+
+        final NotificationRecord nr2 = generateNotificationRecord(mTestNotificationChannel, 0);
+        mService.addNotification(nr2);
+
+        // Cancel all notifications via listener.
+        mService.getBinderService().cancelNotificationsFromListener(null, null);
+        waitForIdle();
+
+        // Notifications should not be active anymore.
+        StatusBarNotification[] notifications = mBinderService.getActiveNotifications(PKG);
+        assertThat(notifications).isEmpty();
+        assertEquals(0, mService.getNotificationRecordCount());
+        // Ensure cancel event is not logged.
+        verify(mAppOpsManager, never()).noteOpNoThrow(
+                eq(AppOpsManager.OP_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER), anyInt(), anyString(),
+                any(), any());
+    }
+
+    @Test
+    public void cancelNotificationsFromListener_rapidClear_oldNew_cancelAll_flagDisabled()
+            throws RemoteException {
+        mSetFlagsRule.disableFlags(android.view.contentprotection.flags.Flags
+                .FLAG_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER_APP_OP_ENABLED);
+
+        // Create recent notification.
+        final NotificationRecord nr1 = generateNotificationRecord(mTestNotificationChannel,
+                System.currentTimeMillis());
+        mService.addNotification(nr1);
+
+        // Create old notification.
+        final NotificationRecord nr2 = generateNotificationRecord(mTestNotificationChannel, 0);
+        mService.addNotification(nr2);
+
+        // Cancel all notifications via listener.
+        mService.getBinderService().cancelNotificationsFromListener(null, null);
+        waitForIdle();
+
+        // Notifications should not be active anymore.
+        StatusBarNotification[] notifications = mBinderService.getActiveNotifications(PKG);
+        assertThat(notifications).isEmpty();
+        assertEquals(0, mService.getNotificationRecordCount());
+        // Ensure cancel event is not logged due to flag being disabled.
+        verify(mAppOpsManager, never()).noteOpNoThrow(
+                eq(AppOpsManager.OP_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER), anyInt(), anyString(),
+                any(), any());
+    }
+
     private NotificationRecord createAndPostNotification(Notification.Builder nb, String testName)
             throws RemoteException {
         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, testName, mUid, 0,
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 fe21103..5ddac03 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -67,7 +67,6 @@
 import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
@@ -2370,7 +2369,7 @@
         mHelper.createNotificationChannel(PKG_N_MR1, uid, channel, true, false,
                 uid, false);
         assertFalse(mHelper.areChannelsBypassingDnd());
-        verify(mMockZenModeHelper, never()).setNotificationPolicy(any(), anyInt(), anyBoolean());
+        verify(mMockZenModeHelper, never()).setNotificationPolicy(any(), anyInt(), anyInt());
         resetZenModeHelper();
 
         // create notification channel that can bypass dnd
@@ -2380,18 +2379,18 @@
         mHelper.createNotificationChannel(PKG_N_MR1, uid, channel2, true, true,
                 uid, false);
         assertTrue(mHelper.areChannelsBypassingDnd());
-        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyBoolean());
+        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyInt());
         resetZenModeHelper();
 
         // delete channels
         mHelper.deleteNotificationChannel(PKG_N_MR1, uid, channel.getId(), uid, false);
         assertTrue(mHelper.areChannelsBypassingDnd()); // channel2 can still bypass DND
-        verify(mMockZenModeHelper, never()).setNotificationPolicy(any(), anyInt(), anyBoolean());
+        verify(mMockZenModeHelper, never()).setNotificationPolicy(any(), anyInt(), anyInt());
         resetZenModeHelper();
 
         mHelper.deleteNotificationChannel(PKG_N_MR1, uid, channel2.getId(), uid, false);
         assertFalse(mHelper.areChannelsBypassingDnd());
-        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyBoolean());
+        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyInt());
         resetZenModeHelper();
     }
 
@@ -2407,7 +2406,7 @@
         mHelper.createNotificationChannel(PKG_N_MR1, uid, channel, true, false,
                 uid, false);
         assertFalse(mHelper.areChannelsBypassingDnd());
-        verify(mMockZenModeHelper, never()).setNotificationPolicy(any(), anyInt(), anyBoolean());
+        verify(mMockZenModeHelper, never()).setNotificationPolicy(any(), anyInt(), anyInt());
         resetZenModeHelper();
 
         // Recreate a channel & now the app has dnd access granted and can set the bypass dnd field
@@ -2417,7 +2416,7 @@
                 uid, false);
 
         assertTrue(mHelper.areChannelsBypassingDnd());
-        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyBoolean());
+        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyInt());
         resetZenModeHelper();
     }
 
@@ -2433,7 +2432,7 @@
         mHelper.createNotificationChannel(PKG_N_MR1, uid, channel, true, false,
                 uid, false);
         assertFalse(mHelper.areChannelsBypassingDnd());
-        verify(mMockZenModeHelper, never()).setNotificationPolicy(any(), anyInt(), anyBoolean());
+        verify(mMockZenModeHelper, never()).setNotificationPolicy(any(), anyInt(), anyInt());
         resetZenModeHelper();
 
         // create notification channel that can bypass dnd, using local app level settings
@@ -2443,18 +2442,18 @@
         mHelper.createNotificationChannel(PKG_N_MR1, uid, channel2, true, true,
                 uid, false);
         assertTrue(mHelper.areChannelsBypassingDnd());
-        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyBoolean());
+        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyInt());
         resetZenModeHelper();
 
         // delete channels
         mHelper.deleteNotificationChannel(PKG_N_MR1, uid, channel.getId(), uid, false);
         assertTrue(mHelper.areChannelsBypassingDnd()); // channel2 can still bypass DND
-        verify(mMockZenModeHelper, never()).setNotificationPolicy(any(), anyInt(), anyBoolean());
+        verify(mMockZenModeHelper, never()).setNotificationPolicy(any(), anyInt(), anyInt());
         resetZenModeHelper();
 
         mHelper.deleteNotificationChannel(PKG_N_MR1, uid, channel2.getId(), uid, false);
         assertFalse(mHelper.areChannelsBypassingDnd());
-        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyBoolean());
+        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyInt());
         resetZenModeHelper();
     }
 
@@ -2481,8 +2480,7 @@
         mHelper.createNotificationChannel(PKG_N_MR1, uid, channel2, true, true,
                 uid, false);
         assertFalse(mHelper.areChannelsBypassingDnd());
-        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(),
-                anyInt(), anyBoolean());
+        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyInt());
         resetZenModeHelper();
     }
 
@@ -2504,7 +2502,7 @@
         mHelper.createNotificationChannel(PKG_N_MR1, uid, channel2, true, true,
                 uid, false);
         assertFalse(mHelper.areChannelsBypassingDnd());
-        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyBoolean());
+        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyInt());
         resetZenModeHelper();
     }
 
@@ -2526,7 +2524,7 @@
         mHelper.createNotificationChannel(PKG_N_MR1, uid, channel2, true, true,
                 uid, false);
         assertFalse(mHelper.areChannelsBypassingDnd());
-        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyBoolean());
+        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyInt());
         resetZenModeHelper();
     }
 
@@ -2542,7 +2540,7 @@
         mHelper.createNotificationChannel(PKG_N_MR1, uid, channel, true, false,
                 uid, false);
         assertFalse(mHelper.areChannelsBypassingDnd());
-        verify(mMockZenModeHelper, never()).setNotificationPolicy(any(), anyInt(), anyBoolean());
+        verify(mMockZenModeHelper, never()).setNotificationPolicy(any(), anyInt(), anyInt());
         resetZenModeHelper();
 
         // update channel so it CAN bypass dnd:
@@ -2550,7 +2548,7 @@
         channel.setBypassDnd(true);
         mHelper.updateNotificationChannel(PKG_N_MR1, uid, channel, true, SYSTEM_UID, true);
         assertTrue(mHelper.areChannelsBypassingDnd());
-        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyBoolean());
+        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyInt());
         resetZenModeHelper();
 
         // update channel so it can't bypass dnd:
@@ -2558,7 +2556,7 @@
         channel.setBypassDnd(false);
         mHelper.updateNotificationChannel(PKG_N_MR1, uid, channel, true, SYSTEM_UID, true);
         assertFalse(mHelper.areChannelsBypassingDnd());
-        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyBoolean());
+        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyInt());
         resetZenModeHelper();
     }
 
@@ -2571,7 +2569,7 @@
         when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
         mHelper.syncChannelsBypassingDnd();
         assertFalse(mHelper.areChannelsBypassingDnd());
-        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyBoolean());
+        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyInt());
         resetZenModeHelper();
     }
 
@@ -2581,7 +2579,7 @@
         mTestNotificationPolicy = new NotificationManager.Policy(0, 0, 0, 0, 0, 0);
         when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
         assertFalse(mHelper.areChannelsBypassingDnd());
-        verify(mMockZenModeHelper, never()).setNotificationPolicy(any(), anyInt(), anyBoolean());
+        verify(mMockZenModeHelper, never()).setNotificationPolicy(any(), anyInt(), anyInt());
         resetZenModeHelper();
     }
 
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index ef6fced..1aea56c 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -45,6 +45,12 @@
 import static android.provider.Settings.Global.ZEN_MODE_OFF;
 import static android.service.notification.Condition.STATE_FALSE;
 import static android.service.notification.Condition.STATE_TRUE;
+import static android.service.notification.ZenModeConfig.UPDATE_ORIGIN_APP;
+import static android.service.notification.ZenModeConfig.UPDATE_ORIGIN_INIT;
+import static android.service.notification.ZenModeConfig.UPDATE_ORIGIN_INIT_USER;
+import static android.service.notification.ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI;
+import static android.service.notification.ZenModeConfig.UPDATE_ORIGIN_UNKNOWN;
+import static android.service.notification.ZenModeConfig.UPDATE_ORIGIN_USER;
 import static android.service.notification.ZenPolicy.PEOPLE_TYPE_CONTACTS;
 import static android.service.notification.ZenPolicy.PEOPLE_TYPE_STARRED;
 
@@ -53,9 +59,6 @@
 import static com.android.os.dnd.DNDProtoEnums.ROOT_CONFIG;
 import static com.android.os.dnd.DNDProtoEnums.STATE_ALLOW;
 import static com.android.os.dnd.DNDProtoEnums.STATE_DISALLOW;
-import static com.android.server.notification.ZenModeHelper.FROM_APP;
-import static com.android.server.notification.ZenModeHelper.FROM_SYSTEM_OR_SYSTEMUI;
-import static com.android.server.notification.ZenModeHelper.FROM_USER;
 import static com.android.server.notification.ZenModeHelper.RULE_LIMIT_PER_PACKAGE;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -77,6 +80,7 @@
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.notNull;
 import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -262,10 +266,12 @@
                 .thenReturn(CUSTOM_PKG_UID);
         when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(
                 new String[] {pkg});
-        ApplicationInfo mockAppInfo = mock(ApplicationInfo.class);
-        when(mockAppInfo.loadLabel(any())).thenReturn(CUSTOM_APP_LABEL);
+
+        ApplicationInfo appInfoSpy = spy(new ApplicationInfo());
+        appInfoSpy.icon = ICON_RES_ID;
+        when(appInfoSpy.loadLabel(any())).thenReturn(CUSTOM_APP_LABEL);
         when(mPackageManager.getApplicationInfo(eq(CUSTOM_PKG_NAME), anyInt()))
-                .thenReturn(mockAppInfo);
+                .thenReturn(appInfoSpy);
         mZenModeHelper.mPm = mPackageManager;
 
         mZenModeEventLogger.reset();
@@ -305,8 +311,8 @@
         mZenModeHelper.writeXml(serializer, false, version, UserHandle.USER_ALL);
         serializer.endDocument();
         serializer.flush();
-        mZenModeHelper.setConfig(new ZenModeConfig(), null, "writing xml", Process.SYSTEM_UID,
-                true);
+        mZenModeHelper.setConfig(new ZenModeConfig(), null, UPDATE_ORIGIN_INIT, "writing xml",
+                Process.SYSTEM_UID);
         return baos;
     }
 
@@ -321,7 +327,8 @@
         serializer.flush();
         ZenModeConfig newConfig = new ZenModeConfig();
         newConfig.user = userId;
-        mZenModeHelper.setConfig(newConfig, null, "writing xml", Process.SYSTEM_UID, true);
+        mZenModeHelper.setConfig(newConfig, null, UPDATE_ORIGIN_INIT, "writing xml",
+                Process.SYSTEM_UID);
         return baos;
     }
 
@@ -838,7 +845,7 @@
         mZenModeHelper.mConfig = null; // will evaluate config to zen mode off
         for (int i = 0; i < 3; i++) {
             // if zen doesn't change, zen should not reapply itself to the ringer
-            mZenModeHelper.evaluateZenModeLocked("test", true);
+            mZenModeHelper.evaluateZenModeLocked(UPDATE_ORIGIN_UNKNOWN, "test", true);
         }
         verify(mAudioManager, never()).setRingerModeInternal(AudioManager.RINGER_MODE_NORMAL,
                 mZenModeHelper.TAG);
@@ -865,7 +872,7 @@
         mZenModeHelper.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
         for (int i = 0; i < 3; i++) {
             // if zen doesn't change, zen should not reapply itself to the ringer
-            mZenModeHelper.evaluateZenModeLocked("test", true);
+            mZenModeHelper.evaluateZenModeLocked(UPDATE_ORIGIN_UNKNOWN, "test", true);
         }
         verify(mAudioManager, never()).setRingerModeInternal(AudioManager.RINGER_MODE_NORMAL,
                 mZenModeHelper.TAG);
@@ -892,7 +899,7 @@
         mZenModeHelper.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
         for (int i = 0; i < 3; i++) {
             // if zen doesn't change, zen should not reapply itself to the ringer
-            mZenModeHelper.evaluateZenModeLocked("test", true);
+            mZenModeHelper.evaluateZenModeLocked(UPDATE_ORIGIN_UNKNOWN, "test", true);
         }
         verify(mAudioManager, never()).setRingerModeInternal(AudioManager.RINGER_MODE_NORMAL,
                 mZenModeHelper.TAG);
@@ -905,8 +912,8 @@
         setupZenConfig();
 
         // Turn manual zen mode on
-        mZenModeHelper.setManualZenMode(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, null,
-                "test", CUSTOM_PKG_UID, false);
+        mZenModeHelper.setManualZenMode(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, UPDATE_ORIGIN_APP,
+                null, "test", CUSTOM_PKG_UID);
 
         // audio manager shouldn't do anything until the handler processes its messages
         verify(mAudioManager, never()).updateRingerModeAffectedStreamsInternal();
@@ -1185,7 +1192,8 @@
         List<StatsEvent> events = new LinkedList<>();
 
         mZenModeHelper.pullRules(events);
-        mZenModeHelper.removeAutomaticZenRule(CUSTOM_RULE_ID, "test", CUSTOM_PKG_UID, false);
+        mZenModeHelper.removeAutomaticZenRule(CUSTOM_RULE_ID, UPDATE_ORIGIN_APP, "test",
+                CUSTOM_PKG_UID);
         assertTrue(-1
                 == mZenModeHelper.mRulesUidCache.getOrDefault(CUSTOM_PKG_NAME + "|" + 0, -1));
     }
@@ -1240,12 +1248,14 @@
         config10.user = 10;
         config10.allowAlarms = true;
         config10.allowMedia = true;
-        mZenModeHelper.setConfig(config10, null, "writeXml", Process.SYSTEM_UID, true);
+        mZenModeHelper.setConfig(config10, null, UPDATE_ORIGIN_INIT, "writeXml",
+                Process.SYSTEM_UID);
         ZenModeConfig config11 = mZenModeHelper.mConfig.copy();
         config11.user = 11;
         config11.allowAlarms = false;
         config11.allowMedia = false;
-        mZenModeHelper.setConfig(config11, null, "writeXml", Process.SYSTEM_UID, true);
+        mZenModeHelper.setConfig(config11, null, UPDATE_ORIGIN_INIT, "writeXml",
+                Process.SYSTEM_UID);
 
         // Backup user 10 and reset values.
         ByteArrayOutputStream baos = writeXmlAndPurgeForUser(null, 10);
@@ -1849,8 +1859,8 @@
                     NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
             // We need the package name to be something that's not "android" so there aren't any
             // existing rules under that package.
-            String id = mZenModeHelper.addAutomaticZenRule("pkgname", zenRule, "test",
-                    CUSTOM_PKG_UID, FROM_APP);
+            String id = mZenModeHelper.addAutomaticZenRule("pkgname", zenRule, UPDATE_ORIGIN_APP,
+                    "test", CUSTOM_PKG_UID);
             assertNotNull(id);
         }
         try {
@@ -1860,8 +1870,8 @@
                     ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
                     new ZenPolicy.Builder().build(),
                     NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
-            String id = mZenModeHelper.addAutomaticZenRule("pkgname", zenRule, "test",
-                    CUSTOM_PKG_UID, FROM_APP);
+            String id = mZenModeHelper.addAutomaticZenRule("pkgname", zenRule, UPDATE_ORIGIN_APP,
+                    "test", CUSTOM_PKG_UID);
             fail("allowed too many rules to be created");
         } catch (IllegalArgumentException e) {
             // yay
@@ -1881,8 +1891,8 @@
                     ZenModeConfig.toScheduleConditionId(si),
                     new ZenPolicy.Builder().build(),
                     NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
-            String id = mZenModeHelper.addAutomaticZenRule("pkgname", zenRule, "test",
-                    CUSTOM_PKG_UID, FROM_APP);
+            String id = mZenModeHelper.addAutomaticZenRule("pkgname", zenRule, UPDATE_ORIGIN_APP,
+                    "test", CUSTOM_PKG_UID);
             assertNotNull(id);
         }
         try {
@@ -1892,8 +1902,8 @@
                     ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
                     new ZenPolicy.Builder().build(),
                     NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
-            String id = mZenModeHelper.addAutomaticZenRule("pkgname", zenRule, "test",
-                    CUSTOM_PKG_UID, FROM_APP);
+            String id = mZenModeHelper.addAutomaticZenRule("pkgname", zenRule, UPDATE_ORIGIN_APP,
+                    "test", CUSTOM_PKG_UID);
             fail("allowed too many rules to be created");
         } catch (IllegalArgumentException e) {
             // yay
@@ -1913,8 +1923,8 @@
                     ZenModeConfig.toScheduleConditionId(si),
                     new ZenPolicy.Builder().build(),
                     NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
-            String id = mZenModeHelper.addAutomaticZenRule("pkgname", zenRule, "test",
-                    CUSTOM_PKG_UID, FROM_APP);
+            String id = mZenModeHelper.addAutomaticZenRule("pkgname", zenRule, UPDATE_ORIGIN_APP,
+                    "test", CUSTOM_PKG_UID);
             assertNotNull(id);
         }
         try {
@@ -1924,8 +1934,8 @@
                     ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
                     new ZenPolicy.Builder().build(),
                     NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
-            String id = mZenModeHelper.addAutomaticZenRule("pkgname", zenRule, "test",
-                    CUSTOM_PKG_UID, FROM_APP);
+            String id = mZenModeHelper.addAutomaticZenRule("pkgname", zenRule, UPDATE_ORIGIN_APP,
+                    "test", CUSTOM_PKG_UID);
             fail("allowed too many rules to be created");
         } catch (IllegalArgumentException e) {
             // yay
@@ -1940,8 +1950,8 @@
                 ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
                 new ZenPolicy.Builder().build(),
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
-        String id = mZenModeHelper.addAutomaticZenRule("android", zenRule, "test",
-                Process.SYSTEM_UID, FROM_SYSTEM_OR_SYSTEMUI);
+        String id = mZenModeHelper.addAutomaticZenRule("android", zenRule,
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID);
 
         assertTrue(id != null);
         ZenModeConfig.ZenRule ruleInConfig = mZenModeHelper.mConfig.automaticRules.get(id);
@@ -1961,8 +1971,8 @@
                 new ComponentName("android", "ScheduleConditionProvider"),
                 ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
-        String id = mZenModeHelper.addAutomaticZenRule("android", zenRule, "test",
-                Process.SYSTEM_UID, FROM_SYSTEM_OR_SYSTEMUI);
+        String id = mZenModeHelper.addAutomaticZenRule("android", zenRule,
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID);
 
         assertTrue(id != null);
         ZenModeConfig.ZenRule ruleInConfig = mZenModeHelper.mConfig.automaticRules.get(id);
@@ -1985,11 +1995,12 @@
                 new ZenPolicy.Builder().build(),
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
 
-        String id = mZenModeHelper.addAutomaticZenRule(null, zenRule, "test",
-                CUSTOM_PKG_UID, FROM_APP);
+        String id = mZenModeHelper.addAutomaticZenRule(null, zenRule, UPDATE_ORIGIN_APP, "test",
+                CUSTOM_PKG_UID);
         mZenModeHelper.setAutomaticZenRuleState(zenRule.getConditionId(),
                 new Condition(zenRule.getConditionId(), "", STATE_TRUE),
-                CUSTOM_PKG_UID, false);
+                UPDATE_ORIGIN_APP,
+                CUSTOM_PKG_UID);
 
         ZenModeConfig.ZenRule ruleInConfig = mZenModeHelper.mConfig.automaticRules.get(id);
         assertEquals(STATE_TRUE, ruleInConfig.condition.state);
@@ -2004,8 +2015,8 @@
                 new ZenPolicy.Builder().build(),
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
 
-        String id = mZenModeHelper.addAutomaticZenRule(null, zenRule, "test",
-                CUSTOM_PKG_UID, FROM_APP);
+        String id = mZenModeHelper.addAutomaticZenRule(null, zenRule, UPDATE_ORIGIN_APP, "test",
+                CUSTOM_PKG_UID);
 
         AutomaticZenRule zenRule2 = new AutomaticZenRule("NEW",
                 null,
@@ -2014,7 +2025,7 @@
                 new ZenPolicy.Builder().build(),
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
 
-        mZenModeHelper.updateAutomaticZenRule(id, zenRule2, "", CUSTOM_PKG_UID, FROM_APP);
+        mZenModeHelper.updateAutomaticZenRule(id, zenRule2, UPDATE_ORIGIN_APP, "", CUSTOM_PKG_UID);
 
         ZenModeConfig.ZenRule ruleInConfig = mZenModeHelper.mConfig.automaticRules.get(id);
         assertEquals("NEW", ruleInConfig.name);
@@ -2029,15 +2040,15 @@
                 new ZenPolicy.Builder().build(),
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
 
-        String id = mZenModeHelper.addAutomaticZenRule(null, zenRule, "test",
-                CUSTOM_PKG_UID, FROM_APP);
+        String id = mZenModeHelper.addAutomaticZenRule(null, zenRule, UPDATE_ORIGIN_APP, "test",
+                CUSTOM_PKG_UID);
 
         assertTrue(id != null);
         ZenModeConfig.ZenRule ruleInConfig = mZenModeHelper.mConfig.automaticRules.get(id);
         assertTrue(ruleInConfig != null);
         assertEquals(zenRule.getName(), ruleInConfig.name);
 
-        mZenModeHelper.removeAutomaticZenRule(id, "test", CUSTOM_PKG_UID, false);
+        mZenModeHelper.removeAutomaticZenRule(id, UPDATE_ORIGIN_APP, "test", CUSTOM_PKG_UID);
         assertNull(mZenModeHelper.mConfig.automaticRules.get(id));
     }
 
@@ -2049,16 +2060,16 @@
                 ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
                 new ZenPolicy.Builder().build(),
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
-        String id = mZenModeHelper.addAutomaticZenRule(null, zenRule, "test",
-                CUSTOM_PKG_UID, FROM_APP);
+        String id = mZenModeHelper.addAutomaticZenRule(null, zenRule, UPDATE_ORIGIN_APP, "test",
+                CUSTOM_PKG_UID);
 
         assertTrue(id != null);
         ZenModeConfig.ZenRule ruleInConfig = mZenModeHelper.mConfig.automaticRules.get(id);
         assertTrue(ruleInConfig != null);
         assertEquals(zenRule.getName(), ruleInConfig.name);
 
-        mZenModeHelper.removeAutomaticZenRules(mContext.getPackageName(), "test",
-                CUSTOM_PKG_UID, false);
+        mZenModeHelper.removeAutomaticZenRules(mContext.getPackageName(), UPDATE_ORIGIN_APP, "test",
+                CUSTOM_PKG_UID);
         assertNull(mZenModeHelper.mConfig.automaticRules.get(id));
     }
 
@@ -2073,17 +2084,18 @@
                 new ComponentName("android", "ScheduleConditionProvider"),
                 sharedUri,
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
-        String id = mZenModeHelper.addAutomaticZenRule("android", zenRule, "test",
-                Process.SYSTEM_UID, FROM_SYSTEM_OR_SYSTEMUI);
+        String id = mZenModeHelper.addAutomaticZenRule("android", zenRule,
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID);
         AutomaticZenRule zenRule2 = new AutomaticZenRule("name2",
                 new ComponentName("android", "ScheduleConditionProvider"),
                 sharedUri,
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
-        String id2 = mZenModeHelper.addAutomaticZenRule("android", zenRule2, "test",
-                Process.SYSTEM_UID, FROM_SYSTEM_OR_SYSTEMUI);
+        String id2 = mZenModeHelper.addAutomaticZenRule("android", zenRule2,
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID);
 
         Condition condition = new Condition(sharedUri, "", STATE_TRUE);
-        mZenModeHelper.setAutomaticZenRuleState(sharedUri, condition, Process.SYSTEM_UID, true);
+        mZenModeHelper.setAutomaticZenRuleState(sharedUri, condition,
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
 
         for (ZenModeConfig.ZenRule rule : mZenModeHelper.mConfig.automaticRules.values()) {
             if (rule.id.equals(id)) {
@@ -2097,7 +2109,8 @@
         }
 
         condition = new Condition(sharedUri, "", STATE_FALSE);
-        mZenModeHelper.setAutomaticZenRuleState(sharedUri, condition, Process.SYSTEM_UID, true);
+        mZenModeHelper.setAutomaticZenRuleState(sharedUri, condition,
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
 
         for (ZenModeConfig.ZenRule rule : mZenModeHelper.mConfig.automaticRules.values()) {
             if (rule.id.equals(id)) {
@@ -2133,7 +2146,7 @@
                         .setOwner(OWNER)
                         .setDeviceEffects(zde)
                         .build(),
-                "reasons", 0, FROM_APP);
+                UPDATE_ORIGIN_APP, "reasons", 0);
 
         AutomaticZenRule savedRule = mZenModeHelper.getAutomaticZenRule(ruleId);
         assertThat(savedRule.getDeviceEffects()).isEqualTo(
@@ -2167,7 +2180,7 @@
                         .setOwner(OWNER)
                         .setDeviceEffects(zde)
                         .build(),
-                "reasons", 0, FROM_SYSTEM_OR_SYSTEMUI);
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "reasons", 0);
 
         AutomaticZenRule savedRule = mZenModeHelper.getAutomaticZenRule(ruleId);
         assertThat(savedRule.getDeviceEffects()).isEqualTo(zde);
@@ -2195,7 +2208,8 @@
                         .setOwner(OWNER)
                         .setDeviceEffects(zde)
                         .build(),
-                "reasons", 0, FROM_USER);
+                UPDATE_ORIGIN_USER,
+                "reasons", 0);
 
         AutomaticZenRule savedRule = mZenModeHelper.getAutomaticZenRule(ruleId);
         assertThat(savedRule.getDeviceEffects()).isEqualTo(zde);
@@ -2212,7 +2226,7 @@
                         .setOwner(OWNER)
                         .setDeviceEffects(original)
                         .build(),
-                "reasons", 0, FROM_SYSTEM_OR_SYSTEMUI);
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "reasons", 0);
 
         ZenDeviceEffects updateFromApp = new ZenDeviceEffects.Builder()
                 .setShouldUseNightMode(true) // Good
@@ -2223,7 +2237,7 @@
                         .setOwner(OWNER)
                         .setDeviceEffects(updateFromApp)
                         .build(),
-                "reasons", 0, FROM_APP);
+                UPDATE_ORIGIN_APP, "reasons", 0);
 
         AutomaticZenRule savedRule = mZenModeHelper.getAutomaticZenRule(ruleId);
         assertThat(savedRule.getDeviceEffects()).isEqualTo(
@@ -2244,7 +2258,7 @@
                         .setOwner(OWNER)
                         .setDeviceEffects(original)
                         .build(),
-                "reasons", 0, FROM_SYSTEM_OR_SYSTEMUI);
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "reasons", 0);
 
         ZenDeviceEffects updateFromSystem = new ZenDeviceEffects.Builder()
                 .setShouldUseNightMode(true) // Good
@@ -2254,7 +2268,7 @@
                 new AutomaticZenRule.Builder("Rule", CONDITION_ID)
                         .setDeviceEffects(updateFromSystem)
                         .build(),
-                "reasons", 0, FROM_SYSTEM_OR_SYSTEMUI);
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "reasons", 0);
 
         AutomaticZenRule savedRule = mZenModeHelper.getAutomaticZenRule(ruleId);
         assertThat(savedRule.getDeviceEffects()).isEqualTo(updateFromSystem);
@@ -2271,7 +2285,7 @@
                         .setOwner(OWNER)
                         .setDeviceEffects(original)
                         .build(),
-                "reasons", 0, FROM_SYSTEM_OR_SYSTEMUI);
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "reasons", 0);
 
         ZenDeviceEffects updateFromUser = new ZenDeviceEffects.Builder()
                 .setShouldUseNightMode(true) // Good
@@ -2281,7 +2295,7 @@
                 new AutomaticZenRule.Builder("Rule", CONDITION_ID)
                         .setDeviceEffects(updateFromUser)
                         .build(),
-                "reasons", 0, FROM_USER);
+                UPDATE_ORIGIN_USER, "reasons", 0);
 
         AutomaticZenRule savedRule = mZenModeHelper.getAutomaticZenRule(ruleId);
         assertThat(savedRule.getDeviceEffects()).isEqualTo(updateFromUser);
@@ -2293,16 +2307,16 @@
         setupZenConfig();
 
         // note that caller=null because that's how it comes in from NMS.setZenMode
-        mZenModeHelper.setManualZenMode(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, null, "",
-                Process.SYSTEM_UID, true);
+        mZenModeHelper.setManualZenMode(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null,
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "", null, Process.SYSTEM_UID);
 
         // confirm that setting zen mode via setManualZenMode changed the zen mode correctly
         assertEquals(ZEN_MODE_IMPORTANT_INTERRUPTIONS, mZenModeHelper.mZenMode);
         assertEquals(true, mZenModeHelper.mConfig.manualRule.allowManualInvocation);
 
         // and also that it works to turn it back off again
-        mZenModeHelper.setManualZenMode(Global.ZEN_MODE_OFF, null, null, "",
-                Process.SYSTEM_UID, true);
+        mZenModeHelper.setManualZenMode(Global.ZEN_MODE_OFF, null, UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI,
+                "", null, Process.SYSTEM_UID);
 
         assertEquals(Global.ZEN_MODE_OFF, mZenModeHelper.mZenMode);
     }
@@ -2312,15 +2326,15 @@
         setupZenConfig();
 
         // note that caller=null because that's how it comes in from NMS.setZenMode
-        mZenModeHelper.setManualZenMode(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, null, "",
-                Process.SYSTEM_UID, true);
+        mZenModeHelper.setManualZenMode(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null,
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "", null, Process.SYSTEM_UID);
 
         // confirm that setting zen mode via setManualZenMode changed the zen mode correctly
         assertEquals(ZEN_MODE_IMPORTANT_INTERRUPTIONS, mZenModeHelper.mZenMode);
 
         // and also that it works to turn it back off again
-        mZenModeHelper.setManualZenMode(ZEN_MODE_OFF, null, null, "",
-                Process.SYSTEM_UID, true);
+        mZenModeHelper.setManualZenMode(ZEN_MODE_OFF, null, UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "",
+                null, Process.SYSTEM_UID);
 
         assertEquals(ZEN_MODE_OFF, mZenModeHelper.mZenMode);
     }
@@ -2332,13 +2346,13 @@
 
         // Turn zen mode on (to important_interruptions)
         // Need to additionally call the looper in order to finish the post-apply-config process
-        mZenModeHelper.setManualZenMode(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, null, "",
-                Process.SYSTEM_UID, true);
+        mZenModeHelper.setManualZenMode(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null,
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "", null, Process.SYSTEM_UID);
 
         // Now turn zen mode off, but via a different package UID -- this should get registered as
         // "not an action by the user" because some other app is changing zen mode
-        mZenModeHelper.setManualZenMode(ZEN_MODE_OFF, null, null, "", CUSTOM_PKG_UID,
-                false);
+        mZenModeHelper.setManualZenMode(ZEN_MODE_OFF, null, UPDATE_ORIGIN_APP, "", null,
+                CUSTOM_PKG_UID);
 
         // In total, this should be 2 loggable changes
         assertEquals(2, mZenModeEventLogger.numLoggedChanges());
@@ -2397,17 +2411,18 @@
                 null,
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
         String id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule,
-                "test", Process.SYSTEM_UID, FROM_SYSTEM_OR_SYSTEMUI);
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID);
 
         // Event 1: Mimic the rule coming on automatically by setting the Condition to STATE_TRUE
         mZenModeHelper.setAutomaticZenRuleState(id,
                 new Condition(zenRule.getConditionId(), "", STATE_TRUE),
-                Process.SYSTEM_UID, true);
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI,
+                Process.SYSTEM_UID);
 
         // Event 2: "User" turns off the automatic rule (sets it to not enabled)
         zenRule.setEnabled(false);
-        mZenModeHelper.updateAutomaticZenRule(id, zenRule, "", Process.SYSTEM_UID,
-                FROM_SYSTEM_OR_SYSTEMUI);
+        mZenModeHelper.updateAutomaticZenRule(id, zenRule, UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "",
+                Process.SYSTEM_UID);
 
         // Add a new system rule
         AutomaticZenRule systemRule = new AutomaticZenRule("systemRule",
@@ -2417,15 +2432,16 @@
                 null,
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
         String systemId = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), systemRule,
-                "test", Process.SYSTEM_UID, FROM_SYSTEM_OR_SYSTEMUI);
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID);
 
         // Event 3: turn on the system rule
         mZenModeHelper.setAutomaticZenRuleState(systemId,
                 new Condition(zenRule.getConditionId(), "", STATE_TRUE),
-                Process.SYSTEM_UID, true);
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
 
         // Event 4: "User" deletes the rule
-        mZenModeHelper.removeAutomaticZenRule(systemId, "", Process.SYSTEM_UID, true);
+        mZenModeHelper.removeAutomaticZenRule(systemId, UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "",
+                Process.SYSTEM_UID);
 
         // In total, this represents 4 events
         assertEquals(4, mZenModeEventLogger.numLoggedChanges());
@@ -2486,26 +2502,26 @@
         setupZenConfig();
 
         // First just turn zen mode on
-        mZenModeHelper.setManualZenMode(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, null, "",
-                Process.SYSTEM_UID, true);
+        mZenModeHelper.setManualZenMode(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null,
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "", null, Process.SYSTEM_UID);
 
         // Now change the policy slightly; want to confirm that this'll be reflected in the logs
         ZenModeConfig newConfig = mZenModeHelper.mConfig.copy();
         newConfig.allowAlarms = true;
         newConfig.allowRepeatCallers = false;
-        mZenModeHelper.setNotificationPolicy(newConfig.toNotificationPolicy(), Process.SYSTEM_UID,
-                true);
+        mZenModeHelper.setNotificationPolicy(newConfig.toNotificationPolicy(),
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
 
         // Turn zen mode off; we want to make sure policy changes do not get logged when zen mode
         // is off.
-        mZenModeHelper.setManualZenMode(ZEN_MODE_OFF, null, null, "",
-                Process.SYSTEM_UID, true);
+        mZenModeHelper.setManualZenMode(ZEN_MODE_OFF, null, UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "",
+                null, Process.SYSTEM_UID);
 
         // Change the policy again
         newConfig.allowMessages = false;
         newConfig.allowRepeatCallers = true;
-        mZenModeHelper.setNotificationPolicy(newConfig.toNotificationPolicy(), Process.SYSTEM_UID,
-                true);
+        mZenModeHelper.setNotificationPolicy(newConfig.toNotificationPolicy(),
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
 
         // Total events: we only expect ones for turning on, changing policy, and turning off
         assertEquals(3, mZenModeEventLogger.numLoggedChanges());
@@ -2548,8 +2564,8 @@
                 ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
                 null,
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
-        String id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule, "test",
-                Process.SYSTEM_UID, FROM_SYSTEM_OR_SYSTEMUI);
+        String id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule,
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID);
 
         // Rule 2, same as rule 1
         AutomaticZenRule zenRule2 = new AutomaticZenRule("name2",
@@ -2558,8 +2574,8 @@
                 ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
                 null,
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
-        String id2 = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule2, "test",
-                Process.SYSTEM_UID, FROM_SYSTEM_OR_SYSTEMUI);
+        String id2 = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule2,
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID);
 
         // Rule 3, has stricter settings than the default settings
         ZenModeConfig ruleConfig = mZenModeHelper.mConfig.copy();
@@ -2572,28 +2588,28 @@
                 ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
                 ruleConfig.toZenPolicy(),
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
-        String id3 = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule3, "test",
-                Process.SYSTEM_UID, FROM_SYSTEM_OR_SYSTEMUI);
+        String id3 = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule3,
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID);
 
         // First: turn on rule 1
         mZenModeHelper.setAutomaticZenRuleState(id,
                 new Condition(zenRule.getConditionId(), "", STATE_TRUE),
-                Process.SYSTEM_UID, true);
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI,  Process.SYSTEM_UID);
 
         // Second: turn on rule 2
         mZenModeHelper.setAutomaticZenRuleState(id2,
                 new Condition(zenRule2.getConditionId(), "", STATE_TRUE),
-                Process.SYSTEM_UID, true);
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI,  Process.SYSTEM_UID);
 
         // Third: turn on rule 3
         mZenModeHelper.setAutomaticZenRuleState(id3,
                 new Condition(zenRule3.getConditionId(), "", STATE_TRUE),
-                Process.SYSTEM_UID, true);
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI,  Process.SYSTEM_UID);
 
         // Fourth: Turn *off* rule 2
         mZenModeHelper.setAutomaticZenRuleState(id2,
                 new Condition(zenRule2.getConditionId(), "", STATE_FALSE),
-                Process.SYSTEM_UID, true);
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI,  Process.SYSTEM_UID);
 
         // This should result in a total of four events
         assertEquals(4, mZenModeEventLogger.numLoggedChanges());
@@ -2649,7 +2665,7 @@
         // Artificially turn zen mode "on". Re-evaluating zen mode should cause it to turn back off
         // given that we don't have any zen rules active.
         mZenModeHelper.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
-        mZenModeHelper.evaluateZenModeLocked("test", true);
+        mZenModeHelper.evaluateZenModeLocked(UPDATE_ORIGIN_UNKNOWN, "test", true);
 
         // Check that the change actually took: zen mode should be off now
         assertEquals(ZEN_MODE_OFF, mZenModeHelper.mZenMode);
@@ -2672,8 +2688,8 @@
                 ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
                 null,
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
-        String id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule, "test",
-                Process.SYSTEM_UID, FROM_SYSTEM_OR_SYSTEMUI);
+        String id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule,
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID);
 
         // Rule 2, same as rule 1 but owned by the system
         AutomaticZenRule zenRule2 = new AutomaticZenRule("name2",
@@ -2682,37 +2698,37 @@
                 ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
                 null,
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
-        String id2 = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule2, "test",
-                Process.SYSTEM_UID, FROM_SYSTEM_OR_SYSTEMUI);
+        String id2 = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule2,
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID);
 
         // Turn on rule 1; call looks like it's from the system. Because setting a condition is
         // typically an automatic (non-user-initiated) action, expect the calling UID to be
         // re-evaluated to the one associat.d with CUSTOM_PKG_NAME.
         mZenModeHelper.setAutomaticZenRuleState(id,
                 new Condition(zenRule.getConditionId(), "", STATE_TRUE),
-                Process.SYSTEM_UID, true);
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
 
         // Second: turn on rule 2. This is a system-owned rule and the UID should not be modified
         // (nor even looked up; the mock PackageManager won't handle "android" as input).
         mZenModeHelper.setAutomaticZenRuleState(id2,
                 new Condition(zenRule2.getConditionId(), "", STATE_TRUE),
-                Process.SYSTEM_UID, true);
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
 
         // Disable rule 1. Because this looks like a user action, the UID should not be modified
         // from the system-provided one.
         zenRule.setEnabled(false);
-        mZenModeHelper.updateAutomaticZenRule(id, zenRule, "", Process.SYSTEM_UID,
-                FROM_SYSTEM_OR_SYSTEMUI);
+        mZenModeHelper.updateAutomaticZenRule(id, zenRule, UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "",
+                Process.SYSTEM_UID);
 
         // Add a manual rule. Any manual rule changes should not get calling uids reassigned.
-        mZenModeHelper.setManualZenMode(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, null, "",
-                CUSTOM_PKG_UID, false);
+        mZenModeHelper.setManualZenMode(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, UPDATE_ORIGIN_APP,
+                "", null, CUSTOM_PKG_UID);
 
         // Change rule 2's condition, but from some other UID. Since it doesn't look like it's from
         // the system, we keep the UID info.
         mZenModeHelper.setAutomaticZenRuleState(id2,
                 new Condition(zenRule2.getConditionId(), "", STATE_FALSE),
-                12345, false);
+                UPDATE_ORIGIN_APP, 12345);
 
         // That was 5 events total
         assertEquals(5, mZenModeEventLogger.numLoggedChanges());
@@ -2767,26 +2783,26 @@
         // Turn on zen mode with a manual rule with an enabler set. This should *not* count
         // as a user action, and *should* get its UID reassigned.
         mZenModeHelper.setManualZenMode(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null,
-                CUSTOM_PKG_NAME, "", Process.SYSTEM_UID, true);
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "", CUSTOM_PKG_NAME, Process.SYSTEM_UID);
 
         // Now change apps bypassing to true
         ZenModeConfig newConfig = mZenModeHelper.mConfig.copy();
         newConfig.areChannelsBypassingDnd = true;
-        mZenModeHelper.setNotificationPolicy(newConfig.toNotificationPolicy(), Process.SYSTEM_UID,
-                true);
+        mZenModeHelper.setNotificationPolicy(newConfig.toNotificationPolicy(),
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
 
         // and then back to false, all without changing anything else
         newConfig.areChannelsBypassingDnd = false;
-        mZenModeHelper.setNotificationPolicy(newConfig.toNotificationPolicy(), Process.SYSTEM_UID,
-                true);
+        mZenModeHelper.setNotificationPolicy(newConfig.toNotificationPolicy(),
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
 
         // Turn off manual mode, call from a package: don't reset UID even though enabler is set
-        mZenModeHelper.setManualZenMode(ZEN_MODE_OFF, null,
-                CUSTOM_PKG_NAME, "", 12345, false);
+        mZenModeHelper.setManualZenMode(ZEN_MODE_OFF, null, UPDATE_ORIGIN_APP, "",
+                CUSTOM_PKG_NAME, 12345);
 
         // And likewise when turning it back on again
-        mZenModeHelper.setManualZenMode(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null,
-                CUSTOM_PKG_NAME, "", 12345, false);
+        mZenModeHelper.setManualZenMode(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, UPDATE_ORIGIN_APP,
+                "", CUSTOM_PKG_NAME, 12345);
 
         // These are 5 events in total.
         assertEquals(5, mZenModeEventLogger.numLoggedChanges());
@@ -2831,15 +2847,15 @@
         setupZenConfig();
 
         // First just turn zen mode on
-        mZenModeHelper.setManualZenMode(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, null, "",
-                Process.SYSTEM_UID, true);
+        mZenModeHelper.setManualZenMode(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null,
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "", null, Process.SYSTEM_UID);
 
         // Now change only the channels part of the policy; want to confirm that this'll be
         // reflected in the logs
         ZenModeConfig newConfig = mZenModeHelper.mConfig.copy();
         newConfig.allowPriorityChannels = false;
-        mZenModeHelper.setNotificationPolicy(newConfig.toNotificationPolicy(), Process.SYSTEM_UID,
-                true);
+        mZenModeHelper.setNotificationPolicy(newConfig.toNotificationPolicy(),
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
 
         // Total events: one for turning on, one for changing policy
         assertThat(mZenModeEventLogger.numLoggedChanges()).isEqualTo(2);
@@ -2881,13 +2897,13 @@
                 ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
                 null,
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
-        String id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule, "test",
-                Process.SYSTEM_UID, FROM_SYSTEM_OR_SYSTEMUI);
+        String id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule,
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID);
 
         // enable the rule
         mZenModeHelper.setAutomaticZenRuleState(id,
                 new Condition(zenRule.getConditionId(), "", STATE_TRUE),
-                Process.SYSTEM_UID, true);
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
 
         // inspect the consolidated policy. Based on setupZenConfig() values.
         assertFalse(mZenModeHelper.mConsolidatedPolicy.allowAlarms());
@@ -2924,13 +2940,13 @@
                 ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
                 customPolicy,
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
-        String id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule, "test",
-                Process.SYSTEM_UID, FROM_SYSTEM_OR_SYSTEMUI);
+        String id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule,
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID);
 
         // enable the rule; this will update the consolidated policy
         mZenModeHelper.setAutomaticZenRuleState(id,
                 new Condition(zenRule.getConditionId(), "", STATE_TRUE),
-                Process.SYSTEM_UID, true);
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
 
         // since this is the only active rule, the consolidated policy should match the custom
         // policy for every field specified, and take default values for unspecified things
@@ -2960,13 +2976,13 @@
                 ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
                 null,
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
-        String id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule, "test",
-                Process.SYSTEM_UID, FROM_SYSTEM_OR_SYSTEMUI);
+        String id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule,
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID);
 
         // enable rule 1
         mZenModeHelper.setAutomaticZenRuleState(id,
                 new Condition(zenRule.getConditionId(), "", STATE_TRUE),
-                Process.SYSTEM_UID, true);
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
 
         // custom policy for rule 2
         ZenPolicy customPolicy = new ZenPolicy.Builder()
@@ -2985,12 +3001,12 @@
                 customPolicy,
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
         String id2 = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule2,
-                "test", Process.SYSTEM_UID, FROM_SYSTEM_OR_SYSTEMUI);
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID);
 
         // enable rule 2; this will update the consolidated policy
         mZenModeHelper.setAutomaticZenRuleState(id2,
                 new Condition(zenRule2.getConditionId(), "", STATE_TRUE),
-                Process.SYSTEM_UID, true);
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
 
         // now both rules should be on, and the consolidated policy should reflect the most
         // restrictive option of each of the two
@@ -3022,13 +3038,13 @@
                 ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
                 customPolicy,
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
-        String id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule, "test",
-                Process.SYSTEM_UID, FROM_SYSTEM_OR_SYSTEMUI);
+        String id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule,
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID);
 
         // enable the rule; this will update the consolidated policy
         mZenModeHelper.setAutomaticZenRuleState(id,
                 new Condition(zenRule.getConditionId(), "", STATE_TRUE),
-                Process.SYSTEM_UID, true);
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
 
         // confirm that channels make it through
         assertTrue(mZenModeHelper.mConsolidatedPolicy.allowPriorityChannels());
@@ -3045,12 +3061,12 @@
                 strictPolicy,
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
         String id2 = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule2,
-                "test", Process.SYSTEM_UID, FROM_SYSTEM_OR_SYSTEMUI);
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID);
 
         // enable rule 2; this will update the consolidated policy
         mZenModeHelper.setAutomaticZenRuleState(id2,
                 new Condition(zenRule2.getConditionId(), "", STATE_TRUE),
-                Process.SYSTEM_UID, true);
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
 
         // rule 2 should override rule 1
         assertFalse(mZenModeHelper.mConsolidatedPolicy.allowPriorityChannels());
@@ -3121,7 +3137,7 @@
 
         ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule();
 
-        mZenModeHelper.populateZenRule(OWNER.getPackageName(), azr, rule, true, FROM_APP);
+        mZenModeHelper.populateZenRule(OWNER.getPackageName(), azr, rule, UPDATE_ORIGIN_APP, true);
 
         assertEquals(NAME, rule.name);
         assertEquals(OWNER, rule.component);
@@ -3149,7 +3165,7 @@
                 null,
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
         final String createdId = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(),
-                zenRule, "test", Process.SYSTEM_UID, FROM_SYSTEM_OR_SYSTEMUI);
+                zenRule, UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID);
 
         CountDownLatch latch = new CountDownLatch(1);
         final int[] actualStatus = new int[1];
@@ -3165,8 +3181,8 @@
         mZenModeHelper.addCallback(callback);
 
         zenRule.setEnabled(false);
-        mZenModeHelper.updateAutomaticZenRule(createdId, zenRule, "", Process.SYSTEM_UID,
-                FROM_SYSTEM_OR_SYSTEMUI);
+        mZenModeHelper.updateAutomaticZenRule(createdId, zenRule, UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI,
+                "", Process.SYSTEM_UID);
 
         assertTrue(latch.await(500, TimeUnit.MILLISECONDS));
         assertEquals(AUTOMATIC_RULE_STATUS_DISABLED, actualStatus[0]);
@@ -3184,7 +3200,7 @@
                 null,
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, false);
         final String createdId = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(),
-                zenRule, "test", Process.SYSTEM_UID, FROM_SYSTEM_OR_SYSTEMUI);
+                zenRule, UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID);
 
         CountDownLatch latch = new CountDownLatch(1);
         final int[] actualStatus = new int[1];
@@ -3200,8 +3216,8 @@
         mZenModeHelper.addCallback(callback);
 
         zenRule.setEnabled(true);
-        mZenModeHelper.updateAutomaticZenRule(createdId, zenRule, "", Process.SYSTEM_UID,
-                FROM_SYSTEM_OR_SYSTEMUI);
+        mZenModeHelper.updateAutomaticZenRule(createdId, zenRule, UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI,
+                "", Process.SYSTEM_UID);
 
         assertTrue(latch.await(500, TimeUnit.MILLISECONDS));
         assertEquals(AUTOMATIC_RULE_STATUS_ENABLED, actualStatus[0]);
@@ -3220,7 +3236,7 @@
                 null,
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
         final String createdId = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(),
-                zenRule, "test", Process.SYSTEM_UID, FROM_SYSTEM_OR_SYSTEMUI);
+                zenRule, UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID);
 
         CountDownLatch latch = new CountDownLatch(1);
         final int[] actualStatus = new int[1];
@@ -3237,7 +3253,7 @@
 
         mZenModeHelper.setAutomaticZenRuleState(createdId,
                 new Condition(zenRule.getConditionId(), "", STATE_TRUE),
-                Process.SYSTEM_UID, true);
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
 
         assertTrue(latch.await(500, TimeUnit.MILLISECONDS));
         assertEquals(AUTOMATIC_RULE_STATUS_ACTIVATED, actualStatus[0]);
@@ -3256,7 +3272,7 @@
                 null,
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
         final String createdId = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(),
-                zenRule, "test", Process.SYSTEM_UID, FROM_SYSTEM_OR_SYSTEMUI);
+                zenRule, UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID);
 
         CountDownLatch latch = new CountDownLatch(1);
         final int[] actualStatus = new int[2];
@@ -3274,10 +3290,10 @@
 
         mZenModeHelper.setAutomaticZenRuleState(createdId,
                 new Condition(zenRule.getConditionId(), "", STATE_TRUE),
-                Process.SYSTEM_UID, true);
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
 
-        mZenModeHelper.setManualZenMode(Global.ZEN_MODE_OFF, null, null, "",
-                Process.SYSTEM_UID, true);
+        mZenModeHelper.setManualZenMode(Global.ZEN_MODE_OFF, null, UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI,
+                null, "", Process.SYSTEM_UID);
 
         assertTrue(latch.await(500, TimeUnit.MILLISECONDS));
         assertEquals(AUTOMATIC_RULE_STATUS_DEACTIVATED, actualStatus[1]);
@@ -3296,7 +3312,7 @@
                 null,
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
         final String createdId = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(),
-                zenRule, "test", Process.SYSTEM_UID, FROM_SYSTEM_OR_SYSTEMUI);
+                zenRule, UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID);
 
         CountDownLatch latch = new CountDownLatch(1);
         final int[] actualStatus = new int[2];
@@ -3314,11 +3330,11 @@
 
         mZenModeHelper.setAutomaticZenRuleState(createdId,
                 new Condition(zenRule.getConditionId(), "", STATE_TRUE),
-                Process.SYSTEM_UID, true);
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
 
         mZenModeHelper.setAutomaticZenRuleState(createdId,
                 new Condition(zenRule.getConditionId(), "", STATE_FALSE),
-                Process.SYSTEM_UID, true);
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
 
         assertTrue(latch.await(500, TimeUnit.MILLISECONDS));
         assertEquals(AUTOMATIC_RULE_STATUS_DEACTIVATED, actualStatus[1]);
@@ -3336,21 +3352,21 @@
                 null,
                 NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
         final String createdId = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(),
-                zenRule, "test", Process.SYSTEM_UID, FROM_SYSTEM_OR_SYSTEMUI);
+                zenRule, UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID);
 
         // Event 1: Mimic the rule coming on automatically by setting the Condition to STATE_TRUE
         mZenModeHelper.setAutomaticZenRuleState(createdId,
                 new Condition(zenRule.getConditionId(), "", STATE_TRUE),
-                Process.SYSTEM_UID, true);
+                UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID);
 
         // Event 2: Snooze rule by turning off DND
-        mZenModeHelper.setManualZenMode(Global.ZEN_MODE_OFF, null, null, "",
-                Process.SYSTEM_UID, true);
+        mZenModeHelper.setManualZenMode(Global.ZEN_MODE_OFF, null, UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI,
+                "", null, Process.SYSTEM_UID);
 
         // Event 3: "User" turns off the automatic rule (sets it to not enabled)
         zenRule.setEnabled(false);
-        mZenModeHelper.updateAutomaticZenRule(createdId, zenRule, "", Process.SYSTEM_UID,
-                FROM_SYSTEM_OR_SYSTEMUI);
+        mZenModeHelper.updateAutomaticZenRule(createdId, zenRule, UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI,
+                "", Process.SYSTEM_UID);
 
         assertEquals(false, mZenModeHelper.mConfig.automaticRules.get(createdId).snoozing);
     }
@@ -3359,18 +3375,20 @@
     public void testDeviceEffects_applied() {
         mSetFlagsRule.enableFlags(android.app.Flags.FLAG_MODES_API);
         mZenModeHelper.setDeviceEffectsApplier(mDeviceEffectsApplier);
+        verify(mDeviceEffectsApplier).apply(eq(NO_EFFECTS), eq(UPDATE_ORIGIN_INIT));
 
         ZenDeviceEffects effects = new ZenDeviceEffects.Builder()
                 .setShouldSuppressAmbientDisplay(true)
                 .setShouldDimWallpaper(true)
                 .build();
         String ruleId = addRuleWithEffects(effects);
-        verify(mDeviceEffectsApplier, never()).apply(any());
+        verifyNoMoreInteractions(mDeviceEffectsApplier);
 
-        mZenModeHelper.setAutomaticZenRuleState(ruleId, CONDITION_TRUE, CUSTOM_PKG_UID, false);
+        mZenModeHelper.setAutomaticZenRuleState(ruleId, CONDITION_TRUE, UPDATE_ORIGIN_APP,
+                CUSTOM_PKG_UID);
         mTestableLooper.processAllMessages();
 
-        verify(mDeviceEffectsApplier).apply(eq(effects));
+        verify(mDeviceEffectsApplier).apply(eq(effects), eq(UPDATE_ORIGIN_APP));
     }
 
     @Test
@@ -3380,31 +3398,66 @@
 
         ZenDeviceEffects zde = new ZenDeviceEffects.Builder().setShouldUseNightMode(true).build();
         String ruleId = addRuleWithEffects(zde);
-        mZenModeHelper.setAutomaticZenRuleState(ruleId, CONDITION_TRUE, CUSTOM_PKG_UID, false);
+        mZenModeHelper.setAutomaticZenRuleState(ruleId, CONDITION_TRUE, UPDATE_ORIGIN_APP,
+                CUSTOM_PKG_UID);
         mTestableLooper.processAllMessages();
-        verify(mDeviceEffectsApplier).apply(eq(zde));
+        verify(mDeviceEffectsApplier).apply(eq(zde), eq(UPDATE_ORIGIN_APP));
 
-        mZenModeHelper.setAutomaticZenRuleState(ruleId, CONDITION_FALSE, CUSTOM_PKG_UID, false);
+        mZenModeHelper.setAutomaticZenRuleState(ruleId, CONDITION_FALSE, UPDATE_ORIGIN_APP,
+                CUSTOM_PKG_UID);
         mTestableLooper.processAllMessages();
 
-        verify(mDeviceEffectsApplier).apply(eq(NO_EFFECTS));
+        verify(mDeviceEffectsApplier).apply(eq(NO_EFFECTS), eq(UPDATE_ORIGIN_APP));
     }
 
     @Test
+    public void testDeviceEffects_changeToConsolidatedEffects_applied() {
+        mSetFlagsRule.enableFlags(android.app.Flags.FLAG_MODES_API);
+        mZenModeHelper.setDeviceEffectsApplier(mDeviceEffectsApplier);
+        verify(mDeviceEffectsApplier).apply(eq(NO_EFFECTS), eq(UPDATE_ORIGIN_INIT));
+
+        String ruleId = addRuleWithEffects(
+                new ZenDeviceEffects.Builder().setShouldDisplayGrayscale(true).build());
+        mZenModeHelper.setAutomaticZenRuleState(ruleId, CONDITION_TRUE, UPDATE_ORIGIN_APP,
+                CUSTOM_PKG_UID);
+        mTestableLooper.processAllMessages();
+        verify(mDeviceEffectsApplier).apply(
+                eq(new ZenDeviceEffects.Builder()
+                        .setShouldDisplayGrayscale(true)
+                        .build()),
+                eq(UPDATE_ORIGIN_APP));
+
+        // Now create and activate a second rule that adds more effects.
+        String secondRuleId = addRuleWithEffects(
+                new ZenDeviceEffects.Builder().setShouldDimWallpaper(true).build());
+        mZenModeHelper.setAutomaticZenRuleState(secondRuleId, CONDITION_TRUE, UPDATE_ORIGIN_APP,
+                CUSTOM_PKG_UID);
+        mTestableLooper.processAllMessages();
+
+        verify(mDeviceEffectsApplier).apply(
+                eq(new ZenDeviceEffects.Builder()
+                        .setShouldDisplayGrayscale(true)
+                        .setShouldDimWallpaper(true)
+                        .build()),
+                eq(UPDATE_ORIGIN_APP));
+    }
+    @Test
     public void testDeviceEffects_noChangeToConsolidatedEffects_notApplied() {
         mSetFlagsRule.enableFlags(android.app.Flags.FLAG_MODES_API);
         mZenModeHelper.setDeviceEffectsApplier(mDeviceEffectsApplier);
+        verify(mDeviceEffectsApplier).apply(eq(NO_EFFECTS), eq(UPDATE_ORIGIN_INIT));
 
         ZenDeviceEffects zde = new ZenDeviceEffects.Builder().setShouldUseNightMode(true).build();
         String ruleId = addRuleWithEffects(zde);
-        mZenModeHelper.setAutomaticZenRuleState(ruleId, CONDITION_TRUE, CUSTOM_PKG_UID, false);
+        mZenModeHelper.setAutomaticZenRuleState(ruleId, CONDITION_TRUE, UPDATE_ORIGIN_APP,
+                CUSTOM_PKG_UID);
         mTestableLooper.processAllMessages();
-        verify(mDeviceEffectsApplier).apply(eq(zde));
+        verify(mDeviceEffectsApplier).apply(eq(zde), eq(UPDATE_ORIGIN_APP));
 
         // Now create and activate a second rule that doesn't add any more effects.
         String secondRuleId = addRuleWithEffects(zde);
-        mZenModeHelper.setAutomaticZenRuleState(secondRuleId, CONDITION_TRUE, CUSTOM_PKG_UID,
-                false);
+        mZenModeHelper.setAutomaticZenRuleState(secondRuleId, CONDITION_TRUE, UPDATE_ORIGIN_APP,
+                CUSTOM_PKG_UID);
         mTestableLooper.processAllMessages();
 
         verifyNoMoreInteractions(mDeviceEffectsApplier);
@@ -3416,21 +3469,50 @@
 
         ZenDeviceEffects zde = new ZenDeviceEffects.Builder().setShouldUseNightMode(true).build();
         String ruleId = addRuleWithEffects(zde);
-        verify(mDeviceEffectsApplier, never()).apply(any());
+        verify(mDeviceEffectsApplier, never()).apply(any(), anyInt());
 
-        mZenModeHelper.setAutomaticZenRuleState(ruleId, CONDITION_TRUE, CUSTOM_PKG_UID, false);
+        mZenModeHelper.setAutomaticZenRuleState(ruleId, CONDITION_TRUE, UPDATE_ORIGIN_APP,
+                CUSTOM_PKG_UID);
         mTestableLooper.processAllMessages();
-        verify(mDeviceEffectsApplier, never()).apply(any());
+        verify(mDeviceEffectsApplier, never()).apply(any(), anyInt());
 
         mZenModeHelper.setDeviceEffectsApplier(mDeviceEffectsApplier);
-        verify(mDeviceEffectsApplier).apply(eq(zde));
+        verify(mDeviceEffectsApplier).apply(eq(zde), eq(UPDATE_ORIGIN_INIT));
+    }
+
+    @Test
+    public void testDeviceEffects_onUserSwitch_appliedImmediately() {
+        mSetFlagsRule.enableFlags(android.app.Flags.FLAG_MODES_API);
+        mZenModeHelper.setDeviceEffectsApplier(mDeviceEffectsApplier);
+        verify(mDeviceEffectsApplier).apply(eq(NO_EFFECTS), eq(UPDATE_ORIGIN_INIT));
+
+        // Initialize default configurations (default rules) for both users.
+        mZenModeHelper.onUserSwitched(1);
+        mZenModeHelper.onUserSwitched(2);
+
+        // Current user is now 2. Tweak a rule for user 1 so it's active and has effects.
+        ZenRule user1Rule = mZenModeHelper.mConfigs.get(1).automaticRules.valueAt(0);
+        user1Rule.enabled = true;
+        user1Rule.condition = new Condition(user1Rule.conditionId, "on", STATE_TRUE);
+        user1Rule.zenDeviceEffects = new ZenDeviceEffects.Builder()
+                .setShouldDimWallpaper(true)
+                .setShouldUseNightMode(true)
+                .build();
+        verifyNoMoreInteractions(mDeviceEffectsApplier);
+
+        mZenModeHelper.onUserSwitched(1);
+        mTestableLooper.processAllMessages();
+
+        verify(mDeviceEffectsApplier).apply(eq(user1Rule.zenDeviceEffects),
+                eq(UPDATE_ORIGIN_INIT_USER));
     }
 
     private String addRuleWithEffects(ZenDeviceEffects effects) {
         AutomaticZenRule rule = new AutomaticZenRule.Builder("Test", CONDITION_ID)
                 .setDeviceEffects(effects)
                 .build();
-        return mZenModeHelper.addAutomaticZenRule("pkg", rule, "", CUSTOM_PKG_UID, FROM_APP);
+        return mZenModeHelper.addAutomaticZenRule("pkg", rule, UPDATE_ORIGIN_APP, "",
+                CUSTOM_PKG_UID);
     }
 
     @Test
@@ -3455,7 +3537,7 @@
 
         mZenModeHelper.applyGlobalZenModeAsImplicitZenRule(CUSTOM_PKG_NAME, CUSTOM_PKG_UID,
                 ZEN_MODE_IMPORTANT_INTERRUPTIONS);
-        mZenModeHelper.setManualZenMode(ZEN_MODE_OFF, null, "test", "test", 0, true);
+        mZenModeHelper.setManualZenMode(ZEN_MODE_OFF, null, UPDATE_ORIGIN_APP, "test", "test", 0);
         assertThat(mZenModeHelper.mConfig.automaticRules).hasSize(1);
 
         mZenModeHelper.applyGlobalZenModeAsImplicitZenRule(CUSTOM_PKG_NAME, CUSTOM_PKG_UID,
@@ -3505,7 +3587,7 @@
         assertThat(mZenModeHelper.mConfig.automaticRules).hasSize(1);
         assertThat(mZenModeHelper.mConfig.automaticRules.valueAt(0).snoozing).isFalse();
 
-        mZenModeHelper.setManualZenMode(ZEN_MODE_OFF, null, "test", "test", 0, true);
+        mZenModeHelper.setManualZenMode(ZEN_MODE_OFF, null, UPDATE_ORIGIN_APP, "test", "test", 0);
         assertThat(mZenModeHelper.mConfig.automaticRules.valueAt(0).snoozing).isTrue();
 
         mZenModeHelper.applyGlobalZenModeAsImplicitZenRule(CUSTOM_PKG_NAME, CUSTOM_PKG_UID,
@@ -3674,6 +3756,10 @@
         rule.zenPolicy = policy;
         rule.pkg = ownerPkg;
         rule.name = CUSTOM_APP_LABEL;
+        rule.iconResName = ICON_RES_NAME;
+        rule.triggerDescription = mContext.getString(R.string.zen_mode_implicit_trigger_description,
+                CUSTOM_APP_LABEL);
+        rule.type = AutomaticZenRule.TYPE_OTHER;
         rule.enabled = true;
         return rule;
     }
diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java
index a105649..d6b2116 100644
--- a/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java
+++ b/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java
@@ -1399,6 +1399,17 @@
     }
 
     @Test
+    public void performHapticFeedback_usesServiceAsToken() throws Exception {
+        VibratorManagerService service = createSystemReadyService();
+
+        HalVibration vibration =
+                performHapticFeedbackAndWaitUntilFinished(
+                        service, HapticFeedbackConstants.SCROLL_TICK, /* always= */ true);
+
+        assertTrue(vibration.callerToken == service);
+    }
+
+    @Test
     public void vibrate_withIntensitySettings_appliesSettingsToScaleVibrations() throws Exception {
         int defaultNotificationIntensity =
                 mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_NOTIFICATION);
diff --git a/services/tests/voiceinteractiontests/Android.bp b/services/tests/voiceinteractiontests/Android.bp
index 744cb63..8a79fe4 100644
--- a/services/tests/voiceinteractiontests/Android.bp
+++ b/services/tests/voiceinteractiontests/Android.bp
@@ -44,6 +44,7 @@
         "servicestests-core-utils",
         "servicestests-utils-mockito-extended",
         "truth",
+        "frameworks-base-testutils",
     ],
 
     libs: [
diff --git a/services/tests/voiceinteractiontests/src/com/android/server/voiceinteraction/SetSandboxedTrainingDataAllowedTest.java b/services/tests/voiceinteractiontests/src/com/android/server/voiceinteraction/SetSandboxedTrainingDataAllowedTest.java
new file mode 100644
index 0000000..159c760
--- /dev/null
+++ b/services/tests/voiceinteractiontests/src/com/android/server/voiceinteraction/SetSandboxedTrainingDataAllowedTest.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.voiceinteraction;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.Manifest;
+import android.app.ActivityManagerInternal;
+import android.app.AppOpsManager;
+import android.app.role.RoleManager;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.os.PermissionEnforcer;
+import android.os.Process;
+import android.os.test.FakePermissionEnforcer;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.modules.utils.testing.ExtendedMockitoRule;
+import com.android.server.LocalServices;
+import com.android.server.pm.UserManagerInternal;
+import com.android.server.pm.permission.LegacyPermissionManagerInternal;
+import com.android.server.pm.permission.PermissionManagerServiceInternal;
+import com.android.server.wm.ActivityTaskManagerInternal;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.quality.Strictness;
+
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class SetSandboxedTrainingDataAllowedTest {
+
+    @Captor private ArgumentCaptor<Integer> mOpIdCaptor, mUidCaptor, mOpModeCaptor;
+
+    @Mock
+    private AppOpsManager mAppOpsManager;
+
+    @Mock
+    private VoiceInteractionManagerServiceImpl mVoiceInteractionManagerServiceImpl;
+
+    private FakePermissionEnforcer mPermissionEnforcer = new FakePermissionEnforcer();
+
+    private Context mContext;
+
+    private VoiceInteractionManagerService mVoiceInteractionManagerService;
+    private VoiceInteractionManagerService.VoiceInteractionManagerServiceStub
+            mVoiceInteractionManagerServiceStub;
+
+    private ApplicationInfo mApplicationInfo = new ApplicationInfo();
+
+    @Rule
+    public final ExtendedMockitoRule mExtendedMockitoRule =
+            new ExtendedMockitoRule.Builder(this)
+                    .setStrictness(Strictness.WARN)
+                    .mockStatic(LocalServices.class)
+                    .mockStatic(PermissionEnforcer.class)
+                    .build();
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mContext = spy(ApplicationProvider.getApplicationContext());
+
+        doReturn(mPermissionEnforcer).when(() -> PermissionEnforcer.fromContext(any()));
+        doReturn(mock(PermissionManagerServiceInternal.class)).when(
+                () -> LocalServices.getService(PermissionManagerServiceInternal.class));
+        doReturn(mock(ActivityManagerInternal.class)).when(
+                () -> LocalServices.getService(ActivityManagerInternal.class));
+        doReturn(mock(UserManagerInternal.class)).when(
+                () -> LocalServices.getService(UserManagerInternal.class));
+        doReturn(mock(ActivityTaskManagerInternal.class)).when(
+                () -> LocalServices.getService(ActivityTaskManagerInternal.class));
+        doReturn(mock(LegacyPermissionManagerInternal.class)).when(
+                () -> LocalServices.getService(LegacyPermissionManagerInternal.class));
+        doReturn(mock(RoleManager.class)).when(mContext).getSystemService(RoleManager.class);
+        doReturn(mAppOpsManager).when(mContext).getSystemService(Context.APP_OPS_SERVICE);
+        doReturn(mApplicationInfo).when(mVoiceInteractionManagerServiceImpl).getApplicationInfo();
+
+        mVoiceInteractionManagerService = new VoiceInteractionManagerService(mContext);
+        mVoiceInteractionManagerServiceStub =
+                mVoiceInteractionManagerService.new VoiceInteractionManagerServiceStub();
+        mVoiceInteractionManagerServiceStub.mImpl = mVoiceInteractionManagerServiceImpl;
+        mPermissionEnforcer.grant(Manifest.permission.MANAGE_HOTWORD_DETECTION);
+    }
+
+    @Test
+    public void setShouldReceiveSandboxedTrainingData_currentAndPreinstalledAssistant_setsOp() {
+        // Set application info so current app is the current and preinstalled assistant.
+        mApplicationInfo.uid = Process.myUid();
+        mApplicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
+
+        mVoiceInteractionManagerServiceStub.setShouldReceiveSandboxedTrainingData(
+                /* allowed= */ true);
+
+        verify(mAppOpsManager).setUidMode(mOpIdCaptor.capture(), mUidCaptor.capture(),
+                mOpModeCaptor.capture());
+        assertThat(mOpIdCaptor.getValue()).isEqualTo(
+                AppOpsManager.OP_RECEIVE_SANDBOXED_DETECTION_TRAINING_DATA);
+        assertThat(mOpModeCaptor.getValue()).isEqualTo(AppOpsManager.MODE_ALLOWED);
+        assertThat(mUidCaptor.getValue()).isEqualTo(Process.myUid());
+    }
+
+    @Test
+    public void setShouldReceiveSandboxedTrainingData_missingPermission_doesNotSetOp() {
+        // Set application info so current app is the current and preinstalled assistant.
+        mApplicationInfo.uid = Process.myUid();
+        mApplicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
+
+        // Simulate missing MANAGE_HOTWORD_DETECTION permission.
+        mPermissionEnforcer.revoke(Manifest.permission.MANAGE_HOTWORD_DETECTION);
+
+        assertThrows(SecurityException.class,
+                () -> mVoiceInteractionManagerServiceStub.setShouldReceiveSandboxedTrainingData(
+                        /* allowed= */ true));
+
+        verify(mAppOpsManager, never()).setUidMode(anyInt(), anyInt(), anyInt());
+    }
+
+    @Test
+    public void setShouldReceiveSandboxedTrainingData_notPreinstalledAssistant_doesNotSetOp() {
+        // Set application info so current app is not preinstalled assistant.
+        mApplicationInfo.uid = Process.myUid();
+        mApplicationInfo.flags = ApplicationInfo.FLAG_INSTALLED; // Does not contain FLAG_SYSTEM.
+
+        assertThrows(SecurityException.class,
+                () -> mVoiceInteractionManagerServiceStub.setShouldReceiveSandboxedTrainingData(
+                                /* allowed= */ true));
+
+        verify(mAppOpsManager, never()).setUidMode(anyInt(), anyInt(), anyInt());
+    }
+
+    @Test
+    public void setShouldReceiveSandboxedTrainingData_notCurrentAssistant_doesNotSetOp() {
+        // Set application info so current app is not current assistant.
+        mApplicationInfo.uid = Process.SHELL_UID; // Set current assistant uid to shell UID.
+        mApplicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
+
+        assertThrows(SecurityException.class,
+                () -> mVoiceInteractionManagerServiceStub.setShouldReceiveSandboxedTrainingData(
+                                /* allowed= */ true));
+
+        verify(mAppOpsManager, never()).setUidMode(anyInt(), anyInt(), anyInt());
+    }
+}
diff --git a/services/tests/wmtests/AndroidManifest.xml b/services/tests/wmtests/AndroidManifest.xml
index c3074bb..ef19791 100644
--- a/services/tests/wmtests/AndroidManifest.xml
+++ b/services/tests/wmtests/AndroidManifest.xml
@@ -99,11 +99,6 @@
             android:theme="@style/WhiteBackgroundTheme"
             android:exported="true"/>
 
-        <activity android:name="com.android.server.wm.TrustedPresentationCallbackTest$TestActivity"
-            android:exported="true"
-            android:showWhenLocked="true"
-            android:turnScreenOn="true" />
-
         <activity android:name="android.app.Activity"
             android:exported="true"
             android:showWhenLocked="true"
diff --git a/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java b/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java
index 8d236ed..0382ca0 100644
--- a/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java
@@ -61,6 +61,7 @@
         META_SHORTCUTS.append(KEYCODE_P, Intent.CATEGORY_APP_MUSIC);
         META_SHORTCUTS.append(KEYCODE_S, Intent.CATEGORY_APP_MESSAGING);
     }
+    private static final int ANY_DISPLAY_ID = 123;
 
     @Before
     public void setUp() {
@@ -96,8 +97,9 @@
      */
     @Test
     public void testCtrlSpace() {
-        sendKeyCombination(new int[]{KEYCODE_CTRL_LEFT, KEYCODE_SPACE}, 0);
-        mPhoneWindowManager.assertSwitchKeyboardLayout(1);
+        sendKeyCombination(new int[]{KEYCODE_CTRL_LEFT, KEYCODE_SPACE}, /* duration= */ 0,
+                ANY_DISPLAY_ID);
+        mPhoneWindowManager.assertSwitchKeyboardLayout(/* direction= */ 1, ANY_DISPLAY_ID);
     }
 
     /**
@@ -105,8 +107,9 @@
      */
     @Test
     public void testCtrlShiftSpace() {
-        sendKeyCombination(new int[]{KEYCODE_CTRL_LEFT, KEYCODE_SHIFT_LEFT, KEYCODE_SPACE}, 0);
-        mPhoneWindowManager.assertSwitchKeyboardLayout(-1);
+        sendKeyCombination(new int[]{KEYCODE_CTRL_LEFT, KEYCODE_SHIFT_LEFT, KEYCODE_SPACE},
+                /* duration= */ 0, ANY_DISPLAY_ID);
+        mPhoneWindowManager.assertSwitchKeyboardLayout(/* direction= */ -1, ANY_DISPLAY_ID);
     }
 
     /**
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 ab35da6..157d162 100644
--- a/services/tests/wmtests/src/com/android/server/policy/ShortcutKeyTestBase.java
+++ b/services/tests/wmtests/src/com/android/server/policy/ShortcutKeyTestBase.java
@@ -64,6 +64,7 @@
     @Rule public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule();
 
     TestPhoneWindowManager mPhoneWindowManager;
+    DispatchedKeyHandler mDispatchedKeyHandler = event -> false;
     final Context mContext = spy(getInstrumentation().getTargetContext());
 
     /** Modifier key to meta state */
@@ -102,6 +103,10 @@
         mPhoneWindowManager = new TestPhoneWindowManager(mContext, supportSettingsUpdate);
     }
 
+    protected final void setDispatchedKeyHandler(DispatchedKeyHandler keyHandler) {
+        mDispatchedKeyHandler = keyHandler;
+    }
+
     @After
     public void tearDown() {
         if (mPhoneWindowManager != null) {
@@ -109,7 +114,7 @@
         }
     }
 
-    void sendKeyCombination(int[] keyCodes, long durationMillis, boolean longPress) {
+    void sendKeyCombination(int[] keyCodes, long durationMillis, boolean longPress, int displayId) {
         final long downTime = mPhoneWindowManager.getCurrentTime();
         final int count = keyCodes.length;
         int metaState = 0;
@@ -119,7 +124,7 @@
             final KeyEvent event = new KeyEvent(downTime, downTime, KeyEvent.ACTION_DOWN, keyCode,
                     0 /*repeat*/, metaState, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /*scancode*/,
                     0 /*flags*/, InputDevice.SOURCE_KEYBOARD);
-            event.setDisplayId(DEFAULT_DISPLAY);
+            event.setDisplayId(displayId);
             interceptKey(event);
             // The order is important here, metaState could be updated and applied to the next key.
             metaState |= MODIFIER.getOrDefault(keyCode, 0);
@@ -137,7 +142,7 @@
                         KeyEvent.ACTION_DOWN, keyCode, 1 /*repeat*/, metaState,
                         KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /*scancode*/,
                         KeyEvent.FLAG_LONG_PRESS /*flags*/, InputDevice.SOURCE_KEYBOARD);
-                nextDownEvent.setDisplayId(DEFAULT_DISPLAY);
+                nextDownEvent.setDisplayId(displayId);
                 interceptKey(nextDownEvent);
             }
         }
@@ -148,18 +153,23 @@
             final KeyEvent upEvent = new KeyEvent(downTime, eventTime, KeyEvent.ACTION_UP, keyCode,
                     0, metaState, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /*scancode*/, 0 /*flags*/,
                     InputDevice.SOURCE_KEYBOARD);
-            upEvent.setDisplayId(DEFAULT_DISPLAY);
+            upEvent.setDisplayId(displayId);
             interceptKey(upEvent);
             metaState &= ~MODIFIER.getOrDefault(keyCode, 0);
         }
     }
 
     void sendKeyCombination(int[] keyCodes, long durationMillis) {
-        sendKeyCombination(keyCodes, durationMillis, false /* longPress */);
+        sendKeyCombination(keyCodes, durationMillis, false /* longPress */, DEFAULT_DISPLAY);
+    }
+
+    void sendKeyCombination(int[] keyCodes, long durationMillis, int displayId) {
+        sendKeyCombination(keyCodes, durationMillis, false /* longPress */, displayId);
     }
 
     void sendLongPressKeyCombination(int[] keyCodes) {
-        sendKeyCombination(keyCodes, ViewConfiguration.getLongPressTimeout(), true /* longPress */);
+        sendKeyCombination(keyCodes, ViewConfiguration.getLongPressTimeout(), true /* longPress */,
+                DEFAULT_DISPLAY);
     }
 
     void sendKey(int keyCode) {
@@ -167,16 +177,27 @@
     }
 
     void sendKey(int keyCode, boolean longPress) {
-        sendKeyCombination(new int[]{keyCode}, 0 /*durationMillis*/, longPress);
+        sendKeyCombination(new int[]{keyCode}, 0 /*durationMillis*/, longPress, DEFAULT_DISPLAY);
     }
 
     private void interceptKey(KeyEvent keyEvent) {
         int actions = mPhoneWindowManager.interceptKeyBeforeQueueing(keyEvent);
         if ((actions & ACTION_PASS_TO_USER) != 0) {
             if (0 == mPhoneWindowManager.interceptKeyBeforeDispatching(keyEvent)) {
-                mPhoneWindowManager.dispatchUnhandledKey(keyEvent);
+                if (!mDispatchedKeyHandler.onKeyDispatched(keyEvent)) {
+                    mPhoneWindowManager.dispatchUnhandledKey(keyEvent);
+                }
             }
         }
         mPhoneWindowManager.dispatchAllPendingEvents();
     }
+
+    interface DispatchedKeyHandler {
+        /**
+         * Called when a key event is dispatched to app.
+         *
+         * @return true if the event is consumed by app.
+         */
+        boolean onKeyDispatched(KeyEvent event);
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/policy/StemKeyGestureTests.java b/services/tests/wmtests/src/com/android/server/policy/StemKeyGestureTests.java
index 912e1d3d..f7ad2a8 100644
--- a/services/tests/wmtests/src/com/android/server/policy/StemKeyGestureTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/StemKeyGestureTests.java
@@ -97,6 +97,35 @@
     }
 
     @Test
+    public void stemSingleKey_appHasOverridePermission_consumedByApp_notOpenAllApp() {
+        overrideBehavior(STEM_PRIMARY_BUTTON_SHORT_PRESS, SHORT_PRESS_PRIMARY_LAUNCH_ALL_APPS);
+        setUpPhoneWindowManager(/* supportSettingsUpdate= */ true);
+        mPhoneWindowManager.overrideStartActivity();
+        mPhoneWindowManager.setKeyguardServiceDelegateIsShowing(false);
+        mPhoneWindowManager.overrideIsUserSetupComplete(true);
+        mPhoneWindowManager.overrideFocusedWindowButtonOverridePermission(true);
+        setDispatchedKeyHandler(keyEvent -> true);
+
+        sendKey(KEYCODE_STEM_PRIMARY);
+
+        mPhoneWindowManager.assertNotOpenAllAppView();
+    }
+
+    @Test
+    public void stemSingleKey_appHasOverridePermission_notConsumedByApp_openAllApp() {
+        overrideBehavior(STEM_PRIMARY_BUTTON_SHORT_PRESS, SHORT_PRESS_PRIMARY_LAUNCH_ALL_APPS);
+        setUpPhoneWindowManager(/* supportSettingsUpdate= */ true);
+        mPhoneWindowManager.overrideStartActivity();
+        mPhoneWindowManager.setKeyguardServiceDelegateIsShowing(false);
+        mPhoneWindowManager.overrideIsUserSetupComplete(true);
+        mPhoneWindowManager.overrideFocusedWindowButtonOverridePermission(true);
+
+        sendKey(KEYCODE_STEM_PRIMARY);
+
+        mPhoneWindowManager.assertOpenAllAppView();
+    }
+
+    @Test
     public void stemLongKey_triggerSearchServiceToLaunchAssist() {
         overrideBehavior(
                 STEM_PRIMARY_BUTTON_LONG_PRESS,
@@ -165,6 +194,30 @@
         mPhoneWindowManager.assertSwitchToRecent(referenceId);
     }
 
+    @Test
+    public void stemDoubleKey_earlyShortPress_firstPressConsumedByApp_switchToMostRecent()
+            throws RemoteException {
+        overrideBehavior(STEM_PRIMARY_BUTTON_DOUBLE_PRESS, SHORT_PRESS_PRIMARY_LAUNCH_ALL_APPS);
+        setUpPhoneWindowManager(/* supportSettingsUpdate= */ true);
+        mPhoneWindowManager.overrideShouldEarlyShortPressOnStemPrimary(true);
+        mPhoneWindowManager.setKeyguardServiceDelegateIsShowing(false);
+        mPhoneWindowManager.overrideIsUserSetupComplete(true);
+        mPhoneWindowManager.overrideFocusedWindowButtonOverridePermission(true);
+        RecentTaskInfo recentTaskInfo = new RecentTaskInfo();
+        int referenceId = 666;
+        recentTaskInfo.persistentId = referenceId;
+        doReturn(recentTaskInfo).when(
+                mPhoneWindowManager.mActivityTaskManagerInternal).getMostRecentTaskFromBackground();
+
+        setDispatchedKeyHandler(keyEvent -> true);
+        sendKey(KEYCODE_STEM_PRIMARY);
+        setDispatchedKeyHandler(keyEvent -> false);
+        sendKey(KEYCODE_STEM_PRIMARY);
+
+        mPhoneWindowManager.assertNotOpenAllAppView();
+        mPhoneWindowManager.assertSwitchToRecent(referenceId);
+    }
+
     private void overrideBehavior(String key, int expectedBehavior) {
         Settings.Global.putLong(mContext.getContentResolver(), key, expectedBehavior);
     }
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 43c4745..0678210 100644
--- a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
+++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
@@ -90,6 +90,7 @@
 
 import com.android.dx.mockito.inline.extended.StaticMockitoSession;
 import com.android.internal.accessibility.AccessibilityShortcutController;
+import com.android.internal.policy.KeyInterceptionInfo;
 import com.android.internal.util.FrameworkStatsLog;
 import com.android.server.GestureLauncherService;
 import com.android.server.LocalServices;
@@ -162,12 +163,37 @@
 
     @Mock private KeyguardServiceDelegate mKeyguardServiceDelegate;
 
+    @Mock
+    private PhoneWindowManager.ButtonOverridePermissionChecker mButtonOverridePermissionChecker;
+
+    @Mock private IBinder mInputToken;
+    @Mock private IBinder mImeTargetWindowToken;
+
     private StaticMockitoSession mMockitoSession;
     private OffsettableClock mClock = new OffsettableClock();
     private TestLooper mTestLooper = new TestLooper(() -> mClock.now());
     private HandlerThread mHandlerThread;
     private Handler mHandler;
 
+    private boolean mIsTalkBackEnabled;
+
+    class TestTalkbackShortcutController extends TalkbackShortcutController {
+        TestTalkbackShortcutController(Context context) {
+            super(context);
+        }
+
+        @Override
+        boolean toggleTalkback(int currentUserId) {
+            mIsTalkBackEnabled = !mIsTalkBackEnabled;
+            return mIsTalkBackEnabled;
+        }
+
+        @Override
+        boolean isTalkBackShortcutGestureEnabled() {
+            return true;
+        }
+    }
+
     private class TestInjector extends PhoneWindowManager.Injector {
         TestInjector(Context context, WindowManagerPolicy.WindowManagerFuncs funcs) {
             super(context, funcs, mTestLooper.getLooper());
@@ -189,6 +215,14 @@
         IActivityManager getActivityManagerService() {
             return mActivityManagerService;
         }
+
+        PhoneWindowManager.ButtonOverridePermissionChecker getButtonOverridePermissionChecker() {
+            return mButtonOverridePermissionChecker;
+        }
+
+        TalkbackShortcutController getTalkbackShortcutController() {
+            return new TestTalkbackShortcutController(mContext);
+        }
     }
 
     TestPhoneWindowManager(Context context, boolean supportSettingsUpdate) {
@@ -296,6 +330,9 @@
         doNothing().when(mPhoneWindowManager).finishedWakingUp(anyInt(), anyInt());
         doNothing().when(mPhoneWindowManager).lockNow(any());
 
+        doReturn(mImeTargetWindowToken)
+                .when(mWindowManagerInternal).getTargetWindowTokenFromInputToken(mInputToken);
+
         mPhoneWindowManager.init(new TestInjector(mContext, mWindowManagerFuncsImpl));
         mPhoneWindowManager.systemReady();
         mPhoneWindowManager.systemBooted();
@@ -304,6 +341,11 @@
         doReturn(false).when(mPhoneWindowManager).keyguardOn();
         doNothing().when(mContext).startActivityAsUser(any(), any());
         doNothing().when(mContext).startActivityAsUser(any(), any(), any());
+
+        KeyInterceptionInfo interceptionInfo = new KeyInterceptionInfo(0, 0, null, 0);
+        doReturn(interceptionInfo)
+                .when(mWindowManagerInternal).getKeyInterceptionInfoFromToken(any());
+
         Mockito.reset(mContext);
     }
 
@@ -329,12 +371,12 @@
     }
 
     long interceptKeyBeforeDispatching(KeyEvent event) {
-        return mPhoneWindowManager.interceptKeyBeforeDispatching(null /*focusedToken*/,
-                event, FLAG_INTERACTIVE);
+        return mPhoneWindowManager.interceptKeyBeforeDispatching(mInputToken, event,
+                FLAG_INTERACTIVE);
     }
 
     void dispatchUnhandledKey(KeyEvent event) {
-        mPhoneWindowManager.dispatchUnhandledKey(null /*focusedToken*/, event, FLAG_INTERACTIVE);
+        mPhoneWindowManager.dispatchUnhandledKey(mInputToken, event, FLAG_INTERACTIVE);
     }
 
     long getCurrentTime() {
@@ -525,6 +567,11 @@
         mPhoneWindowManager.mPrimaryShortPressTargetActivity = component;
     }
 
+    void overrideFocusedWindowButtonOverridePermission(boolean granted) {
+        doReturn(granted)
+                .when(mButtonOverridePermissionChecker).canAppOverrideSystemKey(any(), anyInt());
+    }
+
     /**
      * Below functions will check the policy behavior could be invoked.
      */
@@ -605,14 +652,16 @@
         verify(mStatusBarManagerInternal).startAssist(any());
     }
 
-    void assertSwitchKeyboardLayout(int direction) {
+    void assertSwitchKeyboardLayout(int direction, int displayId) {
         mTestLooper.dispatchAll();
         if (FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_UI)) {
-            verify(mInputMethodManagerInternal).switchKeyboardLayout(eq(direction));
+            verify(mInputMethodManagerInternal).onSwitchKeyboardLayoutShortcut(eq(direction),
+                    eq(displayId), eq(mImeTargetWindowToken));
             verify(mWindowManagerFuncsImpl, never()).switchKeyboardLayout(anyInt(), anyInt());
         } else {
             verify(mWindowManagerFuncsImpl).switchKeyboardLayout(anyInt(), eq(direction));
-            verify(mInputMethodManagerInternal, never()).switchKeyboardLayout(anyInt());
+            verify(mInputMethodManagerInternal, never())
+                    .onSwitchKeyboardLayoutShortcut(anyInt(), anyInt(), any());
         }
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
index 65e77dc..d4ba3b2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
@@ -124,7 +124,7 @@
     private void verifyOnActivityLaunched(ActivityRecord activity) {
         final ArgumentCaptor<Long> idCaptor = ArgumentCaptor.forClass(Long.class);
         verifyAsync(mLaunchObserver).onActivityLaunched(idCaptor.capture(),
-                eq(activity.mActivityComponent), anyInt());
+                eq(activity.mActivityComponent), anyInt(), anyInt());
         final long id = idCaptor.getValue();
         setExpectedStartedId(id, activity);
         mLastLaunchedIds.put(activity.mActivityComponent, id);
@@ -132,7 +132,7 @@
 
     private void verifyOnActivityLaunchFinished(ActivityRecord activity) {
         verifyAsync(mLaunchObserver).onActivityLaunchFinished(eq(mExpectedStartedId),
-                eq(activity.mActivityComponent), anyLong());
+                eq(activity.mActivityComponent), anyLong(), anyInt());
     }
 
     private void setExpectedStartedId(long id, Object reason) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 7aa46a6..85c6f9e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -123,6 +123,7 @@
 import android.app.PictureInPictureParams;
 import android.app.servertransaction.ActivityConfigurationChangeItem;
 import android.app.servertransaction.ClientTransaction;
+import android.app.servertransaction.ClientTransactionItem;
 import android.app.servertransaction.DestroyActivityItem;
 import android.app.servertransaction.PauseActivityItem;
 import android.app.servertransaction.WindowStateResizeItem;
@@ -169,6 +170,7 @@
 import org.mockito.invocation.InvocationOnMock;
 
 import java.util.ArrayList;
+import java.util.List;
 import java.util.function.BiConsumer;
 import java.util.function.Consumer;
 
@@ -260,8 +262,18 @@
         final MutableBoolean pauseFound = new MutableBoolean(false);
         doAnswer((InvocationOnMock invocationOnMock) -> {
             final ClientTransaction transaction = invocationOnMock.getArgument(0);
-            if (transaction.getLifecycleStateRequest() instanceof PauseActivityItem) {
-                pauseFound.value = true;
+            final List<ClientTransactionItem> items = transaction.getTransactionItems();
+            if (items != null) {
+                for (ClientTransactionItem item : items) {
+                    if (item instanceof PauseActivityItem) {
+                        pauseFound.value = true;
+                        break;
+                    }
+                }
+            } else {
+                if (transaction.getLifecycleStateRequest() instanceof PauseActivityItem) {
+                    pauseFound.value = true;
+                }
             }
             return null;
         }).when(mClientLifecycleManager).scheduleTransaction(any());
@@ -279,6 +291,8 @@
 
         // If the activity is not focusable, it should move to paused.
         activity.makeVisibleIfNeeded(null /* starting */, true /* reportToClient */);
+        mClientLifecycleManager.dispatchPendingTransactions();
+
         assertTrue(activity.isState(PAUSING));
         assertTrue(pauseFound.value);
 
@@ -1239,7 +1253,7 @@
     }
 
     @Test
-    public void testFinishActivityIfPossible_sendResultImmediately() {
+    public void testFinishActivityIfPossible_sendResultImmediately() throws RemoteException {
         // Create activity representing the source of the activity result.
         final ComponentName sourceComponent = ComponentName.createRelative(
                 DEFAULT_COMPONENT_PACKAGE_NAME, ".SourceActivity");
@@ -1270,12 +1284,8 @@
 
         targetActivity.finishIfPossible(0, new Intent(), null, "test", false /* oomAdj */);
 
-        try {
-            verify(mClientLifecycleManager, atLeastOnce()).scheduleTransaction(
-                    any(ClientTransaction.class));
-        } catch (RemoteException ignored) {
-        }
-
+        verify(mClientLifecycleManager, atLeastOnce()).scheduleTransactionItem(
+                any(), any(ClientTransactionItem.class));
         assertNull(targetActivity.results);
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index 98055fa..8a9c05d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -117,6 +117,7 @@
 import com.android.compatibility.common.util.DeviceConfigStateHelper;
 import com.android.internal.util.FrameworkStatsLog;
 import com.android.server.am.PendingIntentRecord;
+import com.android.server.pm.PackageArchiver;
 import com.android.server.pm.pkg.AndroidPackage;
 import com.android.server.wm.BackgroundActivityStartController.BalVerdict;
 import com.android.server.wm.LaunchParamsController.LaunchParamsModifier;
@@ -421,6 +422,7 @@
         doNothing().when(mMockPackageManager).grantImplicitAccess(
                 anyInt(), any(), anyInt(), anyInt(), anyBoolean());
         doNothing().when(mMockPackageManager).notifyPackageUse(anyString(), anyInt());
+        doReturn(mock(PackageArchiver.class)).when(mMockPackageManager).getPackageArchiver();
 
         final Intent intent = new Intent();
         intent.addFlags(launchFlags);
diff --git a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
index 4d4d397..ac18f80 100644
--- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
@@ -233,6 +233,29 @@
         assertThat(typeToString(backNavigationInfo.getType()))
                 .isEqualTo(typeToString(BackNavigationInfo.TYPE_CALLBACK));
 
+        // reset drawing status, test if top activity is translucent
+        backNavigationInfo.onBackNavigationFinished(false);
+        mBackNavigationController.clearBackAnimations();
+        makeWindowVisibleAndDrawn(testCase.recordFront.findMainWindow());
+        // simulate translucent
+        testCase.recordFront.setOccludesParent(false);
+        backNavigationInfo = startBackNavigation();
+        assertThat(typeToString(backNavigationInfo.getType()))
+                .isEqualTo(typeToString(BackNavigationInfo.TYPE_CALLBACK));
+        testCase.recordFront.setOccludesParent(true);
+
+        // reset drawing status, test if bottom activity is translucent
+        backNavigationInfo.onBackNavigationFinished(false);
+        mBackNavigationController.clearBackAnimations();
+        makeWindowVisibleAndDrawn(testCase.recordBack.findMainWindow());
+        // simulate translucent
+        testCase.recordBack.setOccludesParent(false);
+        backNavigationInfo = startBackNavigation();
+        assertThat(typeToString(backNavigationInfo.getType()))
+                .isEqualTo(typeToString(BackNavigationInfo.TYPE_CALLBACK));
+        testCase.recordBack.setOccludesParent(true);
+
+        // reset drawing status, test canShowWhenLocked
         backNavigationInfo.onBackNavigationFinished(false);
         mBackNavigationController.clearBackAnimations();
         doReturn(true).when(testCase.recordBack).canShowWhenLocked();
diff --git a/services/tests/wmtests/src/com/android/server/wm/ClientLifecycleManagerTests.java b/services/tests/wmtests/src/com/android/server/wm/ClientLifecycleManagerTests.java
index 04aa981..7fdc5fc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ClientLifecycleManagerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ClientLifecycleManagerTests.java
@@ -17,13 +17,15 @@
 package com.android.server.wm;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.window.flags.Flags.FLAG_BUNDLE_CLIENT_TRANSACTION_FLAG;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.clearInvocations;
-import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.never;
 
@@ -31,12 +33,15 @@
 import android.app.servertransaction.ActivityLifecycleItem;
 import android.app.servertransaction.ClientTransaction;
 import android.app.servertransaction.ClientTransactionItem;
+import android.os.IBinder;
 import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
+import android.platform.test.flag.junit.SetFlagsRule;
 
 import androidx.test.filters.SmallTest;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
@@ -47,30 +52,47 @@
  * Build/Install/Run:
  *  atest WmTests:ClientLifecycleManagerTests
  */
+// Suppress GuardedBy warning on unit tests
+@SuppressWarnings("GuardedBy")
 @SmallTest
 @Presubmit
 public class ClientLifecycleManagerTests {
 
+    @Rule(order = 0)
+    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
+    @Rule(order = 1)
+    public final SystemServicesTestRule mSystemServices = new SystemServicesTestRule();
+
+    @Mock
+    private IBinder mClientBinder;
     @Mock
     private IApplicationThread mClient;
     @Mock
     private IApplicationThread.Stub mNonBinderClient;
     @Mock
+    private ClientTransaction mTransaction;
+    @Mock
     private ClientTransactionItem mTransactionItem;
     @Mock
     private ActivityLifecycleItem mLifecycleItem;
     @Captor
     private ArgumentCaptor<ClientTransaction> mTransactionCaptor;
 
+    private WindowManagerService mWms;
     private ClientLifecycleManager mLifecycleManager;
 
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
 
+        mWms = mSystemServices.getWindowManagerService();
         mLifecycleManager = spy(new ClientLifecycleManager());
+        mLifecycleManager.setWindowManager(mWms);
 
         doReturn(true).when(mLifecycleItem).isActivityLifecycleItem();
+        doReturn(mClientBinder).when(mClient).asBinder();
+        doReturn(mNonBinderClient).when(mNonBinderClient).asBinder();
     }
 
     @Test
@@ -92,9 +114,11 @@
     }
 
     @Test
-    public void testScheduleTransactionItem() throws RemoteException {
-        doNothing().when(mLifecycleManager).scheduleTransaction(any());
-        mLifecycleManager.scheduleTransactionItem(mClient, mTransactionItem);
+    public void testScheduleTransactionItem_notBundle() throws RemoteException {
+        mSetFlagsRule.disableFlags(FLAG_BUNDLE_CLIENT_TRANSACTION_FLAG);
+
+        // Use non binder client to get non-recycled ClientTransaction.
+        mLifecycleManager.scheduleTransactionItem(mNonBinderClient, mTransactionItem);
 
         verify(mLifecycleManager).scheduleTransaction(mTransactionCaptor.capture());
         ClientTransaction transaction = mTransactionCaptor.getValue();
@@ -104,7 +128,7 @@
         assertNull(transaction.getTransactionItems());
 
         clearInvocations(mLifecycleManager);
-        mLifecycleManager.scheduleTransactionItem(mClient, mLifecycleItem);
+        mLifecycleManager.scheduleTransactionItem(mNonBinderClient, mLifecycleItem);
 
         verify(mLifecycleManager).scheduleTransaction(mTransactionCaptor.capture());
         transaction = mTransactionCaptor.getValue();
@@ -113,9 +137,54 @@
     }
 
     @Test
-    public void testScheduleTransactionAndLifecycleItems() throws RemoteException {
-        doNothing().when(mLifecycleManager).scheduleTransaction(any());
-        mLifecycleManager.scheduleTransactionAndLifecycleItems(mClient, mTransactionItem,
+    public void testScheduleTransactionItem() throws RemoteException {
+        mSetFlagsRule.enableFlags(FLAG_BUNDLE_CLIENT_TRANSACTION_FLAG);
+        spyOn(mWms.mWindowPlacerLocked);
+        doReturn(true).when(mWms.mWindowPlacerLocked).isTraversalScheduled();
+
+        // Use non binder client to get non-recycled ClientTransaction.
+        mLifecycleManager.scheduleTransactionItem(mNonBinderClient, mTransactionItem);
+
+        // When there is traversal scheduled, add transaction items to pending.
+        assertEquals(1, mLifecycleManager.mPendingTransactions.size());
+        ClientTransaction transaction =
+                mLifecycleManager.mPendingTransactions.get(mNonBinderClient);
+        assertEquals(1, transaction.getTransactionItems().size());
+        assertEquals(mTransactionItem, transaction.getTransactionItems().get(0));
+        assertNull(transaction.getCallbacks());
+        assertNull(transaction.getLifecycleStateRequest());
+        verify(mLifecycleManager, never()).scheduleTransaction(any());
+
+        // Add new transaction item to the existing pending.
+        clearInvocations(mLifecycleManager);
+        mLifecycleManager.scheduleTransactionItem(mNonBinderClient, mLifecycleItem);
+
+        assertEquals(1, mLifecycleManager.mPendingTransactions.size());
+        transaction = mLifecycleManager.mPendingTransactions.get(mNonBinderClient);
+        assertEquals(2, transaction.getTransactionItems().size());
+        assertEquals(mTransactionItem, transaction.getTransactionItems().get(0));
+        assertEquals(mLifecycleItem, transaction.getTransactionItems().get(1));
+        assertNull(transaction.getCallbacks());
+        assertNull(transaction.getLifecycleStateRequest());
+        verify(mLifecycleManager, never()).scheduleTransaction(any());
+    }
+
+    @Test
+    public void testScheduleTransactionItemUnlocked() throws RemoteException {
+        // Use non binder client to get non-recycled ClientTransaction.
+        mLifecycleManager.scheduleTransactionItemUnlocked(mNonBinderClient, mTransactionItem);
+
+        // Dispatch immediately.
+        assertTrue(mLifecycleManager.mPendingTransactions.isEmpty());
+        verify(mLifecycleManager).scheduleTransaction(any());
+    }
+
+    @Test
+    public void testScheduleTransactionAndLifecycleItems_notBundle() throws RemoteException {
+        mSetFlagsRule.disableFlags(FLAG_BUNDLE_CLIENT_TRANSACTION_FLAG);
+
+        // Use non binder client to get non-recycled ClientTransaction.
+        mLifecycleManager.scheduleTransactionAndLifecycleItems(mNonBinderClient, mTransactionItem,
                 mLifecycleItem);
 
         verify(mLifecycleManager).scheduleTransaction(mTransactionCaptor.capture());
@@ -124,4 +193,36 @@
         assertEquals(mTransactionItem, transaction.getCallbacks().get(0));
         assertEquals(mLifecycleItem, transaction.getLifecycleStateRequest());
     }
+
+    @Test
+    public void testScheduleTransactionAndLifecycleItems() throws RemoteException {
+        mSetFlagsRule.enableFlags(FLAG_BUNDLE_CLIENT_TRANSACTION_FLAG);
+        spyOn(mWms.mWindowPlacerLocked);
+        doReturn(true).when(mWms.mWindowPlacerLocked).isTraversalScheduled();
+
+        // Use non binder client to get non-recycled ClientTransaction.
+        mLifecycleManager.scheduleTransactionAndLifecycleItems(mNonBinderClient, mTransactionItem,
+                mLifecycleItem);
+
+        assertEquals(1, mLifecycleManager.mPendingTransactions.size());
+        final ClientTransaction transaction =
+                mLifecycleManager.mPendingTransactions.get(mNonBinderClient);
+        assertEquals(2, transaction.getTransactionItems().size());
+        assertEquals(mTransactionItem, transaction.getTransactionItems().get(0));
+        assertEquals(mLifecycleItem, transaction.getTransactionItems().get(1));
+        assertNull(transaction.getCallbacks());
+        assertNull(transaction.getLifecycleStateRequest());
+        verify(mLifecycleManager, never()).scheduleTransaction(any());
+    }
+
+    @Test
+    public void testDispatchPendingTransactions() throws RemoteException {
+        mLifecycleManager.mPendingTransactions.put(mClientBinder, mTransaction);
+
+        mLifecycleManager.dispatchPendingTransactions();
+
+        assertTrue(mLifecycleManager.mPendingTransactions.isEmpty());
+        verify(mTransaction).schedule();
+        verify(mTransaction).recycle();
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/DeferredDisplayUpdaterDiffTest.java b/services/tests/wmtests/src/com/android/server/wm/DeferredDisplayUpdaterDiffTest.java
new file mode 100644
index 0000000..44b69f1
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/DeferredDisplayUpdaterDiffTest.java
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static android.hardware.display.DeviceProductInfo.CONNECTION_TO_SINK_UNKNOWN;
+import static android.view.RoundedCorner.POSITION_TOP_LEFT;
+import static android.view.RoundedCorners.NO_ROUNDED_CORNERS;
+
+import static com.android.server.wm.DeferredDisplayUpdater.DEFERRABLE_FIELDS;
+import static com.android.server.wm.DeferredDisplayUpdater.DIFF_NOT_WM_DEFERRABLE;
+import static com.android.server.wm.DeferredDisplayUpdater.DIFF_WM_DEFERRABLE;
+import static com.android.server.wm.DeferredDisplayUpdater.calculateDisplayInfoDiff;
+import static com.android.server.wm.utils.DisplayInfoOverrides.copyDisplayInfoFields;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.annotation.NonNull;
+import android.graphics.Insets;
+import android.graphics.Rect;
+import android.hardware.display.DeviceProductInfo;
+import android.platform.test.annotations.Presubmit;
+import android.util.SparseArray;
+import android.view.Display;
+import android.view.DisplayAddress;
+import android.view.DisplayCutout;
+import android.view.DisplayInfo;
+import android.view.DisplayShape;
+import android.view.RoundedCorner;
+import android.view.RoundedCorners;
+import android.view.SurfaceControl.RefreshRateRange;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.function.Consumer;
+
+/**
+ * Build/Install/Run:
+ * atest WmTests:DeferredDisplayUpdaterDiffTest
+ */
+@SmallTest
+@Presubmit
+public class DeferredDisplayUpdaterDiffTest {
+
+    private static final Set<String> IGNORED_FIELDS = new HashSet<>(Arrays.asList(
+            "name" // human-readable name is ignored in equals() checks
+    ));
+
+    private static final DisplayInfo EMPTY = new DisplayInfo();
+
+    @Test
+    public void testCalculateDisplayInfoDiff_allDifferent_returnsChanges() {
+        final DisplayInfo first = new DisplayInfo();
+        final DisplayInfo second = new DisplayInfo();
+        makeAllFieldsDifferent(first, second);
+
+        int diff = calculateDisplayInfoDiff(first, second);
+
+        assertWithMessage("Expected to receive a non-zero difference when "
+                + "there are changes in all fields of DisplayInfo\n"
+                + "Make sure that you have updated calculateDisplayInfoDiff function after "
+                + "changing DisplayInfo fields").that(diff).isGreaterThan(0);
+    }
+
+    @Test
+    public void testCalculateDisplayInfoDiff_forEveryDifferentField_returnsChanges() {
+        generateWithSingleDifferentField((first, second, field) -> {
+            int diff = calculateDisplayInfoDiff(first, second);
+
+            assertWithMessage("Expected to receive a non-zero difference when "
+                    + "there are changes in " + field + "\n"
+                    + "Make sure that you have updated calculateDisplayInfoDiff function after "
+                    + "changing DisplayInfo fields").that(diff).isGreaterThan(0);
+        });
+    }
+
+    @Test
+    public void testCalculateDisplayInfoDiff_forEveryDifferentField_returnsMatchingChange() {
+        generateWithSingleDifferentField((first, second, field) -> {
+            boolean hasDeferrableFieldChange = hasDeferrableFieldChange(first, second);
+            int expectedDiff =
+                    hasDeferrableFieldChange ? DIFF_WM_DEFERRABLE : DIFF_NOT_WM_DEFERRABLE;
+
+            int diff = calculateDisplayInfoDiff(first, second);
+
+            assertWithMessage("Expected to have diff = " + expectedDiff
+                    + ", for field = " + field + "\n"
+                    + "Make sure that you have updated calculateDisplayInfoDiff function after "
+                    + "changing DisplayInfo fields").that(
+                    diff).isEqualTo(expectedDiff);
+        });
+    }
+
+    /**
+     * Sets each field of the objects to different values using reflection
+     */
+    private static void makeAllFieldsDifferent(@NonNull DisplayInfo first,
+            @NonNull DisplayInfo second) {
+        forEachDisplayInfoField(field -> {
+            try {
+                setDifferentFieldValues(first, second, field);
+            } catch (IllegalAccessException e) {
+                throw new RuntimeException(e);
+            }
+        });
+    }
+
+    private static boolean hasDeferrableFieldChange(@NonNull DisplayInfo first,
+            @NonNull DisplayInfo second) {
+        final DisplayInfo firstDeferrableFieldsOnly = new DisplayInfo();
+        final DisplayInfo secondDeferrableFieldsOnly = new DisplayInfo();
+
+        copyDisplayInfoFields(/* out= */ firstDeferrableFieldsOnly, /* base= */
+                EMPTY, /* override= */ first, DEFERRABLE_FIELDS);
+        copyDisplayInfoFields(/* out= */ secondDeferrableFieldsOnly, /* base= */
+                EMPTY, /* override= */ second, DEFERRABLE_FIELDS);
+
+        return !firstDeferrableFieldsOnly.equals(secondDeferrableFieldsOnly);
+    }
+
+    /**
+     * Creates pairs of DisplayInfos where only one field is different, the callback is called for
+     * each field
+     */
+    private static void generateWithSingleDifferentField(DisplayInfoConsumer consumer) {
+        forEachDisplayInfoField(field -> {
+            final DisplayInfo first = new DisplayInfo();
+            final DisplayInfo second = new DisplayInfo();
+
+            try {
+                setDifferentFieldValues(first, second, field);
+            } catch (IllegalAccessException e) {
+                throw new RuntimeException(e);
+            }
+
+            consumer.consume(first, second, field);
+        });
+    }
+
+    private static void setDifferentFieldValues(@NonNull DisplayInfo first,
+            @NonNull DisplayInfo second,
+            @NonNull Field field) throws IllegalAccessException {
+        final Class<?> type = field.getType();
+        if (type.equals(int.class)) {
+            field.setInt(first, 1);
+            field.setInt(second, 2);
+        } else if (type.equals(double.class)) {
+            field.setDouble(first, 1.0);
+            field.setDouble(second, 2.0);
+        } else if (type.equals(short.class)) {
+            field.setShort(first, (short) 1);
+            field.setShort(second, (short) 2);
+        } else if (type.equals(long.class)) {
+            field.setLong(first, 1L);
+            field.setLong(second, 2L);
+        } else if (type.equals(char.class)) {
+            field.setChar(first, 'a');
+            field.setChar(second, 'b');
+        } else if (type.equals(byte.class)) {
+            field.setByte(first, (byte) 1);
+            field.setByte(second, (byte) 2);
+        } else if (type.equals(float.class)) {
+            field.setFloat(first, 1.0f);
+            field.setFloat(second, 2.0f);
+        } else if (type == boolean.class) {
+            field.setBoolean(first, true);
+            field.setBoolean(second, false);
+        } else if (type.equals(String.class)) {
+            field.set(first, "one");
+            field.set(second, "two");
+        } else if (type.equals(DisplayAddress.class)) {
+            field.set(first, DisplayAddress.fromPhysicalDisplayId(0));
+            field.set(second, DisplayAddress.fromPhysicalDisplayId(1));
+        } else if (type.equals(DeviceProductInfo.class)) {
+            field.set(first, new DeviceProductInfo("name", "pnp_id", "product_id1", 2023,
+                    CONNECTION_TO_SINK_UNKNOWN));
+            field.set(second, new DeviceProductInfo("name", "pnp_id", "product_id2", 2023,
+                    CONNECTION_TO_SINK_UNKNOWN));
+        } else if (type.equals(DisplayCutout.class)) {
+            field.set(first,
+                    new DisplayCutout(Insets.NONE, new Rect(0, 0, 100, 100), null, null,
+                            null));
+            field.set(second,
+                    new DisplayCutout(Insets.NONE, new Rect(0, 0, 200, 200), null, null,
+                            null));
+        } else if (type.equals(RoundedCorners.class)) {
+            field.set(first, NO_ROUNDED_CORNERS);
+
+            final RoundedCorners other = new RoundedCorners(NO_ROUNDED_CORNERS);
+            other.setRoundedCorner(POSITION_TOP_LEFT,
+                    new RoundedCorner(POSITION_TOP_LEFT, 1, 2, 3));
+            field.set(second, other);
+        } else if (type.equals(DisplayShape.class)) {
+            field.set(first, DisplayShape.createDefaultDisplayShape(100, 200, false));
+            field.set(second, DisplayShape.createDefaultDisplayShape(50, 100, false));
+        } else if (type.equals(RefreshRateRange.class)) {
+            field.set(first, new RefreshRateRange(0, 100));
+            field.set(second, new RefreshRateRange(20, 80));
+        } else if (type.equals(Display.HdrCapabilities.class)) {
+            field.set(first, new Display.HdrCapabilities(new int[]{0}, 100, 50, 25));
+            field.set(second, new Display.HdrCapabilities(new int[]{1}, 100, 50, 25));
+        } else if (type.equals(SparseArray.class)
+                && ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0].equals(
+                RefreshRateRange.class)) {
+            final SparseArray<RefreshRateRange> array1 = new SparseArray<>();
+            array1.set(0, new RefreshRateRange(0, 100));
+            final SparseArray<RefreshRateRange> array2 = new SparseArray<>();
+            array2.set(0, new RefreshRateRange(20, 80));
+            field.set(first, array1);
+            field.set(second, array2);
+        } else if (type.isArray() && type.getComponentType().equals(int.class)) {
+            field.set(first, new int[]{0});
+            field.set(second, new int[]{1});
+        } else if (type.isArray() && type.getComponentType().equals(Display.Mode.class)) {
+            field.set(first, new Display.Mode[]{new Display.Mode(100, 200, 300)});
+            field.set(second, new Display.Mode[]{new Display.Mode(10, 20, 30)});
+        } else {
+            throw new IllegalArgumentException("Field " + field
+                    + " is not supported by this test, please add implementation of setting "
+                    + "different values for this field");
+        }
+    }
+
+    private interface DisplayInfoConsumer {
+        void consume(DisplayInfo first, DisplayInfo second, Field field);
+    }
+
+    /**
+     * Iterates over every non-static field of DisplayInfo class except IGNORED_FIELDS
+     */
+    private static void forEachDisplayInfoField(Consumer<Field> consumer) {
+        for (Field field : DisplayInfo.class.getDeclaredFields()) {
+            field.setAccessible(true);
+
+            if (Modifier.isStatic(field.getModifiers())) {
+                continue;
+            }
+
+            if (IGNORED_FIELDS.contains(field.getName())) {
+                continue;
+            }
+
+            consumer.accept(field);
+        }
+    }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentDeferredUpdateTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentDeferredUpdateTests.java
new file mode 100644
index 0000000..dfa595c
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentDeferredUpdateTests.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.when;
+
+import android.platform.test.annotations.Presubmit;
+import android.view.DisplayInfo;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.server.wm.TransitionController.OnStartCollect;
+import com.android.window.flags.Flags;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+
+/**
+ * Tests for the {@link DisplayContent} class when FLAG_DEFER_DISPLAY_UPDATES is enabled.
+ *
+ * Build/Install/Run:
+ * atest WmTests:DisplayContentDeferredUpdateTests
+ */
+@SmallTest
+@Presubmit
+@RunWith(WindowTestRunner.class)
+public class DisplayContentDeferredUpdateTests extends WindowTestsBase {
+
+    @Override
+    protected void onBeforeSystemServicesCreated() {
+        // Set other flags to their default values
+        mSetFlagsRule.initAllFlagsToReleaseConfigDefault();
+
+        mSetFlagsRule.enableFlags(Flags.FLAG_DEFER_DISPLAY_UPDATES);
+    }
+
+    @Before
+    public void before() {
+        mockTransitionsController(/* enabled= */ true);
+        mockRemoteDisplayChangeController();
+    }
+
+    @Test
+    public void testUpdate_deferrableFieldChangedTransitionStarted_deferrableFieldUpdated() {
+        performInitialDisplayUpdate();
+
+        givenDisplayInfo(/* uniqueId= */ "old");
+        Runnable onUpdated = mock(Runnable.class);
+        mDisplayContent.requestDisplayUpdate(onUpdated);
+
+        // Emulate that collection has started
+        captureStartTransitionCollection().getValue().onCollectStarted(/* deferred= */ true);
+        verify(onUpdated).run();
+        clearInvocations(mDisplayContent.mTransitionController, onUpdated);
+
+        givenDisplayInfo(/* uniqueId= */ "new");
+        mDisplayContent.requestDisplayUpdate(onUpdated);
+        captureStartTransitionCollection().getValue().onCollectStarted(/* deferred= */ true);
+        verify(onUpdated).run();
+        assertThat(mDisplayContent.getDisplayInfo().uniqueId).isEqualTo("new");
+    }
+
+    @Test
+    public void testUpdate_nonDeferrableUpdateAndTransitionDeferred_nonDeferrableFieldUpdated() {
+        performInitialDisplayUpdate();
+
+        // Update only color mode (non-deferrable field) and keep the same unique id
+        givenDisplayInfo(/* uniqueId= */ "initial_unique_id", /* colorMode= */ 123);
+        Runnable onUpdated = mock(Runnable.class);
+        mDisplayContent.requestDisplayUpdate(onUpdated);
+
+        verify(onUpdated).run();
+        assertThat(mDisplayContent.getDisplayInfo().colorMode).isEqualTo(123);
+    }
+
+    @Test
+    public void testUpdate_nonDeferrableUpdateTwiceAndTransitionDeferred_fieldHasLatestValue() {
+        performInitialDisplayUpdate();
+
+        // Update only color mode (non-deferrable field) and keep the same unique id
+        givenDisplayInfo(/* uniqueId= */ "initial_unique_id", /* colorMode= */ 123);
+        mDisplayContent.requestDisplayUpdate(mock(Runnable.class));
+
+        assertThat(mDisplayContent.getDisplayInfo().colorMode).isEqualTo(123);
+        assertThat(mDisplayContent.getDisplayInfo().uniqueId)
+                .isEqualTo("initial_unique_id");
+
+        // Update unique id (deferrable field), keep the same color mode,
+        // this update should be deferred
+        givenDisplayInfo(/* uniqueId= */ "new_unique_id", /* colorMode= */ 123);
+        mDisplayContent.requestDisplayUpdate(mock(Runnable.class));
+
+        assertThat(mDisplayContent.getDisplayInfo().colorMode).isEqualTo(123);
+        assertThat(mDisplayContent.getDisplayInfo().uniqueId)
+                .isEqualTo("initial_unique_id");
+
+        // Update color mode again and keep the same unique id, color mode update
+        // should not be deferred, unique id update is still deferred as transition
+        // has not started collecting yet
+        givenDisplayInfo(/* uniqueId= */ "new_unique_id", /* colorMode= */ 456);
+        Runnable onUpdated = mock(Runnable.class);
+        mDisplayContent.requestDisplayUpdate(onUpdated);
+
+        assertThat(mDisplayContent.getDisplayInfo().colorMode).isEqualTo(456);
+        assertThat(mDisplayContent.getDisplayInfo().uniqueId)
+                .isEqualTo("initial_unique_id");
+
+        // Mark transition as started collected, so pending changes are applied
+        captureStartTransitionCollection().getValue().onCollectStarted(/* deferred= */ true);
+
+        // Verify that all fields have the latest values
+        verify(onUpdated).run();
+        assertThat(mDisplayContent.getDisplayInfo().colorMode).isEqualTo(456);
+        assertThat(mDisplayContent.getDisplayInfo().uniqueId).isEqualTo("new_unique_id");
+    }
+
+    @Test
+    public void testUpdate_deferrableFieldUpdatedTransitionPending_fieldNotUpdated() {
+        performInitialDisplayUpdate();
+        givenDisplayInfo(/* uniqueId= */ "old");
+        Runnable onUpdated = mock(Runnable.class);
+        mDisplayContent.requestDisplayUpdate(onUpdated);
+        captureStartTransitionCollection().getValue().onCollectStarted(/* deferred= */ true);
+        verify(onUpdated).run();
+        clearInvocations(mDisplayContent.mTransitionController, onUpdated);
+
+        givenDisplayInfo(/* uniqueId= */ "new");
+        mDisplayContent.requestDisplayUpdate(onUpdated);
+
+        captureStartTransitionCollection(); // do not continue by not starting the collection
+        verify(onUpdated, never()).run();
+        assertThat(mDisplayContent.getDisplayInfo().uniqueId).isEqualTo("old");
+    }
+
+    @Test
+    public void testTwoDisplayUpdates_transitionStarted_displayUpdated() {
+        performInitialDisplayUpdate();
+        givenDisplayInfo(/* uniqueId= */ "old");
+        Runnable onUpdated = mock(Runnable.class);
+        mDisplayContent.requestDisplayUpdate(onUpdated);
+        captureStartTransitionCollection().getValue()
+                .onCollectStarted(/* deferred= */ true);
+        verify(onUpdated).run();
+        clearInvocations(mDisplayContent.mTransitionController, onUpdated);
+
+        // Perform two display updates while WM is 'busy'
+        givenDisplayInfo(/* uniqueId= */ "new1");
+        Runnable onUpdated1 = mock(Runnable.class);
+        mDisplayContent.requestDisplayUpdate(onUpdated1);
+        givenDisplayInfo(/* uniqueId= */ "new2");
+        Runnable onUpdated2 = mock(Runnable.class);
+        mDisplayContent.requestDisplayUpdate(onUpdated2);
+
+        // Continue with the first update
+        captureStartTransitionCollection().getAllValues().get(0)
+                .onCollectStarted(/* deferred= */ true);
+        verify(onUpdated1).run();
+        verify(onUpdated2, never()).run();
+        assertThat(mDisplayContent.getDisplayInfo().uniqueId).isEqualTo("new1");
+
+        // Continue with the second update
+        captureStartTransitionCollection().getAllValues().get(1)
+                .onCollectStarted(/* deferred= */ true);
+        verify(onUpdated2).run();
+        assertThat(mDisplayContent.getDisplayInfo().uniqueId).isEqualTo("new2");
+    }
+
+    private void mockTransitionsController(boolean enabled) {
+        spyOn(mDisplayContent.mTransitionController);
+        when(mDisplayContent.mTransitionController.isShellTransitionsEnabled()).thenReturn(enabled);
+        doReturn(true).when(mDisplayContent.mTransitionController).startCollectOrQueue(any(),
+                any());
+    }
+
+    private void mockRemoteDisplayChangeController() {
+        spyOn(mDisplayContent.mRemoteDisplayChangeController);
+        doReturn(true).when(mDisplayContent.mRemoteDisplayChangeController)
+                .performRemoteDisplayChange(anyInt(), anyInt(), any(), any());
+    }
+
+    private ArgumentCaptor<OnStartCollect> captureStartTransitionCollection() {
+        ArgumentCaptor<OnStartCollect> callbackCaptor =
+                ArgumentCaptor.forClass(OnStartCollect.class);
+        verify(mDisplayContent.mTransitionController, atLeast(1)).startCollectOrQueue(any(),
+                callbackCaptor.capture());
+        return callbackCaptor;
+    }
+
+    private void givenDisplayInfo(String uniqueId) {
+        givenDisplayInfo(uniqueId, /* colorMode= */ 0);
+    }
+
+    private void givenDisplayInfo(String uniqueId, int colorMode) {
+        spyOn(mDisplayContent.mDisplay);
+        doAnswer(invocation -> {
+            DisplayInfo info = invocation.getArgument(0);
+            info.uniqueId = uniqueId;
+            info.colorMode = colorMode;
+            return null;
+        }).when(mDisplayContent.mDisplay).getDisplayInfo(any());
+    }
+
+    private void performInitialDisplayUpdate() {
+        givenDisplayInfo(/* uniqueId= */ "initial_unique_id", /* colorMode= */ 0);
+        Runnable onUpdated = mock(Runnable.class);
+        mDisplayContent.requestDisplayUpdate(onUpdated);
+    }
+}
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 71d2504..dfe79bf 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -993,7 +993,9 @@
         dc.getDisplayPolicy().getDecorInsetsInfo(ROTATION_0, dc.mBaseDisplayHeight,
                 dc.mBaseDisplayWidth).mConfigFrame.set(0, 0, 1000, 990);
         dc.computeScreenConfiguration(config, ROTATION_0);
+        dc.onRequestedOverrideConfigurationChanged(config);
         assertEquals(Configuration.ORIENTATION_LANDSCAPE, config.orientation);
+        assertEquals(Configuration.ORIENTATION_LANDSCAPE, dc.getNaturalOrientation());
     }
 
     @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 50fe042..1fb7cd8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
@@ -553,7 +553,7 @@
             assertTrue(mWm.mInputManager.transferTouchFocus(new InputChannel(),
                     new InputChannel(), true /* isDragDrop */));
             mToken = mTarget.performDrag(TEST_PID, 0, mWindow.mClient,
-                    flag, surface, 0, 0, 0, 0, 0, data);
+                    flag, surface, 0, 0, 0, 0, 0, 0, 0, data);
             assertNotNull(mToken);
 
             r.run();
@@ -575,7 +575,7 @@
 
     private void startA11yDrag(int flags, ClipData data, Runnable r) {
         mToken = mTarget.performDrag(0, 0, mWindow.mClient,
-                flags | View.DRAG_FLAG_ACCESSIBILITY_ACTION, null, 0, 0, 0, 0, 0, data);
+                flags | View.DRAG_FLAG_ACCESSIBILITY_ACTION, null, 0, 0, 0, 0, 0, 0, 0, data);
         assertNotNull(mToken);
         r.run();
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/FrameRateSelectionPriorityTests.java b/services/tests/wmtests/src/com/android/server/wm/FrameRateSelectionPriorityTests.java
index c0a90b2..e77c14a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/FrameRateSelectionPriorityTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/FrameRateSelectionPriorityTests.java
@@ -19,10 +19,13 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyFloat;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.window.flags.Flags.explicitRefreshRateHints;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -62,9 +65,11 @@
 
     private static final FrameRateVote FRAME_RATE_VOTE_NONE = new FrameRateVote();
     private static final FrameRateVote FRAME_RATE_VOTE_60_EXACT =
-            new FrameRateVote(60, Surface.FRAME_RATE_COMPATIBILITY_EXACT);
+            new FrameRateVote(60, Surface.FRAME_RATE_COMPATIBILITY_EXACT,
+                    SurfaceControl.FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN);
     private static final FrameRateVote FRAME_RATE_VOTE_60_PREFERRED =
-            new FrameRateVote(60, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT);
+            new FrameRateVote(60, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT,
+                    SurfaceControl.FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN);
 
     WindowState createWindow(String name) {
         WindowState window = createWindow(null, TYPE_APPLICATION, name);
@@ -110,6 +115,8 @@
                 any(SurfaceControl.class), anyInt());
         verify(appWindow.getPendingTransaction(), never()).setFrameRate(
                 any(SurfaceControl.class), anyInt(), anyInt(), anyInt());
+        verify(appWindow.getPendingTransaction(), never()).setFrameRateSelectionStrategy(
+                any(SurfaceControl.class), anyInt());
     }
 
     @Test
@@ -140,6 +147,8 @@
                 appWindow.getSurfaceControl(), 1);
         verify(appWindow.getPendingTransaction(), never()).setFrameRate(
                 any(SurfaceControl.class), anyInt(), anyInt(), anyInt());
+        verify(appWindow.getPendingTransaction(), never()).setFrameRateSelectionStrategy(
+                any(SurfaceControl.class), anyInt());
     }
 
     @Test
@@ -175,8 +184,17 @@
                 appWindow.getSurfaceControl(), 0);
         verify(appWindow.getPendingTransaction(), times(2)).setFrameRateSelectionPriority(
                 appWindow.getSurfaceControl(), 1);
-        verify(appWindow.getPendingTransaction(), never()).setFrameRate(
-                any(SurfaceControl.class), anyInt(), anyInt(), anyInt());
+        verify(appWindow.getPendingTransaction(), times(1)).setFrameRate(
+                eq(appWindow.getSurfaceControl()), anyFloat(),
+                eq(Surface.FRAME_RATE_COMPATIBILITY_EXACT), eq(Surface.CHANGE_FRAME_RATE_ALWAYS));
+        if (explicitRefreshRateHints()) {
+            verify(appWindow.getPendingTransaction(), times(1)).setFrameRateSelectionStrategy(
+                    appWindow.getSurfaceControl(),
+                    SurfaceControl.FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN);
+        } else {
+            verify(appWindow.getPendingTransaction(), never()).setFrameRateSelectionStrategy(
+                    any(SurfaceControl.class), anyInt());
+        }
     }
 
     @Test
@@ -202,8 +220,17 @@
                 appWindow.getSurfaceControl(), RefreshRatePolicy.LAYER_PRIORITY_UNSET);
         verify(appWindow.getPendingTransaction()).setFrameRateSelectionPriority(
                 appWindow.getSurfaceControl(), 2);
-        verify(appWindow.getPendingTransaction(), never()).setFrameRate(
-                any(SurfaceControl.class), anyInt(), anyInt(), anyInt());
+        verify(appWindow.getPendingTransaction(), times(1)).setFrameRate(
+                eq(appWindow.getSurfaceControl()), anyFloat(),
+                eq(Surface.FRAME_RATE_COMPATIBILITY_EXACT), eq(Surface.CHANGE_FRAME_RATE_ALWAYS));
+        if (explicitRefreshRateHints()) {
+            verify(appWindow.getPendingTransaction(), times(1)).setFrameRateSelectionStrategy(
+                    appWindow.getSurfaceControl(),
+                    SurfaceControl.FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN);
+        } else {
+            verify(appWindow.getPendingTransaction(), never()).setFrameRateSelectionStrategy(
+                    any(SurfaceControl.class), anyInt());
+        }
     }
 
     @Test
@@ -229,6 +256,8 @@
                 appWindow.getSurfaceControl(), RefreshRatePolicy.LAYER_PRIORITY_UNSET);
         verify(appWindow.getPendingTransaction(), never()).setFrameRate(
                 any(SurfaceControl.class), anyInt(), anyInt(), anyInt());
+        verify(appWindow.getPendingTransaction(), never()).setFrameRateSelectionStrategy(
+                any(SurfaceControl.class), anyInt());
     }
 
     @Test
@@ -256,6 +285,14 @@
         verify(appWindow.getPendingTransaction(), times(1)).setFrameRate(
                 appWindow.getSurfaceControl(), 60,
                 Surface.FRAME_RATE_COMPATIBILITY_EXACT, Surface.CHANGE_FRAME_RATE_ALWAYS);
+        if (explicitRefreshRateHints()) {
+            verify(appWindow.getPendingTransaction(), times(1)).setFrameRateSelectionStrategy(
+                    appWindow.getSurfaceControl(),
+                    SurfaceControl.FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN);
+        } else {
+            verify(appWindow.getPendingTransaction(), never()).setFrameRateSelectionStrategy(
+                    any(SurfaceControl.class), anyInt());
+        }
     }
 
     @Test
@@ -283,6 +320,8 @@
                 appWindow.getSurfaceControl(), RefreshRatePolicy.LAYER_PRIORITY_UNSET);
         verify(appWindow.getPendingTransaction(), never()).setFrameRate(
                 any(SurfaceControl.class), anyInt(), anyInt(), anyInt());
+        verify(appWindow.getPendingTransaction(), never()).setFrameRateSelectionStrategy(
+                any(SurfaceControl.class), anyInt());
     }
 
     @Test
@@ -310,5 +349,13 @@
         verify(appWindow.getPendingTransaction(), times(1)).setFrameRate(
                 appWindow.getSurfaceControl(), 60,
                 Surface.FRAME_RATE_COMPATIBILITY_DEFAULT, Surface.CHANGE_FRAME_RATE_ALWAYS);
+        if (explicitRefreshRateHints()) {
+            verify(appWindow.getPendingTransaction(), times(1)).setFrameRateSelectionStrategy(
+                    appWindow.getSurfaceControl(),
+                    SurfaceControl.FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN);
+        } else {
+            verify(appWindow.getPendingTransaction(), never()).setFrameRateSelectionStrategy(
+                    any(SurfaceControl.class), anyInt());
+        }
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
index ffa1ed9..38a66a9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
@@ -19,10 +19,13 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+import static android.view.InsetsSource.ID_IME;
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+import static android.view.WindowInsets.Type.ime;
 import static android.view.WindowInsets.Type.navigationBars;
 import static android.view.WindowInsets.Type.statusBars;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_CONSUME_IME_INSETS;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
 import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
@@ -432,6 +435,56 @@
 
     }
 
+    @SetupWindows(addWindows = W_INPUT_METHOD)
+    @Test
+    public void testConsumeImeInsets() {
+        final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
+        final InsetsSource imeSource = new InsetsSource(ID_IME, ime());
+        imeSource.setVisible(true);
+        mImeWindow.mHasSurface = true;
+
+        final WindowState win1 = addWindow(TYPE_APPLICATION, "win1");
+        final WindowState win2 = addWindow(TYPE_APPLICATION, "win2");
+
+        win1.mAboveInsetsState.addSource(imeSource);
+        win1.mHasSurface = true;
+        win2.mAboveInsetsState.addSource(imeSource);
+        win2.mHasSurface = true;
+
+        assertTrue(mImeWindow.isVisible());
+        assertTrue(win1.isVisible());
+        assertTrue(win2.isVisible());
+
+        // Make sure both windows have visible IME insets.
+        assertTrue(win1.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
+        assertTrue(win2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
+
+        win2.mAttrs.privateFlags |= PRIVATE_FLAG_CONSUME_IME_INSETS;
+
+        displayPolicy.beginPostLayoutPolicyLw();
+        displayPolicy.applyPostLayoutPolicyLw(win2, win2.mAttrs, null, null);
+        displayPolicy.applyPostLayoutPolicyLw(win1, win1.mAttrs, null, null);
+        displayPolicy.finishPostLayoutPolicyLw();
+
+        // Make sure win2 doesn't have visible IME insets, but win1 still does.
+        assertTrue(win2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
+        assertFalse(win1.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
+        assertTrue(win1.getWindowFrames().hasInsetsChanged());
+
+        win2.mAttrs.privateFlags &= ~PRIVATE_FLAG_CONSUME_IME_INSETS;
+        win2.getWindowFrames().setInsetsChanged(false);
+
+        displayPolicy.beginPostLayoutPolicyLw();
+        displayPolicy.applyPostLayoutPolicyLw(win2, win2.mAttrs, null, null);
+        displayPolicy.applyPostLayoutPolicyLw(win1, win1.mAttrs, null, null);
+        displayPolicy.finishPostLayoutPolicyLw();
+
+        // Make sure both windows have visible IME insets.
+        assertTrue(win1.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
+        assertTrue(win2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
+        assertTrue(win1.getWindowFrames().hasInsetsChanged());
+    }
+
     private WindowState addNavigationBar() {
         final Binder owner = new Binder();
         final WindowState win = createWindow(null, TYPE_NAVIGATION_BAR, "navBar");
diff --git a/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java
index 49a8886..c9a83b0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import static android.view.SurfaceControl.FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN;
 import static android.view.SurfaceControl.RefreshRateRange.FLOAT_TOLERANCE;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 
@@ -69,15 +70,20 @@
 
     private static final FrameRateVote FRAME_RATE_VOTE_NONE = new FrameRateVote();
     private static final FrameRateVote FRAME_RATE_VOTE_DENY_LIST =
-            new FrameRateVote(LOW_REFRESH_RATE, Surface.FRAME_RATE_COMPATIBILITY_EXACT);
+            new FrameRateVote(LOW_REFRESH_RATE, Surface.FRAME_RATE_COMPATIBILITY_EXACT,
+                    FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN);
     private static final FrameRateVote FRAME_RATE_VOTE_LOW_EXACT =
-            new FrameRateVote(LOW_REFRESH_RATE, Surface.FRAME_RATE_COMPATIBILITY_EXACT);
+            new FrameRateVote(LOW_REFRESH_RATE, Surface.FRAME_RATE_COMPATIBILITY_EXACT,
+                    FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN);
     private static final FrameRateVote FRAME_RATE_VOTE_HI_EXACT =
-            new FrameRateVote(HI_REFRESH_RATE, Surface.FRAME_RATE_COMPATIBILITY_EXACT);
+            new FrameRateVote(HI_REFRESH_RATE, Surface.FRAME_RATE_COMPATIBILITY_EXACT,
+                    FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN);
     private static final FrameRateVote FRAME_RATE_VOTE_LOW_PREFERRED =
-            new FrameRateVote(LOW_REFRESH_RATE, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT);
+            new FrameRateVote(LOW_REFRESH_RATE, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT,
+                    FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN);
     private static final FrameRateVote FRAME_RATE_VOTE_HI_PREFERRED =
-            new FrameRateVote(HI_REFRESH_RATE, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT);
+            new FrameRateVote(HI_REFRESH_RATE, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT,
+                    FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN);
 
     // Parcel and Unparcel the LayoutParams in the window state to test the path the object
     // travels from the app's process to system server
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java b/services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java
index 7eab06a..89cd726 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java
@@ -1240,7 +1240,7 @@
         final ActivityRecord activity1 = finishTopActivity(rootTask1);
         assertEquals(DESTROYING, activity1.getState());
         verify(mRootWindowContainer).ensureVisibilityAndConfig(eq(null) /* starting */,
-                eq(display.mDisplayId), anyBoolean(), anyBoolean());
+                eq(display.mDisplayId), anyBoolean());
     }
 
     private ActivityRecord finishTopActivity(Task task) {
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 0608cf4..28fecd6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -838,7 +838,7 @@
                         .setSystemDecorations(true).build();
 
         doReturn(true).when(mRootWindowContainer)
-                .ensureVisibilityAndConfig(any(), anyInt(), anyBoolean(), anyBoolean());
+                .ensureVisibilityAndConfig(any(), anyInt(), anyBoolean());
         doReturn(true).when(mRootWindowContainer).canStartHomeOnDisplayArea(any(), any(),
                 anyBoolean());
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/TrustedPresentationCallbackTest.java b/services/tests/wmtests/src/com/android/server/wm/TrustedPresentationCallbackTest.java
deleted file mode 100644
index c5dd447..0000000
--- a/services/tests/wmtests/src/com/android/server/wm/TrustedPresentationCallbackTest.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wm;
-
-import static android.server.wm.ActivityManagerTestBase.createFullscreenActivityScenarioRule;
-import static android.server.wm.BuildUtils.HW_TIMEOUT_MULTIPLIER;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import android.app.Activity;
-import android.platform.test.annotations.Presubmit;
-import android.server.wm.CtsWindowInfoUtils;
-import android.view.SurfaceControl;
-import android.view.SurfaceControl.TrustedPresentationThresholds;
-
-import androidx.annotation.GuardedBy;
-import androidx.test.ext.junit.rules.ActivityScenarioRule;
-
-import com.android.server.wm.utils.CommonUtils;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TestName;
-
-import java.util.function.Consumer;
-
-/**
- * TODO (b/287076178): Move these tests to
- * {@link android.view.surfacecontrol.cts.TrustedPresentationCallbackTest} when API is made public
- */
-@Presubmit
-public class TrustedPresentationCallbackTest {
-    private static final String TAG = "TrustedPresentationCallbackTest";
-    private static final int STABILITY_REQUIREMENT_MS = 500;
-    private static final long WAIT_TIME_MS = HW_TIMEOUT_MULTIPLIER * 2000L;
-
-    private static final float FRACTION_VISIBLE = 0.1f;
-
-    private final Object mResultsLock = new Object();
-    @GuardedBy("mResultsLock")
-    private boolean mResult;
-    @GuardedBy("mResultsLock")
-    private boolean mReceivedResults;
-
-    @Rule
-    public TestName mName = new TestName();
-
-    @Rule
-    public ActivityScenarioRule<TestActivity> mActivityRule = createFullscreenActivityScenarioRule(
-            TestActivity.class);
-
-    private TestActivity mActivity;
-
-    @Before
-    public void setup() {
-        mActivityRule.getScenario().onActivity(activity -> mActivity = activity);
-    }
-
-    @After
-    public void tearDown() {
-        CommonUtils.waitUntilActivityRemoved(mActivity);
-    }
-
-    @Test
-    public void testAddTrustedPresentationListenerOnWindow() throws InterruptedException {
-        TrustedPresentationThresholds thresholds = new TrustedPresentationThresholds(
-                1 /* minAlpha */, FRACTION_VISIBLE, STABILITY_REQUIREMENT_MS);
-        SurfaceControl.Transaction t = new SurfaceControl.Transaction();
-        mActivity.getWindow().getRootSurfaceControl().addTrustedPresentationCallback(t, thresholds,
-                Runnable::run, inTrustedPresentationState -> {
-                    synchronized (mResultsLock) {
-                        mResult = inTrustedPresentationState;
-                        mReceivedResults = true;
-                        mResultsLock.notify();
-                    }
-                });
-        t.apply();
-        synchronized (mResultsLock) {
-            assertResults();
-        }
-    }
-
-    @Test
-    public void testRemoveTrustedPresentationListenerOnWindow() throws InterruptedException {
-        TrustedPresentationThresholds thresholds = new TrustedPresentationThresholds(
-                1 /* minAlpha */, FRACTION_VISIBLE, STABILITY_REQUIREMENT_MS);
-        Consumer<Boolean> trustedPresentationCallback = inTrustedPresentationState -> {
-            synchronized (mResultsLock) {
-                mResult = inTrustedPresentationState;
-                mReceivedResults = true;
-                mResultsLock.notify();
-            }
-        };
-        SurfaceControl.Transaction t = new SurfaceControl.Transaction();
-        mActivity.getWindow().getRootSurfaceControl().addTrustedPresentationCallback(t, thresholds,
-                Runnable::run, trustedPresentationCallback);
-        t.apply();
-
-        synchronized (mResultsLock) {
-            if (!mReceivedResults) {
-                mResultsLock.wait(WAIT_TIME_MS);
-            }
-            assertResults();
-            // reset the state
-            mReceivedResults = false;
-        }
-
-        mActivity.getWindow().getRootSurfaceControl().removeTrustedPresentationCallback(t,
-                trustedPresentationCallback);
-        t.apply();
-
-        synchronized (mResultsLock) {
-            if (!mReceivedResults) {
-                mResultsLock.wait(WAIT_TIME_MS);
-            }
-            // Ensure we waited the full time and never received a notify on the result from the
-            // callback.
-            assertFalse("Should never have received a callback", mReceivedResults);
-            // results shouldn't have changed.
-            assertTrue(mResult);
-        }
-    }
-
-    @GuardedBy("mResultsLock")
-    private void assertResults() throws InterruptedException {
-        mResultsLock.wait(WAIT_TIME_MS);
-
-        if (!mReceivedResults) {
-            CtsWindowInfoUtils.dumpWindowsOnScreen(TAG, "test " + mName.getMethodName());
-        }
-        // Make sure we received the results and not just timed out
-        assertTrue("Timed out waiting for results", mReceivedResults);
-        assertTrue(mResult);
-    }
-
-    public static class TestActivity extends Activity {
-    }
-}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 0e1e0c8..72db7fe 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -332,6 +332,7 @@
                         mUsageEventListeners.valueAt(i).onUsageEvent(userId, event);
                     }
                 }
+                return true;
             }
         }
         return false;
@@ -1973,6 +1974,8 @@
                 + ": " + Flags.userInteractionTypeApi());
         pw.println("    " + Flags.FLAG_USE_PARCELED_LIST
                 + ": " + Flags.useParceledList());
+        pw.println("    " + Flags.FLAG_FILTER_BASED_EVENT_QUERY_API
+                + ": " + Flags.filterBasedEventQueryApi());
 
         final int[] userIds;
         synchronized (mLock) {
@@ -2245,7 +2248,7 @@
             final int callingUid = Binder.getCallingUid();
             final int callingPid = Binder.getCallingPid();
             final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
-                    callingUid, userId);
+                    callingUid, UserHandle.getCallingUserId());
 
             final long token = Binder.clearCallingIdentity();
             try {
@@ -2275,6 +2278,12 @@
                         "Only the system or holders of the REPORT_USAGE_STATS"
                             + " permission are allowed to call reportUserInteraction");
                 }
+                if (userId != UserHandle.getCallingUserId()) {
+                    // Cross-user event reporting.
+                    getContext().enforceCallingPermission(
+                            Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+                            "Caller doesn't have INTERACT_ACROSS_USERS_FULL permission");
+                }
             } else {
                 if (!isCallingUidSystem()) {
                     throw new SecurityException("Only system is allowed to call"
@@ -2284,7 +2293,8 @@
 
             // Verify if this package exists before reporting an event for it.
             if (mPackageManagerInternal.getPackageUid(packageName, 0, userId) < 0) {
-                throw new IllegalArgumentException("Package " + packageName + "not exist!");
+                throw new IllegalArgumentException("Package " + packageName
+                        + " does not exist!");
             }
 
             final Event event = new Event(USER_INTERACTION, SystemClock.elapsedRealtime());
@@ -2384,6 +2394,7 @@
             if (!hasQueryPermission(callingPackage)) {
                 return null;
             }
+
             return queryEventsHelper(UserHandle.getCallingUserId(), query.getBeginTimeMillis(),
                     query.getEndTimeMillis(), callingPackage, query.getEventTypeFilter());
         }
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index b214591..c902d459 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -1569,13 +1569,13 @@
 
         @Override
         @EnforcePermission(android.Manifest.permission.MANAGE_HOTWORD_DETECTION)
-        public void setIsReceiveSandboxedTrainingDataAllowed(boolean allowed) {
-            super.setIsReceiveSandboxedTrainingDataAllowed_enforcePermission();
+        public void setShouldReceiveSandboxedTrainingData(boolean allowed) {
+            super.setShouldReceiveSandboxedTrainingData_enforcePermission();
 
             synchronized (this) {
                 if (mImpl == null) {
                     throw new IllegalStateException(
-                            "setIsReceiveSandboxedTrainingDataAllowed without running voice "
+                            "setShouldReceiveSandboxedTrainingData without running voice "
                                     + "interaction service");
                 }
 
@@ -2273,9 +2273,9 @@
 
         private boolean isCallerPreinstalledAssistant() {
             return mImpl != null
-                    && mImpl.mInfo.getServiceInfo().applicationInfo.uid == Binder.getCallingUid()
-                    && (mImpl.mInfo.getServiceInfo().applicationInfo.isSystemApp()
-                    || mImpl.mInfo.getServiceInfo().applicationInfo.isUpdatedSystemApp());
+                    && mImpl.getApplicationInfo().uid == Binder.getCallingUid()
+                    && (mImpl.getApplicationInfo().isSystemApp()
+                    || mImpl.getApplicationInfo().isUpdatedSystemApp());
         }
 
         private void setImplLocked(VoiceInteractionManagerServiceImpl impl) {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 3c4b58f..7e0cbad 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -40,6 +40,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.ParceledListSlice;
@@ -540,6 +541,10 @@
         return mInfo.getSupportsLocalInteraction();
     }
 
+    public ApplicationInfo getApplicationInfo() {
+        return mInfo.getServiceInfo().applicationInfo;
+    }
+
     public void startListeningVisibleActivityChangedLocked(@NonNull IBinder token) {
         if (DEBUG) {
             Slog.d(TAG, "startListeningVisibleActivityChangedLocked: token=" + token);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 1e68687..7cb2cc3 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -9593,6 +9593,84 @@
             "satellite_connection_hysteresis_sec_int";
 
     /**
+     * This threshold is used when connected to a non-terrestrial LTE network.
+     * A list of 4 NTN LTE RSRP thresholds above which a signal level is considered POOR,
+     * MODERATE, GOOD, or EXCELLENT, to be used in SignalStrength reporting.
+     *
+     * Note that the min and max thresholds are fixed at -140 and -44, as explained in
+     * TS 136.133 9.1.4 - RSRP Measurement Report Mapping.
+     * <p>
+     * See SignalStrength#MAX_LTE_RSRP and SignalStrength#MIN_LTE_RSRP. Any signal level outside
+     * these boundaries is considered invalid.
+     */
+    @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
+    public static final String KEY_NTN_LTE_RSRP_THRESHOLDS_INT_ARRAY =
+            "ntn_lte_rsrp_thresholds_int_array";
+
+    /**
+     * This threshold is used when connected to a non-terrestrial LTE network.
+     * A list of 4 customized NTN LTE Reference Signal Received Quality (RSRQ) thresholds.
+     *
+     * Reference: TS 136.133 v12.6.0 section 9.1.7 - RSRQ Measurement Report Mapping.
+     *
+     * 4 threshold integers must be within the boundaries [-34 dB, 3 dB], and the levels are:
+     *     "NONE: [-34, threshold1)"
+     *     "POOR: [threshold1, threshold2)"
+     *     "MODERATE: [threshold2, threshold3)"
+     *     "GOOD:  [threshold3, threshold4)"
+     *     "EXCELLENT:  [threshold4, 3]"
+     *
+     * This key is considered invalid if the format is violated. If the key is invalid or
+     * not configured, a default value set will apply.
+     */
+    @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
+    public static final String KEY_NTN_LTE_RSRQ_THRESHOLDS_INT_ARRAY =
+            "ntn_lte_rsrq_thresholds_int_array";
+
+    /**
+     * This threshold is used when connected to a non-terrestrial LTE network.
+     * A list of 4 customized NTN LTE Reference Signal Signal to Noise Ratio (RSSNR) thresholds.
+     *
+     * 4 threshold integers must be within the boundaries [-20 dB, 30 dB], and the levels are:
+     *     "NONE: [-20, threshold1)"
+     *     "POOR: [threshold1, threshold2)"
+     *     "MODERATE: [threshold2, threshold3)"
+     *     "GOOD:  [threshold3, threshold4)"
+     *     "EXCELLENT:  [threshold4, 30]"
+     *
+     * This key is considered invalid if the format is violated. If the key is invalid or
+     * not configured, a default value set will apply.
+     */
+    @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
+    public static final String KEY_NTN_LTE_RSSNR_THRESHOLDS_INT_ARRAY =
+            "ntn_lte_rssnr_thresholds_int_array";
+
+    /**
+     * This threshold is used when connected to a non-terrestrial LTE network.
+     * Bit-field integer to determine whether to use Reference Signal Received Power (RSRP),
+     * Reference Signal Received Quality (RSRQ), or/and Reference Signal Signal to Noise Ratio
+     * (RSSNR) for the number of NTN LTE signal bars and signal criteria reporting enabling.
+     *
+     * <p> If a measure is not set, signal criteria reporting from modem will not be triggered and
+     * not be used for calculating signal level. If multiple measures are set bit, the parameter
+     * whose value is smallest is used to indicate the signal level.
+     * <UL>
+     *  <LI>RSRP = 1 << 0</LI>
+     *  <LI>RSRQ = 1 << 1</LI>
+     *  <LI>RSSNR = 1 << 2</LI>
+     * </UL>
+     * <p> The value of this key must be bitwise OR of CellSignalStrengthLte#USE_RSRP,
+     * CellSignalStrengthLte#USE_RSRQ, CellSignalStrengthLte#USE_RSSNR.
+     *
+     * <p> For example, if both RSRP and RSRQ are used, the value of key is 3 (1 << 0 | 1 << 1).
+     * If the key is invalid or not configured, a default value (RSRP = 1 << 0) will apply.
+     *
+     */
+    @FlaggedApi(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
+    public static final String KEY_PARAMETERS_USED_FOR_NTN_LTE_SIGNAL_BAR_INT =
+            "parameters_used_for_ntn_lte_signal_bar_int";
+
+    /**
      * Indicating whether DUN APN should be disabled when the device is roaming. In that case,
      * the default APN (i.e. internet) will be used for tethering.
      *
@@ -9814,7 +9892,6 @@
      *
      * @see TelephonyManager#PURCHASE_PREMIUM_CAPABILITY_RESULT_USER_CANCELED
      * @see TelephonyManager#PURCHASE_PREMIUM_CAPABILITY_RESULT_TIMEOUT
-     * @see TelephonyManager#PURCHASE_PREMIUM_CAPABILITY_RESULT_USER_DISABLED
      */
     public static final String
             KEY_PREMIUM_CAPABILITY_NOTIFICATION_BACKOFF_HYSTERESIS_TIME_MILLIS_LONG =
@@ -10628,6 +10705,32 @@
                 PersistableBundle.EMPTY);
         sDefaults.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, false);
         sDefaults.putInt(KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT, 300);
+        sDefaults.putIntArray(KEY_NTN_LTE_RSRP_THRESHOLDS_INT_ARRAY,
+                // Boundaries: [-140 dBm, -44 dBm]
+                new int[]{
+                        -128, /* SIGNAL_STRENGTH_POOR */
+                        -118, /* SIGNAL_STRENGTH_MODERATE */
+                        -108, /* SIGNAL_STRENGTH_GOOD */
+                        -98  /* SIGNAL_STRENGTH_GREAT */
+                });
+        sDefaults.putIntArray(KEY_NTN_LTE_RSRQ_THRESHOLDS_INT_ARRAY,
+                // Boundaries: [-34 dB, 3 dB]
+                new int[]{
+                        -20, /* SIGNAL_STRENGTH_POOR */
+                        -17, /* SIGNAL_STRENGTH_MODERATE */
+                        -14, /* SIGNAL_STRENGTH_GOOD */
+                        -11  /* SIGNAL_STRENGTH_GREAT */
+                });
+        sDefaults.putIntArray(KEY_NTN_LTE_RSSNR_THRESHOLDS_INT_ARRAY,
+                // Boundaries: [-20 dBm, 30 dBm]
+                new int[] {
+                        -3, /* SIGNAL_STRENGTH_POOR */
+                        1, /* SIGNAL_STRENGTH_MODERATE */
+                        5,  /* SIGNAL_STRENGTH_GOOD */
+                        13   /* SIGNAL_STRENGTH_GREAT */
+                });
+        sDefaults.putInt(KEY_PARAMETERS_USED_FOR_NTN_LTE_SIGNAL_BAR_INT,
+                CellSignalStrengthLte.USE_RSRP);
         sDefaults.putBoolean(KEY_DISABLE_DUN_APN_WHILE_ROAMING_WITH_PRESET_APN_BOOL, false);
         sDefaults.putString(KEY_DEFAULT_PREFERRED_APN_NAME_STRING, "");
         sDefaults.putBoolean(KEY_SUPPORTS_CALL_COMPOSER_BOOL, false);
diff --git a/telephony/java/android/telephony/CarrierRestrictionRules.java b/telephony/java/android/telephony/CarrierRestrictionRules.java
index eac4d16..cc768bc 100644
--- a/telephony/java/android/telephony/CarrierRestrictionRules.java
+++ b/telephony/java/android/telephony/CarrierRestrictionRules.java
@@ -16,12 +16,16 @@
 
 package android.telephony;
 
+import android.annotation.FlaggedApi;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.service.carrier.CarrierIdentifier;
+import android.telephony.TelephonyManager.CarrierRestrictionStatus;
+
+import com.android.internal.telephony.flags.Flags;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -104,7 +108,7 @@
     private int mCarrierRestrictionDefault;
     @MultiSimPolicy
     private int mMultiSimPolicy;
-    @TelephonyManager.CarrierRestrictionStatus
+    @CarrierRestrictionStatus
     private int mCarrierRestrictionStatus;
 
     private CarrierRestrictionRules() {
@@ -293,8 +297,22 @@
         return true;
     }
 
-    /** @hide */
-    public int getCarrierRestrictionStatus() {
+    /**
+     * Get the carrier restriction status of the device.
+     * The return value of the API is as follows.
+     * <ul>
+     *      <li>return {@link TelephonyManager#CARRIER_RESTRICTION_STATUS_RESTRICTED_TO_CALLER}
+     *      if the caller and the device locked by the network are same</li>
+     *      <li>return {@link TelephonyManager#CARRIER_RESTRICTION_STATUS_RESTRICTED} if the
+     *      caller and the device locked by the network are different</li>
+     *      <li>return {@link TelephonyManager#CARRIER_RESTRICTION_STATUS_NOT_RESTRICTED} if the
+     *      device is not locked</li>
+     *      <li>return {@link TelephonyManager#CARRIER_RESTRICTION_STATUS_UNKNOWN} if the device
+     *      locking state is unavailable or radio does not supports the feature</li>
+     * </ul>
+     */
+    @FlaggedApi(Flags.FLAG_CARRIER_RESTRICTION_STATUS)
+    public @CarrierRestrictionStatus int getCarrierRestrictionStatus() {
         return mCarrierRestrictionStatus;
     }
 
diff --git a/telephony/java/android/telephony/CellSignalStrengthLte.java b/telephony/java/android/telephony/CellSignalStrengthLte.java
index 5e90261..f528263 100644
--- a/telephony/java/android/telephony/CellSignalStrengthLte.java
+++ b/telephony/java/android/telephony/CellSignalStrengthLte.java
@@ -263,29 +263,35 @@
             rssnrThresholds = sRssnrThresholds;
             rsrpOnly = false;
         } else {
-            mParametersUseForLevel = cc.getInt(
-                    CarrierConfigManager.KEY_PARAMETERS_USED_FOR_LTE_SIGNAL_BAR_INT);
-            if (DBG) {
-                Rlog.i(LOG_TAG, "Using signal strength level: " + mParametersUseForLevel);
+            if (ss != null && ss.isUsingNonTerrestrialNetwork()) {
+                if (DBG) log("updateLevel: from NTN_LTE");
+                mParametersUseForLevel = cc.getInt(
+                        CarrierConfigManager.KEY_PARAMETERS_USED_FOR_NTN_LTE_SIGNAL_BAR_INT);
+                rsrpThresholds = cc.getIntArray(
+                        CarrierConfigManager.KEY_NTN_LTE_RSRP_THRESHOLDS_INT_ARRAY);
+                rsrqThresholds = cc.getIntArray(
+                        CarrierConfigManager.KEY_NTN_LTE_RSRQ_THRESHOLDS_INT_ARRAY);
+                rssnrThresholds = cc.getIntArray(
+                        CarrierConfigManager.KEY_NTN_LTE_RSSNR_THRESHOLDS_INT_ARRAY);
+            } else {
+                mParametersUseForLevel = cc.getInt(
+                        CarrierConfigManager.KEY_PARAMETERS_USED_FOR_LTE_SIGNAL_BAR_INT);
+                rsrpThresholds = cc.getIntArray(
+                        CarrierConfigManager.KEY_LTE_RSRP_THRESHOLDS_INT_ARRAY);
+                rsrqThresholds = cc.getIntArray(
+                        CarrierConfigManager.KEY_LTE_RSRQ_THRESHOLDS_INT_ARRAY);
+                rssnrThresholds = cc.getIntArray(
+                        CarrierConfigManager.KEY_LTE_RSSNR_THRESHOLDS_INT_ARRAY);
             }
-            rsrpThresholds = cc.getIntArray(
-                    CarrierConfigManager.KEY_LTE_RSRP_THRESHOLDS_INT_ARRAY);
             if (rsrpThresholds == null) rsrpThresholds = sRsrpThresholds;
-            if (DBG) {
-                Rlog.i(LOG_TAG, "Applying LTE RSRP Thresholds: "
-                        + Arrays.toString(rsrpThresholds));
-            }
-            rsrqThresholds = cc.getIntArray(
-                    CarrierConfigManager.KEY_LTE_RSRQ_THRESHOLDS_INT_ARRAY);
             if (rsrqThresholds == null) rsrqThresholds = sRsrqThresholds;
-            if (DBG) {
-                Rlog.i(LOG_TAG, "Applying LTE RSRQ Thresholds: "
-                        + Arrays.toString(rsrqThresholds));
-            }
-            rssnrThresholds = cc.getIntArray(
-                    CarrierConfigManager.KEY_LTE_RSSNR_THRESHOLDS_INT_ARRAY);
             if (rssnrThresholds == null) rssnrThresholds = sRssnrThresholds;
             if (DBG) {
+                Rlog.i(LOG_TAG, "Using signal strength level: " + mParametersUseForLevel);
+                Rlog.i(LOG_TAG, "Applying LTE RSRP Thresholds: "
+                        + Arrays.toString(rsrpThresholds));
+                Rlog.i(LOG_TAG, "Applying LTE RSRQ Thresholds: "
+                        + Arrays.toString(rsrqThresholds));
                 Rlog.i(LOG_TAG, "Applying LTE RSSNR Thresholds: "
                         + Arrays.toString(rssnrThresholds));
             }
diff --git a/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java b/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java
index a004cc3..2506360 100644
--- a/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java
+++ b/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java
@@ -16,6 +16,7 @@
 
 package android.telephony;
 
+import android.annotation.WorkerThread;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Build;
 import android.text.Editable;
@@ -39,6 +40,9 @@
  * </ul>
  * <p>
  * The formatting will be restarted once the text is cleared.
+ *
+ * @deprecated This is a thin wrapper on a `libphonenumber` `AsYouTypeFormatter`; it is recommended
+ * to use that instead.
  */
 public class PhoneNumberFormattingTextWatcher implements TextWatcher {
 
@@ -69,6 +73,7 @@
      * @param countryCode the ISO 3166-1 two-letter country code that indicates the country/region
      * where the phone number is being entered.
      */
+    @WorkerThread
     public PhoneNumberFormattingTextWatcher(String countryCode) {
         if (countryCode == null) throw new IllegalArgumentException();
         mFormatter = PhoneNumberUtil.getInstance().getAsYouTypeFormatter(countryCode);
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index e12a815..326b6f5 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -109,10 +109,6 @@
  * Then for SDK 35+, if the caller identity is personal profile, then
  * {@link #getActiveSubscriptionInfoList} will return subscription 1 only and vice versa.
  *
- * <p>If the caller needs to see all subscriptions across user profiles,
- * use {@link #createForAllUserProfiles} to convert the instance to see all. Additional permission
- * may be required as documented on the each API.
- *
  */
 @SystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE)
 @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
@@ -1512,8 +1508,14 @@
     public void addOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) {
         if (listener == null) return;
 
-        addOnSubscriptionsChangedListener(
-                new HandlerExecutor(new Handler(listener.getCreatorLooper())), listener);
+        Looper looper = listener.getCreatorLooper();
+        if (looper == null) {
+            throw new RuntimeException(
+                    "Can't create handler inside thread " + Thread.currentThread()
+                    + " that has not called Looper.prepare()");
+        }
+
+        addOnSubscriptionsChangedListener(new HandlerExecutor(new Handler(looper)), listener);
     }
 
     /**
@@ -1815,9 +1817,6 @@
      * Then for SDK 35+, if the caller identity is personal profile, then this will return
      * subscription 1 only and vice versa.
      *
-     * <p>If the caller needs to see all subscriptions across user profiles,
-     * use {@link #createForAllUserProfiles} to convert this instance to see all.
-     *
      * <p> The records will be sorted by {@link SubscriptionInfo#getSimSlotIndex} then by
      * {@link SubscriptionInfo#getSubscriptionId}.
      *
@@ -2085,9 +2084,6 @@
      * Android SDK 35(V) and above, while Android SDK 34(U) and below can see all subscriptions as
      * it does today.
      *
-     * <p>If the caller needs to see all subscriptions across user profiles,
-     * use {@link #createForAllUserProfiles} to convert this instance to see all.
-     *
      * @return The current number of active subscriptions.
      *
      * @see #getActiveSubscriptionInfoList()
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index b96914e..55a3da5 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -47,6 +47,7 @@
 import android.compat.Compatibility;
 import android.compat.annotation.ChangeId;
 import android.compat.annotation.EnabledAfter;
+import android.compat.annotation.EnabledSince;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
@@ -420,6 +421,14 @@
     /** @hide */
     public static final String PROPERTY_ENABLE_NULL_CIPHER_TOGGLE = "enable_null_cipher_toggle";
 
+    /**
+     * To apply the enforcement telephony feature and API
+     * @hide
+     */
+    @ChangeId
+    @EnabledSince(targetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM)
+    public static final long ENABLE_FEATURE_MAPPING = 297989574L;
+
     private final Context mContext;
     private final int mSubId;
     @UnsupportedAppUsage
@@ -18009,6 +18018,64 @@
     }
 
     /**
+     * Enable or disable notifications sent for cellular identifier disclosure events.
+     *
+     * Disclosure events are defined as instances where a device has sent a cellular identifier
+     * on the Non-access stratum (NAS) before a security context is established. As a result the
+     * identifier is sent in the clear, which has privacy implications for the user.
+     *
+     * @param enable if notifications about disclosure events should be enabled
+     * @throws IllegalStateException if the Telephony process is not currently available
+     * @throws SecurityException if the caller does not have the required privileges
+     * @throws UnsupportedOperationException if the modem does not support this feature.
+     *
+     * @hide
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY)
+    @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+    @SystemApi
+    public void setEnableCellularIdentifierDisclosureNotifications(boolean enable) {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                telephony.setEnableCellularIdentifierDisclosureNotifications(enable);
+            } else {
+                throw new IllegalStateException("telephony service is null.");
+            }
+        } catch (RemoteException ex) {
+            Rlog.e(TAG, "setEnableCellularIdentifierDisclosureNotifications RemoteException", ex);
+            ex.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Get whether or not cellular identifier disclosure notifications are enabled.
+     *
+     * @throws IllegalStateException if the Telephony process is not currently available
+     * @throws SecurityException if the caller does not have the required privileges
+     * @throws UnsupportedOperationException if the modem does not support this feature.
+     *
+     * @hide
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY)
+    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    @SystemApi
+    public boolean isCellularIdentifierDisclosureNotificationsEnabled() {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.isCellularIdentifierDisclosureNotificationsEnabled();
+            } else {
+                throw new IllegalStateException("telephony service is null.");
+            }
+        } catch (RemoteException ex) {
+            Rlog.e(TAG, "isCellularIdentifierDisclosureNotificationsEnabled RemoteException", ex);
+            ex.rethrowFromSystemServer();
+        }
+        return false;
+    }
+
+    /**
      * Get current cell broadcast message identifier ranges.
      *
      * @throws SecurityException if the caller does not have the required permission
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index 3e87872..8679bd4 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -1866,7 +1866,7 @@
         private int mCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
         private int mSkip464Xlat = Carriers.SKIP_464XLAT_DEFAULT;
         private boolean mAlwaysOn;
-        private int mInfrastructureBitmask = INFRASTRUCTURE_CELLULAR;
+        private int mInfrastructureBitmask = INFRASTRUCTURE_CELLULAR | INFRASTRUCTURE_SATELLITE;
         private boolean mEsimBootstrapProvisioning;
 
         /**
diff --git a/telephony/java/android/telephony/satellite/NtnSignalStrength.java b/telephony/java/android/telephony/satellite/NtnSignalStrength.java
index 16d7654..2fec423 100644
--- a/telephony/java/android/telephony/satellite/NtnSignalStrength.java
+++ b/telephony/java/android/telephony/satellite/NtnSignalStrength.java
@@ -86,6 +86,9 @@
         readFromParcel(in);
     }
 
+    /**
+     * Returns notified non-terrestrial network signal strength level.
+     */
     @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
     @NtnSignalStrengthLevel public int getLevel() {
         return mLevel;
diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java
index 71786b3..e09bd20 100644
--- a/telephony/java/android/telephony/satellite/SatelliteManager.java
+++ b/telephony/java/android/telephony/satellite/SatelliteManager.java
@@ -34,6 +34,7 @@
 import android.os.OutcomeReceiver;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
+import android.os.ServiceSpecificException;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyCallback;
 import android.telephony.TelephonyFrameworkInitializer;
@@ -1919,7 +1920,6 @@
      */
     @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
     @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
-    @NonNull
     public void requestNtnSignalStrength(@NonNull @CallbackExecutor Executor executor,
             @NonNull OutcomeReceiver<NtnSignalStrength, SatelliteException> callback) {
         Objects.requireNonNull(executor);
@@ -1962,6 +1962,8 @@
 
     /**
      * Registers for NTN signal strength changed from satellite modem.
+     * If the registration operation is not successful, a {@link SatelliteException} that contains
+     * {@link SatelliteResult} will be thrown.
      *
      * <p>
      * Note: This API is specifically designed for OEM enabled satellite connectivity only.
@@ -1973,16 +1975,14 @@
      * @param executor The executor on which the callback will be called.
      * @param callback The callback to handle the NTN signal strength changed event.
      *
-     * @return The {@link SatelliteResult} result of the operation.
-     *
      * @throws SecurityException if the caller doesn't have required permission.
      * @throws IllegalStateException if the Telephony process is not currently available.
+     * @throws SatelliteException if the callback registration operation fails.
      */
     @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
     @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
-    @SatelliteResult public int registerForNtnSignalStrengthChanged(
-            @NonNull @CallbackExecutor Executor executor,
-            @NonNull NtnSignalStrengthCallback callback) {
+    public void registerForNtnSignalStrengthChanged(@NonNull @CallbackExecutor Executor executor,
+            @NonNull NtnSignalStrengthCallback callback) throws SatelliteException {
         Objects.requireNonNull(executor);
         Objects.requireNonNull(callback);
 
@@ -1999,16 +1999,18 @@
                                                 ntnSignalStrength)));
                             }
                         };
+                telephony.registerForNtnSignalStrengthChanged(mSubId, internalCallback);
                 sNtnSignalStrengthCallbackMap.put(callback, internalCallback);
-                return telephony.registerForNtnSignalStrengthChanged(mSubId, internalCallback);
             } else {
                 throw new IllegalStateException("Telephony service is null.");
             }
+        } catch (ServiceSpecificException ex) {
+            logd("registerForNtnSignalStrengthChanged() registration fails: " + ex.errorCode);
+            throw new SatelliteException(ex.errorCode);
         } catch (RemoteException ex) {
             loge("registerForNtnSignalStrengthChanged() RemoteException: " + ex);
             ex.rethrowFromSystemServer();
         }
-        return SATELLITE_RESULT_REQUEST_FAILED;
     }
 
     /**
@@ -2025,6 +2027,8 @@
      * {@link #registerForNtnSignalStrengthChanged(Executor, NtnSignalStrengthCallback)}.
      *
      * @throws SecurityException if the caller doesn't have required permission.
+     * @throws IllegalArgumentException if the callback is not valid or has already been
+     * unregistered.
      * @throws IllegalStateException if the Telephony process is not currently available.
      */
     @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
@@ -2041,6 +2045,7 @@
                     telephony.unregisterForNtnSignalStrengthChanged(mSubId, internalCallback);
                 } else {
                     loge("unregisterForNtnSignalStrengthChanged: No internal callback.");
+                    throw new IllegalArgumentException("callback is not valid");
                 }
             } else {
                 throw new IllegalStateException("Telephony service is null.");
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 4c53f8a..37752d0 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -3101,16 +3101,21 @@
     void requestNtnSignalStrength(int subId, in ResultReceiver receiver);
 
     /**
-     * Registers for NTN signal strength changed from satellite modem.
+     * Registers for NTN signal strength changed from satellite modem. If the registration operation
+     * is not successful, a {@link SatelliteException} that contains {@link SatelliteResult} will be
+     * thrown.
      *
      * @param subId The subId of the subscription to request for.
-     * @param callback The callback to handle the NTN signal strength changed event.
-     *
-     * @return The {@link SatelliteResult} result of the operation.
+     * @param callback The callback to handle the NTN signal strength changed event. If the
+     * operation is successful, {@link NtnSignalStrengthCallback#onNtnSignalStrengthChanged(
+     * NtnSignalStrength)} will return an instance of {@link NtnSignalStrength} with a value of
+     * {@link NtnSignalStrength.NtnSignalStrengthLevel} when the signal strength of non-terrestrial
+     * network has changed.
      */
     @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
             + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
-    int registerForNtnSignalStrengthChanged(int subId, in INtnSignalStrengthCallback callback);
+    void registerForNtnSignalStrengthChanged(int subId,
+            in INtnSignalStrengthCallback callback);
 
     /**
      * Unregisters for NTN signal strength changed from satellite modem.
@@ -3159,4 +3164,37 @@
      * @return {@code true} if the operation is successful, {@code false} otherwise.
      */
     boolean setShouldSendDatagramToModemInDemoMode(boolean shouldSendToModemInDemoMode);
+
+    /**
+     * Enable or disable notifications sent for cellular identifier disclosure events.
+     *
+     * Disclosure events are defined as instances where a device has sent a cellular identifier
+     * on the Non-access stratum (NAS) before a security context is established. As a result the
+     * identifier is sent in the clear, which has privacy implications for the user.
+     *
+     * <p>Requires permission: android.Manifest.MODIFY_PHONE_STATE</p>
+     *
+     * @param enabled if notifications about disclosure events should be enabled
+     * @throws IllegalStateException if the Telephony process is not currently available
+     * @throws SecurityException if the caller does not have the required privileges
+     * @throws UnsupportedOperationException if the modem does not support this feature.
+     * @hide
+     */
+    @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+        + "android.Manifest.permission.MODIFY_PHONE_STATE)")
+    void setEnableCellularIdentifierDisclosureNotifications(boolean enable);
+
+    /**
+     * Get whether or not cellular identifier disclosure notifications are enabled.
+     *
+     * <p>Requires permission: android.Manifest.READ_PRIVILEGED_PHONE_STATE</p>
+     *
+     * @throws IllegalStateException if the Telephony process is not currently available
+     * @throws SecurityException if the caller does not have the required privileges
+     * @throws UnsupportedOperationException if the modem does not support this feature.
+     * @hide
+     */
+    @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+        + "android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)")
+    boolean isCellularIdentifierDisclosureNotificationsEnabled();
 }
diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/pip/SecondaryActivityEnterPipTest.kt b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/pip/SecondaryActivityEnterPipTest.kt
index 12a57d5..c8cac8f 100644
--- a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/pip/SecondaryActivityEnterPipTest.kt
+++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/pip/SecondaryActivityEnterPipTest.kt
@@ -25,6 +25,7 @@
 import android.tools.device.flicker.legacy.FlickerBuilder
 import android.tools.device.flicker.legacy.LegacyFlickerTest
 import android.tools.device.flicker.legacy.LegacyFlickerTestFactory
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
 import com.android.server.wm.flicker.activityembedding.ActivityEmbeddingTestBase
 import com.android.server.wm.flicker.helpers.ActivityEmbeddingAppHelper
@@ -142,7 +143,7 @@
     }
 
     /** During the transition Secondary Activity shrinks to the bottom right corner. */
-    @Presubmit
+    @FlakyTest(bugId = 315605409)
     @Test
     fun secondaryLayerShrinks() {
         flicker.assertLayers {
diff --git a/tools/aapt2/integration-tests/SymlinkTest/Android.bp b/tools/aapt2/integration-tests/SymlinkTest/Android.bp
index 15a6a20..6fcdf1c 100644
--- a/tools/aapt2/integration-tests/SymlinkTest/Android.bp
+++ b/tools/aapt2/integration-tests/SymlinkTest/Android.bp
@@ -27,4 +27,7 @@
     name: "AaptSymlinkTest",
     sdk_version: "current",
     use_resource_processor: false,
+    compile_data: [
+        "targets/*",
+    ],
 }
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/LongArrayMultiStateCounter_host.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/LongArrayMultiStateCounter_host.java
new file mode 100644
index 0000000..a135623
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/LongArrayMultiStateCounter_host.java
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.hoststubgen.nativesubstitution;
+
+import android.os.BadParcelableException;
+import android.os.Parcel;
+
+import java.util.Arrays;
+import java.util.HashMap;
+
+/**
+ * Native implementation substitutions for the LongArrayMultiStateCounter class.
+ */
+public class LongArrayMultiStateCounter_host {
+
+    /**
+     * A reimplementation of {@link com.android.internal.os.LongArrayMultiStateCounter}, only in
+     * Java instead of native.  The majority of the code (in C++) can be found in
+     * /frameworks/native/libs/battery/MultiStateCounter.h
+     */
+    private static class LongArrayMultiStateCounterRavenwood {
+        private final int mStateCount;
+        private final int mArrayLength;
+        private int mCurrentState;
+        private long mLastStateChangeTimestampMs = -1;
+        private long mLastUpdateTimestampMs = -1;
+        private boolean mEnabled = true;
+
+        private static class State {
+            private long mTimeInStateSinceUpdate;
+            private long[] mCounter;
+        }
+
+        private final State[] mStates;
+        private final long[] mValues;
+        private final long[] mDelta;
+
+        LongArrayMultiStateCounterRavenwood(int stateCount, int arrayLength) {
+            mStateCount = stateCount;
+            mArrayLength = arrayLength;
+            mStates = new State[stateCount];
+            for (int i = 0; i < mStateCount; i++) {
+                mStates[i] = new State();
+                mStates[i].mCounter = new long[mArrayLength];
+            }
+            mValues = new long[mArrayLength];
+            mDelta = new long[mArrayLength];
+        }
+
+        public void setEnabled(boolean enabled, long timestampMs) {
+            if (enabled == mEnabled) {
+                return;
+            }
+
+            if (!enabled) {
+                setState(mCurrentState, timestampMs);
+                mEnabled = false;
+            } else {
+                if (timestampMs < mLastUpdateTimestampMs) {
+                    timestampMs = mLastUpdateTimestampMs;
+                }
+
+                if (mLastStateChangeTimestampMs >= 0) {
+                    mLastStateChangeTimestampMs = timestampMs;
+                }
+                mEnabled = true;
+            }
+        }
+
+        public void setState(int state, long timestampMs) {
+            if (mEnabled && mLastStateChangeTimestampMs >= 0 && mLastUpdateTimestampMs >= 0) {
+                if (timestampMs < mLastUpdateTimestampMs) {
+                    timestampMs = mLastUpdateTimestampMs;
+                }
+
+                if (timestampMs >= mLastStateChangeTimestampMs) {
+                    mStates[mCurrentState].mTimeInStateSinceUpdate +=
+                            timestampMs - mLastStateChangeTimestampMs;
+                } else {
+                    for (int i = 0; i < mStateCount; i++) {
+                        mStates[i].mTimeInStateSinceUpdate = 0;
+                    }
+                }
+            }
+            mCurrentState = state;
+            mLastStateChangeTimestampMs = timestampMs;
+        }
+
+        public void setValue(int state, long[] values) {
+            System.arraycopy(values, 0, mStates[state].mCounter, 0, mArrayLength);
+        }
+
+        public void updateValue(long[] values, long timestampMs) {
+            if (mEnabled || mLastUpdateTimestampMs < mLastStateChangeTimestampMs) {
+                if (timestampMs < mLastStateChangeTimestampMs) {
+                    timestampMs = mLastStateChangeTimestampMs;
+                }
+
+                setState(mCurrentState, timestampMs);
+
+                if (mLastUpdateTimestampMs >= 0) {
+                    if (timestampMs > mLastUpdateTimestampMs) {
+                        if (delta(mValues, values, mDelta)) {
+                            long timeSinceUpdate = timestampMs - mLastUpdateTimestampMs;
+                            for (int i = 0; i < mStateCount; i++) {
+                                long timeInState = mStates[i].mTimeInStateSinceUpdate;
+                                if (timeInState > 0) {
+                                    add(mStates[i].mCounter, mDelta, timeInState, timeSinceUpdate);
+                                    mStates[i].mTimeInStateSinceUpdate = 0;
+                                }
+                            }
+                        } else {
+                            throw new RuntimeException();
+                        }
+                    } else if (timestampMs < mLastUpdateTimestampMs) {
+                        throw new RuntimeException();
+                    }
+                }
+            }
+            System.arraycopy(values, 0, mValues, 0, mArrayLength);
+            mLastUpdateTimestampMs = timestampMs;
+        }
+
+        public void incrementValues(long[] delta, long timestampMs) {
+            long[] values = Arrays.copyOf(mValues, mValues.length);
+            for (int i = 0; i < mArrayLength; i++) {
+                values[i] += delta[i];
+            }
+            updateValue(values, timestampMs);
+        }
+
+        public void getValues(long[] values, int state) {
+            System.arraycopy(mStates[state].mCounter, 0, values, 0, mArrayLength);
+        }
+
+        public void reset() {
+            mLastStateChangeTimestampMs = -1;
+            mLastUpdateTimestampMs = -1;
+            for (int i = 0; i < mStateCount; i++) {
+                mStates[i].mTimeInStateSinceUpdate = 0;
+                Arrays.fill(mStates[i].mCounter, 0);
+            }
+        }
+
+        public void writeToParcel(Parcel parcel) {
+            parcel.writeInt(mStateCount);
+            parcel.writeInt(mArrayLength);
+            for (int i = 0; i < mStateCount; i++) {
+                parcel.writeLongArray(mStates[i].mCounter);
+            }
+        }
+
+        public void initFromParcel(Parcel parcel) {
+            try {
+                for (int i = 0; i < mStateCount; i++) {
+                    parcel.readLongArray(mStates[i].mCounter);
+                }
+            } catch (Exception e) {
+                throw new BadParcelableException(e);
+            }
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            sb.append("[");
+            for (int state = 0; state < mStateCount; state++) {
+                if (state != 0) {
+                    sb.append(", ");
+                }
+                sb.append(state).append(": {");
+                for (int i = 0; i < mStates[state].mCounter.length; i++) {
+                    if (i != 0) {
+                        sb.append(", ");
+                    }
+                    sb.append(mStates[state].mCounter[i]);
+                }
+                sb.append("}");
+            }
+            sb.append("]");
+            if (mLastUpdateTimestampMs >= 0) {
+                sb.append(" updated: ").append(mLastUpdateTimestampMs);
+            }
+            if (mLastStateChangeTimestampMs >= 0) {
+                sb.append(" currentState: ").append(mCurrentState);
+                if (mLastStateChangeTimestampMs > mLastUpdateTimestampMs) {
+                    sb.append(" stateChanged: ").append(mLastStateChangeTimestampMs);
+                }
+            } else {
+                sb.append(" currentState: none");
+            }
+            return sb.toString();
+        }
+
+        private boolean delta(long[] values1, long[] values2, long[] delta) {
+            if (delta.length != mArrayLength) {
+                throw new RuntimeException();
+            }
+
+            boolean is_delta_valid = true;
+            for (int i = 0; i < mArrayLength; i++) {
+                if (values2[i] >= values1[i]) {
+                    delta[i] = values2[i] - values1[i];
+                } else {
+                    delta[i] = 0;
+                    is_delta_valid = false;
+                }
+            }
+
+            return is_delta_valid;
+        }
+
+        private void add(long[] counter, long[] delta, long numerator, long denominator) {
+            if (numerator != denominator) {
+                for (int i = 0; i < mArrayLength; i++) {
+                    counter[i] += delta[i] * numerator / denominator;
+                }
+            } else {
+                for (int i = 0; i < mArrayLength; i++) {
+                    counter[i] += delta[i];
+                }
+            }
+        }
+    }
+
+    public static class LongArrayContainer_host {
+        private static final HashMap<Long, long[]> sInstances = new HashMap<>();
+        private static long sNextId = 1;
+
+        public static long native_init(int arrayLength) {
+            long[] array = new long[arrayLength];
+            long instanceId = sNextId++;
+            sInstances.put(instanceId, array);
+            return instanceId;
+        }
+
+        static long[] getInstance(long instanceId) {
+            return sInstances.get(instanceId);
+        }
+
+        public static void native_setValues(long instanceId, long[] values) {
+            System.arraycopy(values, 0, getInstance(instanceId), 0, values.length);
+        }
+
+        public static void native_getValues(long instanceId, long[] values) {
+            System.arraycopy(getInstance(instanceId), 0, values, 0, values.length);
+        }
+
+        public static boolean native_combineValues(long instanceId, long[] array, int[] indexMap) {
+            long[] values = getInstance(instanceId);
+
+            boolean nonZero = false;
+            Arrays.fill(array, 0);
+
+            for (int i = 0; i < values.length; i++) {
+                int index = indexMap[i];
+                if (index < 0 || index >= array.length) {
+                    throw new IndexOutOfBoundsException("Index " + index + " is out of bounds: [0, "
+                                                        + (array.length - 1) + "]");
+                }
+                if (values[i] != 0) {
+                    array[index] += values[i];
+                    nonZero = true;
+                }
+            }
+            return nonZero;
+        }
+    }
+
+    private static final HashMap<Long, LongArrayMultiStateCounterRavenwood> sInstances =
+            new HashMap<>();
+    private static long sNextId = 1;
+
+    public static long native_init(int stateCount, int arrayLength) {
+        LongArrayMultiStateCounterRavenwood instance = new LongArrayMultiStateCounterRavenwood(
+                stateCount, arrayLength);
+        long instanceId = sNextId++;
+        sInstances.put(instanceId, instance);
+        return instanceId;
+    }
+
+    private static LongArrayMultiStateCounterRavenwood getInstance(long instanceId) {
+        return sInstances.get(instanceId);
+    }
+
+    public static void native_setEnabled(long instanceId, boolean enabled,
+            long timestampMs) {
+        getInstance(instanceId).setEnabled(enabled, timestampMs);
+    }
+
+    public static int native_getStateCount(long instanceId) {
+        return getInstance(instanceId).mStateCount;
+    }
+
+    public static int native_getArrayLength(long instanceId) {
+        return getInstance(instanceId).mArrayLength;
+    }
+
+    public static void native_setValues(long instanceId, int state, long containerInstanceId) {
+        getInstance(instanceId).setValue(state,
+                LongArrayContainer_host.getInstance(containerInstanceId));
+    }
+
+    public static void native_updateValues(long instanceId, long containerInstanceId,
+            long timestampMs) {
+        getInstance(instanceId).updateValue(
+                LongArrayContainer_host.getInstance(containerInstanceId), timestampMs);
+    }
+
+    public static void native_setState(long instanceId, int state, long timestampMs) {
+        getInstance(instanceId).setState(state, timestampMs);
+    }
+
+    public static void native_incrementValues(long instanceId, long containerInstanceId,
+            long timestampMs) {
+        getInstance(instanceId).incrementValues(
+                LongArrayContainer_host.getInstance(containerInstanceId), timestampMs);
+    }
+
+    public static void native_getCounts(long instanceId, long containerInstanceId, int state) {
+        getInstance(instanceId).getValues(LongArrayContainer_host.getInstance(containerInstanceId),
+                state);
+    }
+
+    public static void native_reset(long instanceId) {
+        getInstance(instanceId).reset();
+    }
+
+    public static void native_writeToParcel(long instanceId, Parcel parcel, int flags) {
+        getInstance(instanceId).writeToParcel(parcel);
+    }
+
+    public static long native_initFromParcel(Parcel parcel) {
+        int stateCount = parcel.readInt();
+        if (stateCount < 0 || stateCount > 0xEFFF) {
+            throw new BadParcelableException("stateCount out of range");
+        }
+        // LongArrayMultiStateCounter.cpp uses AParcel, which throws on out-of-data.
+        if (parcel.dataPosition() >= parcel.dataSize()) {
+            throw new RuntimeException("Bad parcel");
+        }
+        int arrayLength = parcel.readInt();
+        if (parcel.dataPosition() >= parcel.dataSize()) {
+            throw new RuntimeException("Bad parcel");
+        }
+        long instanceId = native_init(stateCount, arrayLength);
+        getInstance(instanceId).initFromParcel(parcel);
+        if (parcel.dataPosition() > parcel.dataSize()) {
+            throw new RuntimeException("Bad parcel");
+        }
+        return instanceId;
+    }
+
+    public static String native_toString(long instanceId) {
+        return getInstance(instanceId).toString();
+    }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Parcel_host.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Parcel_host.java
index 3bcabcb..d63bff6 100644
--- a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Parcel_host.java
+++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Parcel_host.java
@@ -343,6 +343,28 @@
         p.mPos += length;
         p.updateSize();
     }
+    public static int nativeCompareData(long thisNativePtr, long otherNativePtr) {
+        var a = getInstance(thisNativePtr);
+        var b = getInstance(otherNativePtr);
+        if ((a.mSize == b.mSize) && Arrays.equals(a.mBuffer, b.mBuffer)) {
+            return 0;
+        } else {
+            return -1;
+        }
+    }
+    public static boolean nativeCompareDataInRange(
+            long ptrA, int offsetA, long ptrB, int offsetB, int length) {
+        var a = getInstance(ptrA);
+        var b = getInstance(ptrB);
+        if (offsetA < 0 || offsetA + length > a.mSize) {
+            throw new IllegalArgumentException();
+        }
+        if (offsetB < 0 || offsetB + length > b.mSize) {
+            throw new IllegalArgumentException();
+        }
+        return Arrays.equals(Arrays.copyOfRange(a.mBuffer, offsetA, offsetA + length),
+                Arrays.copyOfRange(b.mBuffer, offsetB, offsetB + length));
+    }
     public static void nativeAppendFrom(
             long thisNativePtr, long otherNativePtr, int srcOffset, int length) {
         var dst = getInstance(thisNativePtr);
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/libcore/util/HexEncoding.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/libcore/util/HexEncoding.java
new file mode 100644
index 0000000..cc2fb7b
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/libcore/util/HexEncoding.java
@@ -0,0 +1,240 @@
+/*
+ * 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 libcore.util;
+
+/**
+ * Hexadecimal encoding where each byte is represented by two hexadecimal digits.
+ * @hide
+ */
+public class HexEncoding {
+
+    private static final char[] LOWER_CASE_DIGITS = {
+            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
+    };
+
+    private static final char[] UPPER_CASE_DIGITS = {
+            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+    };
+
+    /** Hidden constructor to prevent instantiation. */
+    private HexEncoding() {}
+
+    /**
+     * Encodes the provided byte as a two-digit hexadecimal String value.
+     *
+     * @param  b byte to encode
+     * @param  upperCase {@code true} to use uppercase letters, {@code false}
+     *         for lowercase
+     * @return the encoded string
+     *
+     * @hide
+     */
+    public static String encodeToString(byte b, boolean upperCase) {
+        char[] digits = upperCase ? UPPER_CASE_DIGITS : LOWER_CASE_DIGITS;
+        char[] buf = new char[2]; // We always want two digits.
+        buf[0] = digits[(b >> 4) & 0xf];
+        buf[1] = digits[b & 0xf];
+        return new String(buf, 0, 2);
+    }
+
+    /**
+     * Encodes the provided data as a sequence of hexadecimal characters.
+     *
+     * @param  data byte array to encode
+     * @return the encoded data, using uppercase letters
+     *
+     * @hide
+     */
+    public static char[] encode(byte[] data) {
+        return encode(data, 0, data.length, true /* upperCase */);
+    }
+
+    /**
+     * Encodes the provided data as a sequence of hexadecimal characters.
+     *
+     * @param  data byte array to encode
+     * @param  upperCase {@code true} to use uppercase letters, {@code false}
+     *         for lowercase
+     * @return the encoded data
+     *
+     * @hide
+     */
+    public static char[] encode(byte[] data, boolean upperCase) {
+        return encode(data, 0, data.length, upperCase);
+    }
+
+    /**
+     * Encodes the provided data as a sequence of hexadecimal characters.
+     *
+     * @param  data byte array containing the data to encode
+     * @param  offset offset of the data to encode in the {@code data} array
+     * @param  len length of the data to encode in the {@code data} array
+     * @return the encoded data, using uppercase letters
+     *
+     * @hide
+     */
+    public static char[] encode(byte[] data, int offset, int len) {
+        return encode(data, offset, len, true /* upperCase */);
+    }
+
+    /**
+     * Encodes the provided data as a sequence of hexadecimal characters.
+     */
+    private static char[] encode(byte[] data, int offset, int len, boolean upperCase) {
+        char[] digits = upperCase ? UPPER_CASE_DIGITS : LOWER_CASE_DIGITS;
+        char[] result = new char[len * 2];
+        for (int i = 0; i < len; i++) {
+            byte b = data[offset + i];
+            int resultIndex = 2 * i;
+            result[resultIndex] = (digits[(b >> 4) & 0x0f]);
+            result[resultIndex + 1] = (digits[b & 0x0f]);
+        }
+
+        return result;
+    }
+
+    /**
+     * Encodes the provided data as a sequence of hexadecimal characters.
+     *
+     * @param  data byte array to encode
+     * @return the encoded data, using uppercase letters
+     *
+     * @hide
+     */
+    public static String encodeToString(byte[] data) {
+        return encodeToString(data, true /* upperCase */);
+    }
+
+    /**
+     * Encodes the provided data as a sequence of hexadecimal characters.
+     *
+     * @param  data byte array to encode.
+     * @param  upperCase {@code true} to use uppercase letters, {@code false}
+     *         for lowercase
+     * @return the encoded data
+     *
+     * @hide
+     */
+    public static String encodeToString(byte[] data, boolean upperCase) {
+        return new String(encode(data, upperCase));
+    }
+
+    /**
+     * Decodes the provided hexadecimal sequence. Odd-length inputs are not
+     * allowed.
+     *
+     * @param  encoded string of hexadecimal characters to decode. Letters
+     *         can be either uppercase or lowercase.
+     * @return the decoded data
+     * @throws IllegalArgumentException if the input is malformed
+     *
+     * @hide
+     */
+    public static byte[] decode(String encoded) throws IllegalArgumentException {
+        return decode(encoded.toCharArray());
+    }
+
+    /**
+     * Decodes the provided hexadecimal sequence.
+     *
+     * @param  encoded string of hexadecimal characters to decode. Letters
+     *         can be either uppercase or lowercase.
+     * @param  allowSingleChar If {@code true} odd-length inputs are allowed and
+     *         the first character is interpreted as the lower bits of the first
+     *         result byte. If {@code false} odd-length inputs are not allowed.
+     * @return the decoded data
+     * @throws IllegalArgumentException if the input is malformed
+     *
+     * @hide
+     */
+    public static byte[] decode(String encoded, boolean allowSingleChar)
+            throws IllegalArgumentException {
+        return decode(encoded.toCharArray(), allowSingleChar);
+    }
+
+    /**
+     * Decodes the provided hexadecimal sequence. Odd-length inputs are not
+     * allowed.
+     *
+     * @param  encoded char array of hexadecimal characters to decode. Letters
+     *         can be either uppercase or lowercase.
+     * @return the decoded data
+     * @throws IllegalArgumentException if the input is malformed
+     *
+     * @hide
+     */
+    public static byte[] decode(char[] encoded) throws IllegalArgumentException {
+        return decode(encoded, false);
+    }
+
+    /**
+     * Decodes the provided hexadecimal sequence.
+     *
+     * @param  encoded char array of hexadecimal characters to decode. Letters
+     *         can be either uppercase or lowercase.
+     * @param  allowSingleChar If {@code true} odd-length inputs are allowed and
+     *         the first character is interpreted as the lower bits of the first
+     *         result byte. If {@code false} odd-length inputs are not allowed.
+     * @return the decoded data
+     * @throws IllegalArgumentException if the input is malformed
+     *
+     * @hide
+     */
+    public static byte[] decode(char[] encoded, boolean allowSingleChar)
+            throws IllegalArgumentException {
+        int encodedLength = encoded.length;
+        int resultLengthBytes = (encodedLength + 1) / 2;
+        byte[] result = new byte[resultLengthBytes];
+
+        int resultOffset = 0;
+        int i = 0;
+        if (allowSingleChar) {
+            if ((encodedLength % 2) != 0) {
+                // Odd number of digits -- the first digit is the lower 4 bits of the first result
+                // byte.
+                result[resultOffset++] = (byte) toDigit(encoded, i);
+                i++;
+            }
+        } else {
+            if ((encodedLength % 2) != 0) {
+                throw new IllegalArgumentException("Invalid input length: " + encodedLength);
+            }
+        }
+
+        for (; i < encodedLength; i += 2) {
+            result[resultOffset++] = (byte) ((toDigit(encoded, i) << 4) | toDigit(encoded, i + 1));
+        }
+
+        return result;
+    }
+
+    private static int toDigit(char[] str, int offset) throws IllegalArgumentException {
+        // NOTE: that this isn't really a code point in the traditional sense, since we're
+        // just rejecting surrogate pairs outright.
+        int pseudoCodePoint = str[offset];
+
+        if ('0' <= pseudoCodePoint && pseudoCodePoint <= '9') {
+            return pseudoCodePoint - '0';
+        } else if ('a' <= pseudoCodePoint && pseudoCodePoint <= 'f') {
+            return 10 + (pseudoCodePoint - 'a');
+        } else if ('A' <= pseudoCodePoint && pseudoCodePoint <= 'F') {
+            return 10 + (pseudoCodePoint - 'A');
+        }
+
+        throw new IllegalArgumentException("Illegal char: " + str[offset] + " at offset " + offset);
+    }
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AndroidHeuristicsFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AndroidHeuristicsFilter.kt
index 8354d98..8ca4732 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AndroidHeuristicsFilter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AndroidHeuristicsFilter.kt
@@ -23,12 +23,16 @@
 class AndroidHeuristicsFilter(
         private val classes: ClassNodes,
         val aidlPolicy: FilterPolicyWithReason?,
+        val featureFlagsPolicy: FilterPolicyWithReason?,
         fallback: OutputFilter
 ) : DelegatingFilter(fallback) {
     override fun getPolicyForClass(className: String): FilterPolicyWithReason {
         if (aidlPolicy != null && classes.isAidlClass(className)) {
             return aidlPolicy
         }
+        if (featureFlagsPolicy != null && classes.isFeatureFlagsClass(className)) {
+            return featureFlagsPolicy
+        }
         return super.getPolicyForClass(className)
     }
 }
@@ -40,4 +44,16 @@
     return hasClass(className) &&
             hasClass("$className\$Stub") &&
             hasClass("$className\$Stub\$Proxy")
-}
\ No newline at end of file
+}
+
+/**
+ * @return if a given class "seems like" an feature flags class.
+ */
+private fun ClassNodes.isFeatureFlagsClass(className: String): Boolean {
+    // Matches template classes defined here:
+    // https://cs.android.com/android/platform/superproject/+/master:build/make/tools/aconfig/templates/
+    return className.endsWith("/Flags")
+            || className.endsWith("/FeatureFlags")
+            || className.endsWith("/FeatureFlagsImpl")
+            || className.endsWith("/FakeFeatureFlagsImpl");
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt
index b4354ba..d38a6e3 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt
@@ -62,7 +62,8 @@
 
         var lineNo = 0
 
-        var aidlPolicy: FilterPolicy? = null
+        var aidlPolicy: FilterPolicyWithReason? = null
+        var featureFlagsPolicy: FilterPolicyWithReason? = null
 
         try {
             BufferedReader(FileReader(filename)).use { reader ->
@@ -130,7 +131,15 @@
                                             throw ParseException(
                                                     "Policy for AIDL classes already defined")
                                         }
-                                        aidlPolicy = policy
+                                        aidlPolicy = policy.withReason("$FILTER_REASON (AIDL)")
+                                    }
+                                    SpecialClass.FeatureFlags -> {
+                                        if (featureFlagsPolicy != null) {
+                                            throw ParseException(
+                                                    "Policy for feature flags already defined")
+                                        }
+                                        featureFlagsPolicy =
+                                                policy.withReason("$FILTER_REASON (feature flags)")
                                     }
                                 }
                             }
@@ -196,10 +205,10 @@
         }
 
         var ret: OutputFilter = imf
-        aidlPolicy?.let { policy ->
+        if (aidlPolicy != null || featureFlagsPolicy != null) {
             log.d("AndroidHeuristicsFilter enabled")
             ret = AndroidHeuristicsFilter(
-                    classes, policy.withReason("$FILTER_REASON (AIDL)"), imf)
+                    classes, aidlPolicy, featureFlagsPolicy, imf)
         }
         return ret
     }
@@ -208,6 +217,7 @@
 private enum class SpecialClass {
     NotSpecial,
     Aidl,
+    FeatureFlags,
 }
 
 private fun resolveSpecialClass(className: String): SpecialClass {
@@ -216,6 +226,7 @@
     }
     when (className.lowercase()) {
         ":aidl" -> return SpecialClass.Aidl
+        ":feature_flags" -> return SpecialClass.FeatureFlags
     }
     throw ParseException("Invalid special class name \"$className\"")
 }